From 3438e5d3ddf8444f0e31009ffbe8237ef3752c22 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Sun, 24 Nov 2013 14:21:13 +0000 Subject: move cryptopp into lib --- lib/cryptopp/Doxyfile | 1634 +++++++++++++++++ lib/cryptopp/License.txt | 51 + lib/cryptopp/Readme.txt | 452 +++++ lib/cryptopp/adler32.cpp | 77 + lib/cryptopp/adler32.h | 28 + lib/cryptopp/aes.h | 16 + lib/cryptopp/algebra.cpp | 340 ++++ lib/cryptopp/algebra.h | 285 +++ lib/cryptopp/algparam.cpp | 75 + lib/cryptopp/algparam.h | 398 +++++ lib/cryptopp/argnames.h | 81 + lib/cryptopp/asn.cpp | 597 +++++++ lib/cryptopp/asn.h | 369 ++++ lib/cryptopp/authenc.cpp | 180 ++ lib/cryptopp/authenc.h | 49 + lib/cryptopp/base32.cpp | 39 + lib/cryptopp/base32.h | 38 + lib/cryptopp/base64.cpp | 42 + lib/cryptopp/base64.h | 36 + lib/cryptopp/basecode.cpp | 238 +++ lib/cryptopp/basecode.h | 86 + lib/cryptopp/cbcmac.cpp | 62 + lib/cryptopp/cbcmac.h | 50 + lib/cryptopp/ccm.cpp | 140 ++ lib/cryptopp/ccm.h | 101 ++ lib/cryptopp/channels.cpp | 309 ++++ lib/cryptopp/channels.h | 123 ++ lib/cryptopp/cmac.cpp | 122 ++ lib/cryptopp/cmac.h | 52 + lib/cryptopp/config.h | 462 +++++ lib/cryptopp/cpu.cpp | 199 +++ lib/cryptopp/cpu.h | 345 ++++ lib/cryptopp/crc.cpp | 160 ++ lib/cryptopp/crc.h | 42 + lib/cryptopp/cryptlib.cpp | 828 +++++++++ lib/cryptopp/cryptlib.h | 1655 ++++++++++++++++++ lib/cryptopp/default.cpp | 258 +++ lib/cryptopp/default.h | 104 ++ lib/cryptopp/des.cpp | 449 +++++ lib/cryptopp/des.h | 144 ++ lib/cryptopp/dessp.cpp | 95 + lib/cryptopp/dh.cpp | 19 + lib/cryptopp/dh.h | 99 ++ lib/cryptopp/dh2.cpp | 22 + lib/cryptopp/dh2.h | 58 + lib/cryptopp/dll.cpp | 146 ++ lib/cryptopp/dll.h | 70 + lib/cryptopp/dmac.h | 93 + lib/cryptopp/dsa.cpp | 63 + lib/cryptopp/dsa.h | 35 + lib/cryptopp/eax.cpp | 59 + lib/cryptopp/eax.h | 91 + lib/cryptopp/ec2n.cpp | 292 ++++ lib/cryptopp/ec2n.h | 113 ++ lib/cryptopp/eccrypto.cpp | 694 ++++++++ lib/cryptopp/eccrypto.h | 280 +++ lib/cryptopp/ecp.cpp | 473 +++++ lib/cryptopp/ecp.h | 126 ++ lib/cryptopp/elgamal.cpp | 17 + lib/cryptopp/elgamal.h | 121 ++ lib/cryptopp/emsa2.cpp | 34 + lib/cryptopp/emsa2.h | 86 + lib/cryptopp/eprecomp.cpp | 112 ++ lib/cryptopp/eprecomp.h | 75 + lib/cryptopp/esign.cpp | 210 +++ lib/cryptopp/esign.h | 128 ++ lib/cryptopp/factory.h | 136 ++ lib/cryptopp/files.cpp | 259 +++ lib/cryptopp/files.h | 112 ++ lib/cryptopp/filters.cpp | 1120 ++++++++++++ lib/cryptopp/filters.h | 810 +++++++++ lib/cryptopp/fips140.cpp | 84 + lib/cryptopp/fips140.h | 59 + lib/cryptopp/fltrimpl.h | 67 + lib/cryptopp/gcm.cpp | 828 +++++++++ lib/cryptopp/gcm.h | 106 ++ lib/cryptopp/gf256.cpp | 34 + lib/cryptopp/gf256.h | 66 + lib/cryptopp/gf2_32.cpp | 99 ++ lib/cryptopp/gf2_32.h | 66 + lib/cryptopp/gf2n.cpp | 882 ++++++++++ lib/cryptopp/gf2n.h | 369 ++++ lib/cryptopp/gfpcrypt.cpp | 273 +++ lib/cryptopp/gfpcrypt.h | 528 ++++++ lib/cryptopp/gzip.h | 65 + lib/cryptopp/hex.cpp | 44 + lib/cryptopp/hex.h | 36 + lib/cryptopp/hmac.cpp | 86 + lib/cryptopp/hmac.h | 61 + lib/cryptopp/hrtimer.cpp | 138 ++ lib/cryptopp/hrtimer.h | 61 + lib/cryptopp/integer.cpp | 4235 +++++++++++++++++++++++++++++++++++++++++++++ lib/cryptopp/integer.h | 420 +++++ lib/cryptopp/iterhash.cpp | 160 ++ lib/cryptopp/iterhash.h | 106 ++ lib/cryptopp/lubyrack.h | 141 ++ lib/cryptopp/luc.cpp | 210 +++ lib/cryptopp/luc.h | 236 +++ lib/cryptopp/md2.cpp | 120 ++ lib/cryptopp/md2.h | 46 + lib/cryptopp/md4.cpp | 110 ++ lib/cryptopp/md4.h | 35 + lib/cryptopp/md5.cpp | 118 ++ lib/cryptopp/md5.h | 33 + lib/cryptopp/mdc.h | 72 + lib/cryptopp/misc.cpp | 189 ++ lib/cryptopp/misc.h | 1282 ++++++++++++++ lib/cryptopp/modarith.h | 158 ++ lib/cryptopp/modes.cpp | 245 +++ lib/cryptopp/modes.h | 422 +++++ lib/cryptopp/modexppc.h | 34 + lib/cryptopp/mqueue.cpp | 174 ++ lib/cryptopp/mqueue.h | 100 ++ lib/cryptopp/mqv.cpp | 13 + lib/cryptopp/mqv.h | 141 ++ lib/cryptopp/nbtheory.cpp | 1123 ++++++++++++ lib/cryptopp/nbtheory.h | 131 ++ lib/cryptopp/network.cpp | 550 ++++++ lib/cryptopp/network.h | 235 +++ lib/cryptopp/nr.h | 6 + lib/cryptopp/oaep.cpp | 97 ++ lib/cryptopp/oaep.h | 42 + lib/cryptopp/oids.h | 123 ++ lib/cryptopp/osrng.cpp | 192 ++ lib/cryptopp/osrng.h | 156 ++ lib/cryptopp/pch.cpp | 1 + lib/cryptopp/pch.h | 21 + lib/cryptopp/pkcspad.cpp | 124 ++ lib/cryptopp/pkcspad.h | 94 + lib/cryptopp/polynomi.cpp | 577 ++++++ lib/cryptopp/polynomi.h | 459 +++++ lib/cryptopp/pssr.cpp | 145 ++ lib/cryptopp/pssr.h | 66 + lib/cryptopp/pubkey.cpp | 165 ++ lib/cryptopp/pubkey.h | 1678 ++++++++++++++++++ lib/cryptopp/pwdbased.h | 214 +++ lib/cryptopp/queue.cpp | 565 ++++++ lib/cryptopp/queue.h | 144 ++ lib/cryptopp/rabin.cpp | 221 +++ lib/cryptopp/rabin.h | 107 ++ lib/cryptopp/randpool.cpp | 63 + lib/cryptopp/randpool.h | 33 + lib/cryptopp/rdtables.cpp | 172 ++ lib/cryptopp/resource.h | 15 + lib/cryptopp/rijndael.cpp | 1261 ++++++++++++++ lib/cryptopp/rijndael.h | 68 + lib/cryptopp/rng.cpp | 155 ++ lib/cryptopp/rng.h | 77 + lib/cryptopp/rsa.cpp | 304 ++++ lib/cryptopp/rsa.h | 174 ++ lib/cryptopp/rw.cpp | 196 +++ lib/cryptopp/rw.h | 102 ++ lib/cryptopp/safer.cpp | 153 ++ lib/cryptopp/safer.h | 86 + lib/cryptopp/seal.cpp | 213 +++ lib/cryptopp/seal.h | 44 + lib/cryptopp/secblock.h | 467 +++++ lib/cryptopp/seckey.h | 221 +++ lib/cryptopp/seed.cpp | 104 ++ lib/cryptopp/seed.h | 38 + lib/cryptopp/sha.cpp | 900 ++++++++++ lib/cryptopp/sha.h | 63 + lib/cryptopp/shacal2.cpp | 140 ++ lib/cryptopp/shacal2.h | 54 + lib/cryptopp/simple.cpp | 14 + lib/cryptopp/simple.h | 209 +++ lib/cryptopp/smartptr.h | 223 +++ lib/cryptopp/socketft.cpp | 531 ++++++ lib/cryptopp/socketft.h | 224 +++ lib/cryptopp/square.cpp | 177 ++ lib/cryptopp/square.h | 58 + lib/cryptopp/squaretb.cpp | 582 +++++++ lib/cryptopp/stdcpp.h | 41 + lib/cryptopp/strciphr.cpp | 252 +++ lib/cryptopp/strciphr.h | 306 ++++ lib/cryptopp/tea.cpp | 159 ++ lib/cryptopp/tea.h | 132 ++ lib/cryptopp/tiger.cpp | 265 +++ lib/cryptopp/tiger.h | 24 + lib/cryptopp/tigertab.cpp | 525 ++++++ lib/cryptopp/trdlocal.cpp | 73 + lib/cryptopp/trdlocal.h | 44 + lib/cryptopp/trunhash.h | 48 + lib/cryptopp/ttmac.cpp | 338 ++++ lib/cryptopp/ttmac.h | 38 + lib/cryptopp/validate.h | 81 + lib/cryptopp/vmac.cpp | 832 +++++++++ lib/cryptopp/vmac.h | 68 + lib/cryptopp/wait.cpp | 397 +++++ lib/cryptopp/wait.h | 208 +++ lib/cryptopp/winpipes.cpp | 205 +++ lib/cryptopp/winpipes.h | 142 ++ lib/cryptopp/words.h | 103 ++ 193 files changed, 48154 insertions(+) create mode 100644 lib/cryptopp/Doxyfile create mode 100644 lib/cryptopp/License.txt create mode 100644 lib/cryptopp/Readme.txt create mode 100644 lib/cryptopp/adler32.cpp create mode 100644 lib/cryptopp/adler32.h create mode 100644 lib/cryptopp/aes.h create mode 100644 lib/cryptopp/algebra.cpp create mode 100644 lib/cryptopp/algebra.h create mode 100644 lib/cryptopp/algparam.cpp create mode 100644 lib/cryptopp/algparam.h create mode 100644 lib/cryptopp/argnames.h create mode 100644 lib/cryptopp/asn.cpp create mode 100644 lib/cryptopp/asn.h create mode 100644 lib/cryptopp/authenc.cpp create mode 100644 lib/cryptopp/authenc.h create mode 100644 lib/cryptopp/base32.cpp create mode 100644 lib/cryptopp/base32.h create mode 100644 lib/cryptopp/base64.cpp create mode 100644 lib/cryptopp/base64.h create mode 100644 lib/cryptopp/basecode.cpp create mode 100644 lib/cryptopp/basecode.h create mode 100644 lib/cryptopp/cbcmac.cpp create mode 100644 lib/cryptopp/cbcmac.h create mode 100644 lib/cryptopp/ccm.cpp create mode 100644 lib/cryptopp/ccm.h create mode 100644 lib/cryptopp/channels.cpp create mode 100644 lib/cryptopp/channels.h create mode 100644 lib/cryptopp/cmac.cpp create mode 100644 lib/cryptopp/cmac.h create mode 100644 lib/cryptopp/config.h create mode 100644 lib/cryptopp/cpu.cpp create mode 100644 lib/cryptopp/cpu.h create mode 100644 lib/cryptopp/crc.cpp create mode 100644 lib/cryptopp/crc.h create mode 100644 lib/cryptopp/cryptlib.cpp create mode 100644 lib/cryptopp/cryptlib.h create mode 100644 lib/cryptopp/default.cpp create mode 100644 lib/cryptopp/default.h create mode 100644 lib/cryptopp/des.cpp create mode 100644 lib/cryptopp/des.h create mode 100644 lib/cryptopp/dessp.cpp create mode 100644 lib/cryptopp/dh.cpp create mode 100644 lib/cryptopp/dh.h create mode 100644 lib/cryptopp/dh2.cpp create mode 100644 lib/cryptopp/dh2.h create mode 100644 lib/cryptopp/dll.cpp create mode 100644 lib/cryptopp/dll.h create mode 100644 lib/cryptopp/dmac.h create mode 100644 lib/cryptopp/dsa.cpp create mode 100644 lib/cryptopp/dsa.h create mode 100644 lib/cryptopp/eax.cpp create mode 100644 lib/cryptopp/eax.h create mode 100644 lib/cryptopp/ec2n.cpp create mode 100644 lib/cryptopp/ec2n.h create mode 100644 lib/cryptopp/eccrypto.cpp create mode 100644 lib/cryptopp/eccrypto.h create mode 100644 lib/cryptopp/ecp.cpp create mode 100644 lib/cryptopp/ecp.h create mode 100644 lib/cryptopp/elgamal.cpp create mode 100644 lib/cryptopp/elgamal.h create mode 100644 lib/cryptopp/emsa2.cpp create mode 100644 lib/cryptopp/emsa2.h create mode 100644 lib/cryptopp/eprecomp.cpp create mode 100644 lib/cryptopp/eprecomp.h create mode 100644 lib/cryptopp/esign.cpp create mode 100644 lib/cryptopp/esign.h create mode 100644 lib/cryptopp/factory.h create mode 100644 lib/cryptopp/files.cpp create mode 100644 lib/cryptopp/files.h create mode 100644 lib/cryptopp/filters.cpp create mode 100644 lib/cryptopp/filters.h create mode 100644 lib/cryptopp/fips140.cpp create mode 100644 lib/cryptopp/fips140.h create mode 100644 lib/cryptopp/fltrimpl.h create mode 100644 lib/cryptopp/gcm.cpp create mode 100644 lib/cryptopp/gcm.h create mode 100644 lib/cryptopp/gf256.cpp create mode 100644 lib/cryptopp/gf256.h create mode 100644 lib/cryptopp/gf2_32.cpp create mode 100644 lib/cryptopp/gf2_32.h create mode 100644 lib/cryptopp/gf2n.cpp create mode 100644 lib/cryptopp/gf2n.h create mode 100644 lib/cryptopp/gfpcrypt.cpp create mode 100644 lib/cryptopp/gfpcrypt.h create mode 100644 lib/cryptopp/gzip.h create mode 100644 lib/cryptopp/hex.cpp create mode 100644 lib/cryptopp/hex.h create mode 100644 lib/cryptopp/hmac.cpp create mode 100644 lib/cryptopp/hmac.h create mode 100644 lib/cryptopp/hrtimer.cpp create mode 100644 lib/cryptopp/hrtimer.h create mode 100644 lib/cryptopp/integer.cpp create mode 100644 lib/cryptopp/integer.h create mode 100644 lib/cryptopp/iterhash.cpp create mode 100644 lib/cryptopp/iterhash.h create mode 100644 lib/cryptopp/lubyrack.h create mode 100644 lib/cryptopp/luc.cpp create mode 100644 lib/cryptopp/luc.h create mode 100644 lib/cryptopp/md2.cpp create mode 100644 lib/cryptopp/md2.h create mode 100644 lib/cryptopp/md4.cpp create mode 100644 lib/cryptopp/md4.h create mode 100644 lib/cryptopp/md5.cpp create mode 100644 lib/cryptopp/md5.h create mode 100644 lib/cryptopp/mdc.h create mode 100644 lib/cryptopp/misc.cpp create mode 100644 lib/cryptopp/misc.h create mode 100644 lib/cryptopp/modarith.h create mode 100644 lib/cryptopp/modes.cpp create mode 100644 lib/cryptopp/modes.h create mode 100644 lib/cryptopp/modexppc.h create mode 100644 lib/cryptopp/mqueue.cpp create mode 100644 lib/cryptopp/mqueue.h create mode 100644 lib/cryptopp/mqv.cpp create mode 100644 lib/cryptopp/mqv.h create mode 100644 lib/cryptopp/nbtheory.cpp create mode 100644 lib/cryptopp/nbtheory.h create mode 100644 lib/cryptopp/network.cpp create mode 100644 lib/cryptopp/network.h create mode 100644 lib/cryptopp/nr.h create mode 100644 lib/cryptopp/oaep.cpp create mode 100644 lib/cryptopp/oaep.h create mode 100644 lib/cryptopp/oids.h create mode 100644 lib/cryptopp/osrng.cpp create mode 100644 lib/cryptopp/osrng.h create mode 100644 lib/cryptopp/pch.cpp create mode 100644 lib/cryptopp/pch.h create mode 100644 lib/cryptopp/pkcspad.cpp create mode 100644 lib/cryptopp/pkcspad.h create mode 100644 lib/cryptopp/polynomi.cpp create mode 100644 lib/cryptopp/polynomi.h create mode 100644 lib/cryptopp/pssr.cpp create mode 100644 lib/cryptopp/pssr.h create mode 100644 lib/cryptopp/pubkey.cpp create mode 100644 lib/cryptopp/pubkey.h create mode 100644 lib/cryptopp/pwdbased.h create mode 100644 lib/cryptopp/queue.cpp create mode 100644 lib/cryptopp/queue.h create mode 100644 lib/cryptopp/rabin.cpp create mode 100644 lib/cryptopp/rabin.h create mode 100644 lib/cryptopp/randpool.cpp create mode 100644 lib/cryptopp/randpool.h create mode 100644 lib/cryptopp/rdtables.cpp create mode 100644 lib/cryptopp/resource.h create mode 100644 lib/cryptopp/rijndael.cpp create mode 100644 lib/cryptopp/rijndael.h create mode 100644 lib/cryptopp/rng.cpp create mode 100644 lib/cryptopp/rng.h create mode 100644 lib/cryptopp/rsa.cpp create mode 100644 lib/cryptopp/rsa.h create mode 100644 lib/cryptopp/rw.cpp create mode 100644 lib/cryptopp/rw.h create mode 100644 lib/cryptopp/safer.cpp create mode 100644 lib/cryptopp/safer.h create mode 100644 lib/cryptopp/seal.cpp create mode 100644 lib/cryptopp/seal.h create mode 100644 lib/cryptopp/secblock.h create mode 100644 lib/cryptopp/seckey.h create mode 100644 lib/cryptopp/seed.cpp create mode 100644 lib/cryptopp/seed.h create mode 100644 lib/cryptopp/sha.cpp create mode 100644 lib/cryptopp/sha.h create mode 100644 lib/cryptopp/shacal2.cpp create mode 100644 lib/cryptopp/shacal2.h create mode 100644 lib/cryptopp/simple.cpp create mode 100644 lib/cryptopp/simple.h create mode 100644 lib/cryptopp/smartptr.h create mode 100644 lib/cryptopp/socketft.cpp create mode 100644 lib/cryptopp/socketft.h create mode 100644 lib/cryptopp/square.cpp create mode 100644 lib/cryptopp/square.h create mode 100644 lib/cryptopp/squaretb.cpp create mode 100644 lib/cryptopp/stdcpp.h create mode 100644 lib/cryptopp/strciphr.cpp create mode 100644 lib/cryptopp/strciphr.h create mode 100644 lib/cryptopp/tea.cpp create mode 100644 lib/cryptopp/tea.h create mode 100644 lib/cryptopp/tiger.cpp create mode 100644 lib/cryptopp/tiger.h create mode 100644 lib/cryptopp/tigertab.cpp create mode 100644 lib/cryptopp/trdlocal.cpp create mode 100644 lib/cryptopp/trdlocal.h create mode 100644 lib/cryptopp/trunhash.h create mode 100644 lib/cryptopp/ttmac.cpp create mode 100644 lib/cryptopp/ttmac.h create mode 100644 lib/cryptopp/validate.h create mode 100644 lib/cryptopp/vmac.cpp create mode 100644 lib/cryptopp/vmac.h create mode 100644 lib/cryptopp/wait.cpp create mode 100644 lib/cryptopp/wait.h create mode 100644 lib/cryptopp/winpipes.cpp create mode 100644 lib/cryptopp/winpipes.h create mode 100644 lib/cryptopp/words.h (limited to 'lib') 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 , where is the value of +# the FILE_VERSION_FILTER tag, and 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 , where +# is the value of the INPUT_FILTER tag, and 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 +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +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 to + AutoSeededX917RNG + - 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) + +//! AES 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 + +NAMESPACE_BEGIN(CryptoPP) + +template const T& AbstractGroup::Double(const Element &a) const +{ + return this->Add(a, a); +} + +template const T& AbstractGroup::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 T& AbstractGroup::Accumulate(Element &a, const Element &b) const +{ + return a = this->Add(a, b); +} + +template T& AbstractGroup::Reduce(Element &a, const Element &b) const +{ + return a = this->Subtract(a, b); +} + +template const T& AbstractRing::Square(const Element &a) const +{ + return this->Multiply(a, a); +} + +template const T& AbstractRing::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 const T& AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const +{ + Element q; + this->DivisionAlgorithm(result, q, a, b); + return result; +} + +template const T& AbstractEuclideanDomain::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 const typename QuotientRing::Element& QuotientRing::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 T AbstractGroup::ScalarMultiply(const Element &base, const Integer &exponent) const +{ + Element result; + this->SimultaneousMultiply(&result, base, &exponent, 1); + return result; +} + +template T AbstractGroup::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< 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=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<Double(result); + if (power1 || power2) + Accumulate(result, powerTable[(power2<Double(result); + power1 = power2 = 0; + } + } + return result; +} + +template Element GeneralCascadeMultiplication(const AbstractGroup &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 +void AbstractGroup::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const +{ + std::vector > buckets(expCount); + std::vector exponents; + exponents.reserve(expCount); + unsigned int i; + + for (i=0; iNotNegative()); + 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 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 T AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const +{ + Element result; + SimultaneousExponentiate(&result, base, &exponent, 1); + return result; +} + +template T AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(x, e1, y, e2); +} + +template Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end) +{ + return GeneralCascadeMultiplication(ring.MultiplicativeGroup(), begin, end); +} + +template +void AbstractRing::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const +{ + MultiplicativeGroup().AbstractGroup::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 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 CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup +{ +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& MultiplicativeGroup() const + {return m_mg;} + +private: + class MultiplicativeGroupT : public AbstractGroup + { + public: + const AbstractRing& 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 *m_pRing; + }; + + MultiplicativeGroupT m_mg; +}; + +// ******************************************************** + +//! Base and Exponent +template +struct BaseAndExponent +{ +public: + BaseAndExponent() {} + BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {} + bool operator<(const BaseAndExponent &rhs) const {return exponent < rhs.exponent;} + T base; + E exponent; +}; + +// VC60 workaround: incomplete member template support +template + Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end); +template + Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end); + +// ******************************************************** + +//! Abstract Euclidean Domain +template class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing +{ +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 EuclideanDomainOf : public AbstractEuclideanDomain +{ +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 &rhs) const + {return true;} + +private: + mutable Element result; +}; + +//! Quotient Ring +template class QuotientRing : public AbstractRing +{ +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 &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(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(x).m_next.release()); +} + +AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x) +{ + m_next.reset(const_cast(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 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 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(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(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 + GetValueHelperClass & operator()(const char *name, const R & (T::*pm)() const) + { + if (m_getValueNames) + (*reinterpret_cast(m_pValue) += name) += ";"; + if (!m_found && strcmp(name, m_name) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType); + *reinterpret_cast(m_pValue) = (m_pObject->*pm)(); + m_found = true; + } + return *this; + } + + GetValueHelperClass &Assignable() + { +#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason + if (m_getValueNames) + ((*reinterpret_cast(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(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 +GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL) +{ + return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); +} + +template +GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL) +{ + return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); +} + +// ******************************************************** + +template +R Hack_DefaultValueFromConstReferenceType(const R &) +{ + return R(); +} + +template +bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value) +{ + return source.GetValue(name, const_cast(value)); +} + +template +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 + 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(*(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 + 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(*(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(*(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 +AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL) +{ + return AssignFromHelperClass(pObject, source); +} + +template +AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source) +{ + return AssignFromHelperClass(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(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 m_next; +}; + +template +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(pValue) = m_value; + } + } + + void MoveInto(void *buffer) const + { + AlgorithmParametersTemplate* p = new(buffer) AlgorithmParametersTemplate(*this); + } + +protected: + T m_value; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; + +class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs +{ +public: + AlgorithmParameters(); + +#ifdef __BORLANDC__ + template + AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true) + : m_next(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)) + , m_defaultThrowIfNotUsed(throwIfNotUsed) + { + } +#endif + + AlgorithmParameters(const AlgorithmParameters &x); + + AlgorithmParameters & operator=(const AlgorithmParameters &x); + + template + AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed) + { + member_ptr p(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)); + p->m_next.reset(m_next.release()); + m_next.reset(p.release()); + m_defaultThrowIfNotUsed = throwIfNotUsed; + return *this; + } + + template + 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 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 +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 +#include + +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 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(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(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 + +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 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 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 ¶meters) {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 ASNOptional : public member_ptr +{ +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 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 +{ +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 +{ +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 +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)-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::max conflicts with MFC max macro +// CW41 workaround: std::numeric_limits::max causes a template error +template +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 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 ¶ms) +{ + 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 ¶ms); + 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(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 ¶ms) =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 ¶meters) +{ + 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 ¶meters) +{ + 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 ¶meters); +}; + +//! 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 ¶meters); + +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 ¶meters) +{ + 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 ¶meters); +}; + +//! Base64 Decoder Class +class Base64Decoder : public BaseN_Decoder +{ +public: + Base64Decoder(BufferedTransformation *attachment = NULL) + : BaseN_Decoder(GetDecodingLookupArray(), 6, attachment) {} + + void IsolatedInitialize(const NameValuePairs ¶meters) {} + +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 + +NAMESPACE_BEGIN(CryptoPP) + +void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + 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 0) + ++m_bytePos; + + int i; + for (i=0; i 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 ¶meters) +{ + 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 +{ +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 ¶meters); + 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 +{ +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 ¶meters); + 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 +{ +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 ¶meters); + 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 ¶ms) +{ + 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 ¶ms); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int DigestSize() const {return const_cast(this)->AccessCipher().BlockSize();} + +protected: + virtual BlockCipher & AccessCipher() =0; + +private: + void ProcessBuf(); + SecByteBlock m_reg; + unsigned int m_counter; +}; + +//! CBC-MAC +/*! 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 CBC_MAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs +{ +public: + CBC_MAC() {} + CBC_MAC(const byte *key, size_t length=SameKeyLengthAs::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 ¶ms) +{ + 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(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(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(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength); + m_bufferedDataLength = 6; + } + else + { + m_buffer[0] = 0xff; + m_buffer[1] = 0xff; + PutWord(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 ¶ms); + 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(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 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; +}; + +/// CCM +template +struct CCM : public AuthenticatedSymmetricCipherDocumentation +{ + typedef CCM_Final Encryption; + typedef CCM_Final 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 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 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 ¶meters/* =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(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 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 +#include + +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 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 RouteList; + typedef std::list DefaultRouteList; + + RouteList m_routes; + DefaultRouteList m_defaultRoutes; + unsigned int m_nCurrentMessage; +}; +#endif + +class ChannelSwitchTypedefs +{ +public: + typedef std::pair Route; + typedef std::multimap RouteMap; + + typedef std::pair > DefaultRoute; + typedef std::list 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, 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 ¶meters=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 ¶ms) +{ + 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 ¶ms); + 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(this)->AccessCipher();} + virtual BlockCipher & AccessCipher() =0; + + void ProcessBuf(); + SecByteBlock m_reg; + unsigned int m_counter; +}; + +/// CMAC +/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */ +template +class CMAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs +{ +public: + CMAC() {} + CMAC(const byte *key, size_t length=SameKeyLengthAs::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 + #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 + +#ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY +#include +#include +#endif + +#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE +#include +#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 +#endif + +#if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE +#if !defined(__GNUC__) || defined(__SSSE3__) || defined(__INTEL_COMPILER) +#include +#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 +#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 +#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(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> 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 + +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 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 ¶ms) +{ + 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 ¶ms, 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(inBlocks)[blockSize-1]++; + inBlocks += inIncrement; + outBlocks += outIncrement; + xorBlocks += xorIncrement; + length -= blockSize; + } + + return length; +} + +unsigned int BlockTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +unsigned int StreamTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +unsigned int HashTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +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 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 ¶meters, 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 +{ +public: + PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) + : 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 ¶meters) const +{ + return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters); +} + +class PK_DefaultDecryptionFilter : public Unflushable +{ +public: + PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) + : 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 ¶meters) 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 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 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 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 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 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 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 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 +
+
Abstract Base Classes
+ cryptlib.h +
Authenticated Encryption
+ AuthenticatedSymmetricCipherDocumentation +
Symmetric Ciphers
+ SymmetricCipherDocumentation +
Hash Functions
+ SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, Whirlpool, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, Weak1::MD2, Weak1::MD4, Weak1::MD5 +
Non-Cryptographic Checksums
+ CRC32, Adler32 +
Message Authentication Codes
+ VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM (GMAC) +
Random Number Generators
+ NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, #DefaultAutoSeededRNG +
Password-based Cryptography
+ PasswordBasedKeyDerivationFunction +
Public Key Cryptosystems
+ DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES +
Public Key Signature Schemes
+ DSA2, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, RabinSS, RWSS, ESIGN +
Key Agreement
+ #DH, DH2, #MQV, ECDH, ECMQV, XTR_DH +
Algebraic Structures
+ Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver, + ModularArithmetic, MontgomeryRepresentation, GFP2_ONB, + GF2NP, GF256, GF2_32, EC2N, ECP +
Secret Sharing and Information Dispersal
+ SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery +
Compression
+ Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor +
Input Source Classes
+ StringSource, #ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource +
Output Sink Classes
+ StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink +
Filter Wrappers
+ StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter +
Binary to Text Encoders and Decoders
+ HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder +
Wrappers for OS features
+ Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer +
FIPS 140 related
+ fips140.h +
+ +In the DLL version of Crypto++, only the following implementation class are available. +
+
Block Ciphers
+ AES, DES_EDE2, DES_EDE3, SKIPJACK +
Cipher Modes (replace template parameter BC with one of the block ciphers above)
+ ECB_Mode\, CTR_Mode\, CBC_Mode\, CFB_FIPS_Mode\, OFB_Mode\, GCM\ +
Hash Functions
+ SHA1, SHA224, SHA256, SHA384, SHA512 +
Public Key Signature Schemes (replace template parameter H with one of the hash functions above)
+ RSASS\, RSASS\, RSASS_ISO\, RWSS\, DSA, ECDSA\, ECDSA\ +
Message Authentication Codes (replace template parameter H with one of the hash functions above)
+ HMAC\, CBC_MAC\, CBC_MAC\, GCM\ +
Random Number Generators
+ #DefaultAutoSeededRNG (AutoSeededX917RNG\) +
Key Agreement
+ #DH +
Public Key Cryptosystems
+ RSAES\ \> +
+ +

This reference manual is a work in progress. Some classes are still lacking detailed descriptions. +

Click here to download a zip archive containing this manual. +

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 +struct EnumToType +{ + static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;} +}; + +enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1}; +typedef EnumToType LittleEndian; +typedef EnumToType 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 + 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 + 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 + 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 + 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 + 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 ¶ms = 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 ¶ms) =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 ¶ms, 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(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 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 ¶meters) {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 ¶meters=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(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 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 ¶ms = 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(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(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(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 ¶meters = 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 ¶meters = 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 ¶meters = 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 ¶meters = g_nullNameValuePairs) const; + + //! decrypt a fixed size ciphertext + DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs ¶meters = 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 ¶meters) =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 +#include + +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> 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> 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 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(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 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::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::Decryption m_cipher; + member_ptr 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 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 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 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 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";} +}; + +/// DES +/*! 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, public RawDES + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + 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; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";} +}; + +/// DES-EDE2 +class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + RawDES m_des1, m_des2; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";} +}; + +/// DES-EDE3 +class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + RawDES m_des1, m_des2, m_des3; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> +{ + static const char *StaticAlgorithmName() {return "DES-XEX3";} +}; + +/// DES-XEX3, AKA DESX +class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + FixedSizeSecBlock 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 m_des; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal 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 DH_Domain : public DL_SimpleKeyAgreementDomainBase +{ + typedef DL_SimpleKeyAgreementDomainBase Base; + +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef DL_KeyAgreementAlgorithm_DH DH_Algorithm; + typedef DH_Domain Domain; + + DH_Domain() {} + + DH_Domain(const GroupParameters ¶ms) + : m_groupParameters(params) {} + + DH_Domain(BufferedTransformation &bt) + {m_groupParameters.BERDecode(bt);} + + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2) + {m_groupParameters.Initialize(v1, v2);} + + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + template + DH_Domain(const T1 &v1, const T2 &v2) + {m_groupParameters.Initialize(v1, v2);} + + template + DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + template + 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 & GetKeyAgreementAlgorithm() const + {return Singleton().Ref();} + DL_GroupParameters & AccessAbstractGroupParameters() + {return m_groupParameters;} + + GroupParameters m_groupParameters; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain; + +//! Diffie-Hellman in GF(p) with key validation +typedef DH_Domain 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) + +/// Unified Diffie-Hellman +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 +#endif + +#ifndef CRYPTOPP_IMPORTS + +NAMESPACE_BEGIN(CryptoPP) + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte EMSA2HashId::id = 0x33; +template<> const byte EMSA2HashId::id = 0x38; +template<> const byte EMSA2HashId::id = 0x34; +template<> const byte EMSA2HashId::id = 0x36; +template<> const byte EMSA2HashId::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 // 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 CRYPTOPP_NO_VTABLE DMAC_Base : public SameKeyLengthAs, 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 ¶ms); + 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 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 DMAC : public MessageAuthenticationCodeFinal > +{ +public: + DMAC() {} + DMAC(const byte *key, size_t length=DMAC_Base::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} +}; + +template +void DMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + 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 +void DMAC_Base::Update(const byte *input, size_t length) +{ + m_mac1.Update(input, length); + m_counter = (unsigned int)((m_counter + length) % T::BLOCKSIZE); +} + +template +void DMAC_Base::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 +byte *DMAC_Base::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 ¶ms) +{ + 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 ¶ms); + 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(this)->AccessMAC();} + virtual CMAC_Base & AccessMAC() =0; + + CTR_Mode_ExternalCipher::Encryption m_ctr; +}; + +//! . +template +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 m_cmac; +}; + +#ifdef EAX // EAX is defined to 11 on GCC 3.4.3, OpenSolaris 8.11 +#undef EAX +#endif + +/// EAX +template +struct EAX : public AuthenticatedSymmetricCipherDocumentation +{ + typedef EAX_Final Encryption; + typedef EAX_Final 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().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& EcPrecomputation::operator=(const EcPrecomputation &rhs) +{ + m_ec = rhs.m_ec; + m_ep = rhs.m_ep; + m_ep.m_group = m_ec.get(); + return *this; +} + +void EcPrecomputation::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base) +{ + m_ec.reset(new EC2N(ec)); + m_ep.SetGroupAndBase(*m_ec, base); +} + +void EcPrecomputation::Precompute(unsigned int maxExpBits, unsigned int storage) +{ + m_ep.Precompute(maxExpBits, storage); +} + +void EcPrecomputation::Load(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(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::Save(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + m_ep.m_exponentBase.DEREncode(seq); + for (unsigned i=0; iDEREncodePoint(seq, m_ep.m_bases[i]); + seq.MessageEnd(); +} + +EC2N::Point EcPrecomputation::Exponentiate(const Integer &exponent) const +{ + return m_ep.Exponentiate(exponent); +} + +EC2N::Point EcPrecomputation::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const +{ + return m_ep.CascadeExponentiate(exponent, static_cast &>(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; + +//! Elliptic Curve over GF(2^n) +class CRYPTOPP_DLL EC2N : public AbstractGroup +{ +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 m_field; + FieldElement m_a, m_b; + mutable Point m_R; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; + +template class EcPrecomputation; + +//! EC2N precomputation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +public: + typedef EC2N EllipticCurve; + + // DL_GroupPrecomputation + const AbstractGroup & 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::Signer t1; + ECDSA::Verifier t2(t1); + ECNR::Signer t3; + ECNR::Verifier t4(t3); + ECIES::Encryptor t5; + ECIES::Decryptor t6; + ECDH::Domain t7; + ECMQV::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) struct EcRecommendedParameters; + +template<> struct EcRecommendedParameters +{ + 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 +{ + 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 + inline bool operator()(const EcRecommendedParameters& a, const OID& b) {return a.oid < b;} + template + inline bool operator()(const OID& a, const EcRecommendedParameters& b) {return a < b.oid;} + template + inline bool operator()(const EcRecommendedParameters& a, const EcRecommendedParameters& b) {return a.oid < b.oid;} +}; + +static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = { + EcRecommendedParameters(ASN1::sect163k1(), + 163, 7, 6, 3, 0, + "000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000001", + "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9", + "04000000000000000000020108A2E0CC0D99F8A5EF", + 2), + EcRecommendedParameters(ASN1::sect163r1(), + 163, 7, 6, 3, 0, + "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", + "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", + "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883", + "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", + 2), + EcRecommendedParameters(ASN1::sect239k1(), + 239, 158, 0, + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", + "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", + 4), + EcRecommendedParameters(ASN1::sect113r1(), + 113, 9, 0, + "003088250CA6E7C7FE649CE85820F7", + "00E8BEE4D3E2260744188BE0E9C723", + "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886", + "0100000000000000D9CCEC8A39E56F", + 2), + EcRecommendedParameters(ASN1::sect113r2(), + 113, 9, 0, + "00689918DBEC7E5A0DD6DFC0AA55C7", + "0095E9A9EC9B297BD4BF36E059184F", + "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D", + "010000000000000108789B2496AF93", + 2), + EcRecommendedParameters(ASN1::sect163r2(), + 163, 7, 6, 3, 0, + "000000000000000000000000000000000000000001", + "020A601907B8C953CA1481EB10512F78744A3205FD", + "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", + "040000000000000000000292FE77E70C12A4234C33", + 2), + EcRecommendedParameters(ASN1::sect283k1(), + 283, 12, 7, 5, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000001", + "040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", + 4), + EcRecommendedParameters(ASN1::sect283r1(), + 283, 12, 7, 5, 0, + "000000000000000000000000000000000000000000000000000000000000000000000001", + "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", + "0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", + 2), + EcRecommendedParameters(ASN1::sect131r1(), + 131, 8, 3, 2, 0, + "07A11B09A76B562144418FF3FF8C2570B8", + "0217C05610884B63B9C6C7291678F9D341", + "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150", + "0400000000000000023123953A9464B54D", + 2), + EcRecommendedParameters(ASN1::sect131r2(), + 131, 8, 3, 2, 0, + "03E5A88919D7CAFCBF415F07C2176573B2", + "04B8266A46C55657AC734CE38F018F2192", + "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F", + "0400000000000000016954A233049BA98F", + 2), + EcRecommendedParameters(ASN1::sect193r1(), + 193, 15, 0, + "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", + "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", + "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", + "01000000000000000000000000C7F34A778F443ACC920EBA49", + 2), + EcRecommendedParameters(ASN1::sect193r2(), + 193, 15, 0, + "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", + "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", + "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", + "010000000000000000000000015AAB561B005413CCD4EE99D5", + 2), + EcRecommendedParameters(ASN1::sect233k1(), + 233, 74, 0, + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", + "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", + 4), + EcRecommendedParameters(ASN1::sect233r1(), + 233, 74, 0, + "000000000000000000000000000000000000000000000000000000000001", + "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", + "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", + "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", + 2), + EcRecommendedParameters(ASN1::sect409k1(), + 409, 87, 0, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", + 4), + EcRecommendedParameters(ASN1::sect409r1(), + 409, 87, 0, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", + "04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", + "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", + 2), + EcRecommendedParameters(ASN1::sect571k1(), + 571, 10, 5, 2, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", + "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", + 4), + EcRecommendedParameters(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 *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = { + EcRecommendedParameters(ASN1::secp192r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + 1), + EcRecommendedParameters(ASN1::secp256r1(), + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 1), + EcRecommendedParameters(ASN1::brainpoolP160r1(), + "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", + "1E589A8595423412134FAA2DBDEC95C8D8675E58", + "04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321", + "E95E4A5F737059DC60DF5991D45029409E60FC09", + 1), + EcRecommendedParameters(ASN1::brainpoolP192r1(), + "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", + "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", + "04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", + "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + 1), + EcRecommendedParameters(ASN1::brainpoolP224r1(), + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + "040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + 1), + EcRecommendedParameters(ASN1::brainpoolP256r1(), + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + 1), + EcRecommendedParameters(ASN1::brainpoolP320r1(), + "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", + "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", + "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", + "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + 1), + EcRecommendedParameters(ASN1::brainpoolP384r1(), + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + 1), + EcRecommendedParameters(ASN1::brainpoolP512r1(), + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + 1), + EcRecommendedParameters(ASN1::secp112r1(), + "DB7C2ABF62E35E668076BEAD208B", + "DB7C2ABF62E35E668076BEAD2088", + "659EF8BA043916EEDE8911702B22", + "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500", + "DB7C2ABF62E35E7628DFAC6561C5", + 1), + EcRecommendedParameters(ASN1::secp112r2(), + "DB7C2ABF62E35E668076BEAD208B", + "6127C24C05F38A0AAAF65C0EF02C", + "51DEF1815DB5ED74FCC34C85D709", + "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97", + "36DF0AAFD8B8D7597CA10520D04B", + 4), + EcRecommendedParameters(ASN1::secp160r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32", + "0100000000000000000001F4C8F927AED3CA752257", + 1), + EcRecommendedParameters(ASN1::secp160k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "0000000000000000000000000000000000000000", + "0000000000000000000000000000000000000007", + "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE", + "0100000000000000000001B8FA16DFAB9ACA16B6B3", + 1), + EcRecommendedParameters(ASN1::secp256k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000007", + "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + 1), + EcRecommendedParameters(ASN1::secp128r1(), + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", + "E87579C11079F43DD824993C2CEE5ED3", + "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83", + "FFFFFFFE0000000075A30D1B9038A115", + 1), + EcRecommendedParameters(ASN1::secp128r2(), + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "D6031998D1B3BBFEBF59CC9BBFF9AEE1", + "5EEEFCA380D02919DC2C6558BB6D8A5D", + "047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44", + "3FFFFFFF7FFFFFFFBE0024720613B5A3", + 4), + EcRecommendedParameters(ASN1::secp160r2(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", + "B4E134D3FB59EB8BAB57274904664D5AF50388BA", + "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", + "0100000000000000000000351EE786A818F3A1A16B", + 1), + EcRecommendedParameters(ASN1::secp192k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000003", + "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", + 1), + EcRecommendedParameters(ASN1::secp224k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000005", + "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", + 1), + EcRecommendedParameters(ASN1::secp224r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + 1), + EcRecommendedParameters(ASN1::secp384r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 1), + EcRecommendedParameters(ASN1::secp521r1(), + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 1), + }; + begin = rec; + end = rec + sizeof(rec)/sizeof(rec[0]); +} + +template OID DL_GroupParameters_EC::GetNextRecommendedParametersOID(const OID &oid) +{ + const EcRecommendedParameters *begin, *end; + GetRecommendedParameters(begin, end); + const EcRecommendedParameters *it = std::upper_bound(begin, end, oid, OIDLessThan()); + return (it == end ? OID() : it->oid); +} + +template void DL_GroupParameters_EC::Initialize(const OID &oid) +{ + const EcRecommendedParameters *begin, *end; + GetRecommendedParameters(begin, end); + const EcRecommendedParameters *it = std::lower_bound(begin, end, oid, OIDLessThan()); + if (it == end || it->oid != oid) + throw UnknownOID(); + + const EcRecommendedParameters ¶m = *it; + m_oid = oid; + std::auto_ptr 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 +bool DL_GroupParameters_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(pValue) = m_oid; + return true; + } + else + return GetValueHelper >(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Curve); +} + +template +void DL_GroupParameters_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", Name::Curve(), ec); + source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupGenerator(), G); + source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupOrder(), n); + Integer k = source.GetValueWithDefault(Name::Cofactor(), Integer::Zero()); + + Initialize(ec, G, n, k); + } +} + +template +void DL_GroupParameters_EC::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + try + { + AssignFrom(alg); + } + catch (InvalidArgument &) + { + throw NotImplemented("DL_GroupParameters_EC: curve generation is not implemented yet"); + } +} + +template +void DL_GroupParameters_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(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 +void DL_GroupParameters_EC::DEREncode(BufferedTransformation &bt) const +{ + if (m_encodeAsOID && !m_oid.m_values.empty()) + m_oid.DEREncode(bt); + else + { + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(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 +Integer DL_GroupParameters_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 +Integer DL_GroupParameters_EC::ConvertElementToInteger(const Element &element) const +{ + return ConvertToInteger(element.x); +}; + +template +bool DL_GroupParameters_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 +bool DL_GroupParameters_EC::ValidateElement(unsigned int level, const Element &g, const DL_FixedBasePrecomputation *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 +void DL_GroupParameters_EC::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const +{ + GetCurve().SimultaneousMultiply(results, base, exponents, exponentsCount); +} + +template +CPP_TYPENAME DL_GroupParameters_EC::Element DL_GroupParameters_EC::MultiplyElements(const Element &a, const Element &b) const +{ + return GetCurve().Add(a, b); +} + +template +CPP_TYPENAME DL_GroupParameters_EC::Element DL_GroupParameters_EC::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const +{ + return GetCurve().CascadeMultiply(exponent1, element1, exponent2, element2); +} + +template +OID DL_GroupParameters_EC::GetAlgorithmID() const +{ + return ASN1::id_ecPublicKey(); +} + +// ****************************************************************** + +template +void DL_PublicKey_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 +void DL_PublicKey_EC::DEREncodePublicKey(BufferedTransformation &bt) const +{ + this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression()); +} + +// ****************************************************************** + +template +void DL_PrivateKey_EC::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(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 +void DL_PrivateKey_EC::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + DEREncodeUnsigned(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 DL_GroupParameters_EC : public DL_GroupParametersImpl > +{ + typedef DL_GroupParameters_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 & GetBasePrecomputation() const {return this->m_gpc;} + DL_FixedBasePrecomputation & 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 *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 DL_PublicKey_EC : public DL_PublicKeyImpl > +{ +public: + typedef typename EC::Point Element; + + void Initialize(const DL_GroupParameters_EC ¶ms, 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 DL_PrivateKey_EC : public DL_PrivateKeyImpl > +{ +public: + typedef typename EC::Point Element; + + void Initialize(const DL_GroupParameters_EC ¶ms, 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 ¶ms) + {this->GenerateRandom(rng, params);} + void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n) + {this->GenerateRandom(rng, DL_GroupParameters_EC(ec, G, n));} + + // PKCS8PrivateKey + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; +}; + +//! Elliptic Curve Diffie-Hellman, AKA ECDH +template ::DefaultCofactorOption> +struct ECDH +{ + typedef DH_Domain, COFACTOR_OPTION> Domain; +}; + +/// Elliptic Curve Menezes-Qu-Vanstone, AKA ECMQV +template ::DefaultCofactorOption> +struct ECMQV +{ + typedef MQV_Domain, COFACTOR_OPTION> Domain; +}; + +//! EC keys +template +struct DL_Keys_EC +{ + typedef DL_PublicKey_EC PublicKey; + typedef DL_PrivateKey_EC PrivateKey; +}; + +template +struct ECDSA; + +//! ECDSA keys +template +struct DL_Keys_ECDSA +{ + typedef DL_PublicKey_EC PublicKey; + typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA > PrivateKey; +}; + +//! ECDSA algorithm +template +class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";} +}; + +//! ECNR algorithm +template +class DL_Algorithm_ECNR : public DL_Algorithm_NR +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";} +}; + +//! ECDSA +template +struct ECDSA : public DL_SS, DL_Algorithm_ECDSA, DL_SignatureMessageEncodingMethod_DSA, H> +{ +}; + +//! ECNR +template +struct ECNR : public DL_SS, DL_Algorithm_ECNR, DL_SignatureMessageEncodingMethod_NR, H> +{ +}; + +//! Elliptic Curve Integrated Encryption Scheme, AKA ECIES +/*! 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 +struct ECIES + : public DL_ES< + DL_Keys_EC, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE>, + ECIES > +{ + 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; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; + +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

= 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

().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 void ParallelInvert(const AbstractRing &ring, Iterator begin, Iterator end) +{ + size_t n = end-begin; + if (n == 1) + *begin = ring.MultiplicativeInverse(*begin); + else if (n > 1) + { + std::vector vec((n+1)/2); + unsigned int i; + Iterator it; + + for (i=0, it=begin; i::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::iterator it; +}; + +ECP::Point ECP::ScalarMultiply(const Point &P, const Integer &k) const +{ + Element result; + if (k.BitCount() <= 5) + AbstractGroup::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 bases; + std::vector exponents; + exponents.reserve(expCount); + std::vector > baseIndices(expCount); + std::vector > negateBase(expCount); + std::vector > exponentWindows(expCount); + unsigned int i; + + for (i=0; iNotNegative()); + 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 > finalCascade; + for (i=0; i::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; + +//! Elliptic Curve over GF(p), where p is prime +class CRYPTOPP_DLL ECP : public AbstractGroup +{ +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 m_fieldPtr; + FieldElement m_a, m_b; + mutable Point m_R; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; + +template class EcPrecomputation; + +//! ECP precomputation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +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 & 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 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, + public DL_KeyDerivationAlgorithm, + public DL_SymmetricEncryptionAlgorithm +{ +public: + void Derive(const DL_GroupParameters &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 ¶meters) 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 ¶meters) 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 ElGamalObjectImpl : public DL_ObjectImplBase, 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 & GetKeyAgreementAlgorithm() const {return *this;} + const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const {return *this;} + const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const {return *this;} +}; + +struct ElGamalKeys +{ + typedef DL_CryptoKeys_GFP::GroupParameters GroupParameters; + typedef DL_PrivateKey_GFP_OldFormat PrivateKey; + typedef DL_PublicKey_GFP_OldFormat PublicKey; +}; + +//! ElGamal encryption scheme with non-standard padding +struct ElGamal +{ + typedef DL_CryptoSchemeOptions SchemeOptions; + + static const char * StaticAlgorithmName() {return "ElgamalEnc/Crypto++Padding";} + + typedef SchemeOptions::GroupParameters GroupParameters; + //! implements PK_Encryptor interface + typedef PK_FinalTemplate, SchemeOptions, SchemeOptions::PublicKey> > Encryptor; + //! implements PK_Decryptor interface + typedef PK_FinalTemplate, 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 EMSA2HashId +{ +public: + static const byte id; +}; + +template +class EMSA2HashIdLookup : public BASE +{ +public: + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier Lookup() + { + return HashIdentifier(&EMSA2HashId::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; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +#endif + +//! _ +class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup +{ +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 void DL_FixedBasePrecomputationImpl::SetBase(const DL_GroupPrecomputation &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 void DL_FixedBasePrecomputationImpl::Precompute(const DL_GroupPrecomputation &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 void DL_FixedBasePrecomputationImpl::Load(const DL_GroupPrecomputation &group, BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(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 void DL_FixedBasePrecomputationImpl::Save(const DL_GroupPrecomputation &group, BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + m_exponentBase.DEREncode(seq); + for (unsigned i=0; i void DL_FixedBasePrecomputationImpl::PrepareCascade(const DL_GroupPrecomputation &i_group, std::vector > &eb, const Integer &exponent) const +{ + const AbstractGroup &group = i_group.GetGroup(); + + Integer r, q, e = exponent; + bool fastNegate = group.InversionIsFast() && m_windowSize > 1; + unsigned int i; + + for (i=0; i+1(group.Inverse(m_bases[i]), m_exponentBase - r)); + } + else + eb.push_back(BaseAndExponent(m_bases[i], r)); + } + eb.push_back(BaseAndExponent(m_bases[i], e)); +} + +template T DL_FixedBasePrecomputationImpl::Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const +{ + std::vector > eb; // array of segments of the exponent and precalculated bases + eb.reserve(m_bases.size()); + PrepareCascade(group, eb, exponent); + return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); +} + +template T + DL_FixedBasePrecomputationImpl::CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, + const DL_FixedBasePrecomputation &i_pc2, const Integer &exponent2) const +{ + std::vector > eb; // array of segments of the exponent and precalculated bases + const DL_FixedBasePrecomputationImpl &pc2 = static_cast &>(i_pc2); + eb.reserve(m_bases.size() + pc2.m_bases.size()); + PrepareCascade(group, eb, exponent); + pc2.PrepareCascade(group, eb, exponent2); + return group.ConvertOut(GeneralCascadeMultiplication(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 + +NAMESPACE_BEGIN(CryptoPP) + +template +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 & GetGroup() const =0; + virtual Element BERDecodeElement(BufferedTransformation &bt) const =0; + virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0; +}; + +template +class DL_FixedBasePrecomputation +{ +public: + typedef T Element; + + virtual bool IsInitialized() const =0; + virtual void SetBase(const DL_GroupPrecomputation &group, const Element &base) =0; + virtual const Element & GetBase(const DL_GroupPrecomputation &group) const =0; + virtual void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) =0; + virtual void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) =0; + virtual void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const =0; + virtual Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const =0; + virtual Element CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const =0; +}; + +template +class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation +{ +public: + typedef T Element; + + DL_FixedBasePrecomputationImpl() : m_windowSize(0) {} + + // DL_FixedBasePrecomputation + bool IsInitialized() const + {return !m_bases.empty();} + void SetBase(const DL_GroupPrecomputation &group, const Element &base); + const Element & GetBase(const DL_GroupPrecomputation &group) const + {return group.NeedConversions() ? m_base : m_bases[0];} + void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage); + void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation); + void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const; + Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const; + Element CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const; + +private: + void PrepareCascade(const DL_GroupPrecomputation &group, std::vector > &eb, const Integer &exponent) const; + + Element m_base; + unsigned int m_windowSize; + Integer m_exponentBase; // what base to represent the exponent in + std::vector 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::Verifier x1(1, 1); + ESIGN::Signer x2(NullRNG(), 1); + ESIGN::Verifier x3(x2); + ESIGN::Verifier x4(x2.GetKey()); + ESIGN::Verifier x5(x3); + ESIGN::Signer x6 = x2; + + x6 = x2; + x3 = ESIGN::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 ¶m) +{ + 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(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + ; +} + +void InvertibleESIGNFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(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 +{ + 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 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 SignatureMessageEncodingMethod; +}; + +struct ESIGN_Keys +{ + static std::string StaticAlgorithmName() {return "ESIGN";} + typedef ESIGNFunction PublicKey; + typedef InvertibleESIGNFunction PrivateKey; +}; + +//! ESIGN, as defined in IEEE P1363a +template +struct ESIGN : public TF_SS +{ +}; + +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 +#include + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +template +class ObjectFactory +{ +public: + virtual ~ObjectFactory () {} + virtual AbstractClass * CreateObject() const =0; +}; + +//! _ +template +class DefaultObjectFactory : public ObjectFactory +{ +public: + AbstractClass * CreateObject() const + { + return new ConcreteClass; + } + +}; + +//! _ +template +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 *)i->second; + i->second = NULL; + } + } + + void RegisterFactory(const std::string &name, ObjectFactory *factory) + { + m_map[name] = factory; + } + + const ObjectFactory * GetFactory(const char *name) const + { + CPP_TYPENAME Map::const_iterator i = m_map.find(name); + return i == m_map.end() ? NULL : (ObjectFactory *)i->second; + } + + AbstractClass *CreateObject(const char *name) const + { + const ObjectFactory *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 GetFactoryNames() const + { + std::vector 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 & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT); + +private: + // use void * instead of ObjectFactory * to save code size + typedef std::map Map; + Map m_map; +}; + +template +ObjectFactoryRegistry & ObjectFactoryRegistry::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT) +{ + static ObjectFactoryRegistry s_registry; + return s_registry; +} + +template +struct RegisterDefaultFactoryFor { +RegisterDefaultFactoryFor(const char *name=NULL) +{ + // BCB2006 workaround + std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName()); + ObjectFactoryRegistry::Registry(). + RegisterFactory(n, new DefaultObjectFactory); +}}; + +template +void RegisterAsymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +template +void RegisterSignatureSchemeDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +template +void RegisterSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((const char *)name); +} + +template +void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL) +{ + RegisterDefaultFactoryFor((const char *)name); + RegisterDefaultFactoryFor((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 + +NAMESPACE_BEGIN(CryptoPP) + +using namespace std; + +#ifndef NDEBUG +void Files_TestInstantiations() +{ + FileStore f0; + FileSource f1; + FileSink f2; +} +#endif + +void FileStore::StoreInitialize(const NameValuePairs ¶meters) +{ + 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::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(this)->TransferTo2(target, copyMax, channel, blocking); + begin += copyMax; + if (blockedBytes) + { + const_cast(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 ¶meters) +{ + 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::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 +#include + +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 ¶meters); + + member_ptr 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 +{ +public: + typedef FileStore::Err Err; + typedef FileStore::OpenErr OpenErr; + typedef FileStore::ReadErr ReadErr; + + FileSource(BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {} + FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));} + FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true) + : SourceTemplate(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(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 ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedFlush(bool hardFlush, bool blocking); + +private: + member_ptr 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 +#include + +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(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 ¶meters, 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 ¶meters, 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(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 ¶meters) +{ + 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 ¶meters, 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 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 ¶meters) +{ + 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 ¶meters) +{ + 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(&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 ¶meters, 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(), 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 ¶meters) +{ + 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 ¶meters, 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 ¶meters) +{ + 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 ¶meters, 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 ¶meters) +{ + 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 ¶meters, 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 ¶meters) +{ + 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 ¶meters) +{ + 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 + +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 ¶meters=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 ¶meters, 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 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 +{ +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 ¶meters) {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 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 ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + return PutMaybeModifiable(const_cast(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 ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) + {InitializeDerived(parameters);} + virtual void InitializeDerived(const NameValuePairs ¶meters) {} + // 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 ¶meters) {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 ¶meters, 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, 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 ¶meters); + 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 ¶meters, 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 ¶meters); + 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 ¶meters, 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 +{ +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 ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + RandomNumberGenerator &m_rng; + const PK_Signer &m_signer; + member_ptr 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 ¶meters, 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 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 +{ +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 = ⌖} + 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 ¶meters, 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 +{ +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 ¶meters=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 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 StringSinkTemplate : public Bufferless +{ +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 ¶meters) + {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; +typedef StringSinkTemplate StringSink; + +//! incorporates input into RNG as additional entropy +class RandomNumberSink : public Bufferless +{ +public: + RandomNumberSink() + : m_rng(NULL) {} + + RandomNumberSink(RandomNumberGenerator &rng) + : m_rng(&rng) {} + + void IsolatedInitialize(const NameValuePairs ¶meters); + 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 +{ +public: + ArraySink(const NameValuePairs ¶meters = 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 ¶meters); + 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 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 ¶meters); + + 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 ¶meters); + + 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 ¶meters) {} + 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 +{ +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 ¶meters) + { + IsolatedInitialize(parameters); + if (pumpAll) + PumpAll(); + } +}; + +//! Turn a Store into a Source +template +class SourceTemplate : public Source +{ +public: + SourceTemplate(BufferedTransformation *attachment) + : Source(attachment) {} + void IsolatedInitialize(const NameValuePairs ¶meters) + {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 +{ +public: + StringSource(BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {} + //! zero terminated string as source + StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(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(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} + //! std::string as source + StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(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 +{ +public: + RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(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 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 ¶ms) +{ + 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 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>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= 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(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 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(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(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 ¶ms); + 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(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 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; +}; + +//! GCM +template +struct GCM : public AuthenticatedSymmetricCipherDocumentation +{ + typedef GCM_Final Encryption; + typedef GCM_Final 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 + +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 +struct NewPolynomialMod2 +{ + PolynomialMod2 * operator()() const + { + return new PolynomialMod2(i); + } +}; + +const PolynomialMod2 &PolynomialMod2::Zero() +{ + return Singleton().Ref(); +} + +const PolynomialMod2 &PolynomialMod2::One() +{ + return Singleton >().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()) + { + 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> (j/2)) % 16] << j; + + for (j=0; j> (j/2 + WORD_BITS/2)) % 16] << j; + } + + return result; +} + +void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 "ient, + const PolynomialMod2 ÷nd, 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>(unsigned int n) const +{ + PolynomialMod2 result(*this); + return result>>=n; +} + +bool PolynomialMod2::operator!() const +{ + for (unsigned i=0; i 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().Gcd(a, b); +} + +PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const +{ + typedef EuclideanDomainOf Domain; + return QuotientRing(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(), modulus), m(modulus.Degree()) +{ +} + +GF2NP::Element GF2NP::SquareRoot(const Element &a) const +{ + Element r = a; + for (unsigned int i=1; i 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> 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> 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 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 + +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 > for VC .NET 2003 +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; +CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf; +CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing >; + +//! GF(2^n) with Polynomial Basis +class CRYPTOPP_DLL GF2NP : public QuotientRing > +{ +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::Signer test; + GDSA::Verifier test1; + DSA::Signer test5(NullRNG(), 100); + DSA::Signer test2(test5); + NR::Signer test3; + NR::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 *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 >(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 + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial > +{ + typedef DL_GroupParameters_IntegerBased ThisClass; + +public: + void Initialize(const DL_GroupParameters_IntegerBased ¶ms) + {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 *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 CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl +{ + typedef DL_GroupParameters_IntegerBasedImpl 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(this, name, valueType, pValue).Assignable();} + + void AssignFrom(const NameValuePairs &source) + {AssignFromHelper(this, source);} + + // DL_GroupParameters + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;} + DL_FixedBasePrecomputation & 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 &rhs) const + {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();} + bool operator!=(const DL_GroupParameters_IntegerBasedImpl &rhs) const + {return !operator==(rhs);} +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl; + +//! GF(p) group parameters +class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl +{ +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(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 DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";} + + void Sign(const DL_GroupParameters ¶ms, 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 ¶ms, const DL_PublicKey &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; + +//! NR algorithm +template +class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";} + + void Sign(const DL_GroupParameters ¶ms, 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 ¶ms, const DL_PublicKey &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 DL_PublicKey_GFP : public DL_PublicKeyImpl +{ +public: + void Initialize(const DL_GroupParameters_IntegerBased ¶ms, 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 DL_PrivateKey_GFP : public DL_PrivateKeyImpl +{ +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 ¶ms, 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 PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +//! DL encryption/decryption keys (in GF(p) groups) +struct DL_CryptoKeys_GFP +{ + typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format +template +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 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(); + } +}; + +//! DSA-1363 +template +struct GDSA : public DL_SS< + DL_SignatureKeys_GFP, + DL_Algorithm_GDSA, + DL_SignatureMessageEncodingMethod_DSA, + H> +{ +}; + +//! NR +template +struct NR : public DL_SS< + DL_SignatureKeys_GFP, + DL_Algorithm_NR, + 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 DSA2; + +//! DSA keys +struct DL_Keys_DSA +{ + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA2 > PrivateKey; +}; + +//! DSA, as specified in FIPS 186-3 +// class named DSA2 instead of DSA for backwards compatibility (DSA was a non-template class) +template +class DSA2 : public DL_SS< + DL_Keys_DSA, + DL_Algorithm_GDSA, + DL_SignatureMessageEncodingMethod_DSA, + H, + DSA2 > +{ +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();} +}; + +//! DSA with SHA-1, typedef'd for backwards compatibility +typedef DSA2 DSA; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA2 >; + +//! the XOR encryption method, for use with DL-based cryptosystems +template +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 ¶meters) 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 ¶meters) 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 DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm +{ +public: + bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;} + void Derive(const DL_GroupParameters ¶ms, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs ¶meters) 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 DLIES +template +struct DLIES + : public DL_ES< + DL_CryptoKeys_GFP, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, 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 ¶meters, 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 ¶meters) +{ + 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 ¶meters) +{ + 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 ¶meters); +}; + +//! 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 ¶meters); + +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, public MessageAuthenticationCode +{ +public: + HMAC_Base() : m_innerHashKeyed(false) {} + void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms); + + void Restart(); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int OptimalBlockSize() const {return const_cast(this)->AccessHash().OptimalBlockSize();} + unsigned int DigestSize() const {return const_cast(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; +}; + +//! HMAC +/*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */ +template +class HMAC : public MessageAuthenticationCodeImpl > +{ +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 // for NULL +#include + +#if defined(CRYPTOPP_WIN32_AVAILABLE) +#include +#elif defined(CRYPTOPP_UNIX_AVAILABLE) +#include +#include +#include +#endif + +#include + +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 +#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 + +#if _MSC_VER >= 1400 + #include +#endif + +#ifdef __DECCXX + #include +#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(pInteger) = *reinterpret_cast(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>(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 = (ta) + (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 +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 +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(T+1, B.GetLowHalf(), B.GetHighHalf()); + Q[0] = DivideThreeWordsByTwo(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(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(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=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=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](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]= 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(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((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((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((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 +struct NewInteger +{ + Integer * operator()() const + { + return new Integer(i); + } +}; + +const Integer &Integer::Zero() +{ + return Singleton().Ref(); +} + +const Integer &Integer::One() +{ + return Singleton >().Ref(); +} + +const Integer &Integer::Two() +{ + return Singleton >().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 +static Integer StringToInteger(const T *str) +{ + int radix; + // GCC workaround + // std::char_traits::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= '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 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::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 ¶ms) +{ + 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 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 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 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 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 "ient, + const Integer ÷nd, 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 "ient, + 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 "ient, const Integer ÷nd, 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 "ient, const Integer ÷nd, 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().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 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::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::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 +#include + +NAMESPACE_BEGIN(CryptoPP) + +struct InitializeInteger // used to initialize static variables +{ + InitializeInteger(); +}; + +typedef SecBlock > 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 ¶ms = g_nullNameValuePairs); + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = 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 "ient, const Integer ÷nd, 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 void IteratedHashBase::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(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 byte * IteratedHashBase::CreateUpdateSpace(size_t &size) +{ + unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + size = blockSize - num; + return (byte *)DataBuf() + num; +} + +template size_t IteratedHashBase::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 void IteratedHashBase::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 void IteratedHashBase::Restart() +{ + m_countLo = m_countHi = 0; + Init(); +} + +template void IteratedHashBase::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(digest) && size%sizeof(HashWordType)==0) + ConditionalByteReverse(order, (HashWordType *)digest, stateBuf, size); + else + { + ConditionalByteReverse(order, stateBuf, stateBuf, this->DigestSize()); + memcpy(digest, stateBuf, size); + } + + this->Restart(); // reinit for next use +} + +#ifdef __GNUC__ + template class IteratedHashBase; + template class IteratedHashBase; + + template class IteratedHashBase; + template class IteratedHashBase; +#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 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();} + 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 CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase +{ +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 m_data; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform + : public ClonableImpl, 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 m_state; +}; + +#ifndef __GNUC__ + CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; + CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; + + CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; + CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; +#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 struct DigestSizeDoubleWorkaround // VC60 workaround +{ + CRYPTOPP_CONSTANT(RESULT = 2*T::DIGESTSIZE) +}; + +//! algorithm info +template +struct LR_Info : public VariableKeyLength<16, 0, 2*(INT_MAX/2), 2>, public FixedBlockSize::RESULT> +{ + static std::string StaticAlgorithmName() {return std::string("LR/")+T::StaticAlgorithmName();} +}; + +//! Luby-Rackoff +template +class LR : public LR_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl > + { + public: + // VC60 workaround: have to define these functions within class definition + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) + { + 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; + typedef BlockCipherFinal 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::Signer t1; + LUCFunction t2; + InvertibleLUCFunction t3; +} + +void DL_Algorithm_LUC_HMP::Sign(const DL_GroupParameters ¶ms, 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 ¶ms, const DL_PublicKey &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 &group, const Integer &exponent) const +{ + return Lucas(exponent, m_g, static_cast(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 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(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(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 + +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 +struct LUCES : public TF_ES +{ +}; + +//! LUC signature scheme with appendix +template +struct LUCSS : public TF_SS +{ +}; + +// analagous to the RSA schemes defined in PKCS #1 v2.0 +typedef LUCES >::Decryptor LUCES_OAEP_SHA_Decryptor; +typedef LUCES >::Encryptor LUCES_OAEP_SHA_Encryptor; + +typedef LUCSS::Signer LUCSSA_PKCS1v15_SHA_Signer; +typedef LUCSS::Verifier LUCSSA_PKCS1v15_SHA_Verifier; + +// ******************************************************** + +// no actual precomputation +class DL_GroupPrecomputation_LUC : public DL_GroupPrecomputation +{ +public: + const AbstractGroup & 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 +{ +public: + // DL_FixedBasePrecomputation + bool IsInitialized() const {return m_g.NotZero();} + void SetBase(const DL_GroupPrecomputation &group, const Integer &base) {m_g = base;} + const Integer & GetBase(const DL_GroupPrecomputation &group) const {return m_g;} + void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) {} + void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) {} + void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const {} + Integer Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const; + Integer CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &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 +{ +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(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 +{ +public: + static const char * StaticAlgorithmName() {return "LUC-HMP";} + + void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const; + bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const; + + size_t RLen(const DL_GroupParameters ¶ms) const + {return params.GetGroupOrder().ByteCount();} +}; + +//! _ +struct DL_SignatureKeys_LUC +{ + typedef DL_GroupParameters_LUC GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +//! LUC-HMP, based on "Digital signature schemes based on Lucas functions" by Patrick Horster, Markus Michels, Holger Petersen +template +struct LUC_HMP : public DL_SS +{ +}; + +//! _ +struct DL_CryptoKeys_LUC +{ + typedef DL_GroupParameters_LUC_DefaultSafePrime GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +//! LUC-IES +template +struct LUC_IES + : public DL_ES< + DL_CryptoKeys_LUC, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE>, + LUC_IES<> > +{ + static std::string StaticAlgorithmName() {return "LUC-IES";} // non-standard name +}; + +// ******************************************************** + +//! LUC-DH +typedef DH_Domain 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; iMD2 +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 { + +//! MD4 +/*! \warning MD4 is considered insecure, and should not be used + unless you absolutely need it for compatibility. */ +class MD4 : public IteratedHashWithStaticTransform +{ +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 { + +//! MD5 +class MD5 : public IteratedHashWithStaticTransform +{ +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 +struct MDC_Info : public FixedBlockSize, public FixedKeyLength +{ + static std::string StaticAlgorithmName() {return std::string("MDC/")+T::StaticAlgorithmName();} +}; + +//! MDC +/*! a construction by Peter Gutmann to turn an iterated hash function into a PRF */ +template +class MDC : public MDC_Info +{ + class CRYPTOPP_NO_VTABLE Enc : public BlockCipherImpl > + { + typedef typename T::HashWordType HashWordType; + + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) + { + 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::KEYLENGTH, AllocatorWithCleanup > m_key; + mutable FixedSizeSecBlock::BLOCKSIZE, AllocatorWithCleanup > m_buffer; + }; + +public: + //! use BlockCipher interface + typedef BlockCipherFinal 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 + +#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX) +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +void xorbuf(byte *buf, const byte *mask, size_t count) +{ + size_t i; + + if (IsAligned(buf) && IsAligned(mask)) + { + if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(buf) && IsAligned(mask)) + { + for (i=0; i(output) && IsAligned(input) && IsAligned(mask)) + { + if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(output) && IsAligned(input) && IsAligned(mask)) + { + for (i=0; i(buf) && IsAligned(mask)) + { + word32 acc32 = 0; + if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(buf) && IsAligned(mask)) + { + word64 acc64 = 0; + for (i=0; i>32); + } + + for (i=0; i>8) | byte(acc32>>16) | byte(acc32>>24); + } + + for (i=0; i // 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 + #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 +#endif + +#if defined(__GNUC__) && defined(__linux__) +#define CRYPTOPP_BYTESWAP_AVAILABLE +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** compile-time assertion *************** + +template +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 CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2 +{ +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3 +{ +}; + +template +class ObjectHolder +{ +protected: + T m_object; +}; + +class NotCopyable +{ +public: + NotCopyable() {} +private: + NotCopyable(const NotCopyable &); + void operator=(const NotCopyable &); +}; + +template +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 , 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 +const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const +{ + static volatile simple_ptr 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 inline const T& STDMIN(const T& a, const T& b) +{ + return b < a ? b : a; +} + +template 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 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 +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 +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 +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 +inline T Crop(T value, size_t size) +{ + if (size < 8*sizeof(value)) + return T(value & ((T(1) << size) - 1)); + else + return value; +} + +template +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 +inline bool IsPowerOf2(const T &n) +{ + return n > 0 && (n & (n-1)) == 0; +} + +template +inline T2 ModPowerOf2(const T1 &a, const T2 &b) +{ + assert(IsPowerOf2(b)); + return T2(a) & (b-1); +} + +template +inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m) +{ + if (IsPowerOf2(m)) + return n - ModPowerOf2(n, m); + else + return n - n%m; +} + +template +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 +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 +inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround +{ + return IsAlignedOn(p, GetAlignmentOf()); +} + +#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 +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 +inline T1 SaturatingSubtract(const T1 &a, const T2 &b) +{ + return T1((a > b) ? (a - b) : 0); +} + +template +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 +inline void ConditionalSwap(bool c, T &a, T &b) +{ + T t = c * (a ^ b); + a ^= t; + b ^= t; +} + +template +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 +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 +inline void SecureWipeArray(T *buf, size_t n) +{ + if (sizeof(T) % 8 == 0 && GetAlignmentOf() % GetAlignmentOf() == 0) + SecureWipeBuffer((word64 *)buf, n * (sizeof(T)/8)); + else if (sizeof(T) % 4 == 0 && GetAlignmentOf() % GetAlignmentOf() == 0) + SecureWipeBuffer((word32 *)buf, n * (sizeof(T)/4)); + else if (sizeof(T) % 2 == 0 && GetAlignmentOf() % GetAlignmentOf() == 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 inline T rotlFixed(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return y ? T((x<>(sizeof(T)*8-y))) : x; +} + +template 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 inline T rotlVariable(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return T((x<>(sizeof(T)*8-y))); +} + +template inline T rotrVariable(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return T((x>>y) | (x<<(sizeof(T)*8-y))); +} + +template inline T rotlMod(T x, unsigned int y) +{ + y %= sizeof(T)*8; + return T((x<>(sizeof(T)*8-y))); +} + +template 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 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _lrotl(x, y) : x; +} + +template<> inline word32 rotrFixed(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _lrotr(x, y) : x; +} + +template<> inline word32 rotlVariable(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _lrotl(x, y); +} + +template<> inline word32 rotrVariable(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _lrotr(x, y); +} + +template<> inline word32 rotlMod(word32 x, unsigned int y) +{ + return _lrotl(x, y); +} + +template<> inline word32 rotrMod(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 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotl64(x, y) : x; +} + +template<> inline word64 rotrFixed(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotr64(x, y) : x; +} + +template<> inline word64 rotlVariable(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotl64(x, y); +} + +template<> inline word64 rotrVariable(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotr64(x, y); +} + +template<> inline word64 rotlMod(word64 x, unsigned int y) +{ + return _rotl64(x, y); +} + +template<> inline word64 rotrMod(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 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotl16(x, y) : x; +} + +template<> inline word16 rotrFixed(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotr16(x, y) : x; +} + +template<> inline word16 rotlVariable(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotl16(x, y); +} + +template<> inline word16 rotrVariable(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotr16(x, y); +} + +template<> inline word16 rotlMod(word16 x, unsigned int y) +{ + return _rotl16(x, y); +} + +template<> inline word16 rotrMod(word16 x, unsigned int y) +{ + return _rotr16(x, y); +} + +template<> inline byte rotlFixed(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotl8(x, y) : x; +} + +template<> inline byte rotrFixed(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotr8(x, y) : x; +} + +template<> inline byte rotlVariable(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotl8(x, y); +} + +template<> inline byte rotrVariable(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotr8(x, y); +} + +template<> inline byte rotlMod(byte x, unsigned int y) +{ + return _rotl8(x, y); +} + +template<> inline byte rotrMod(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 x, unsigned int y) +{ + assert(y < 32); + return y ? __rlwinm(x,y,0,31) : x; +} + +template<> inline word32 rotrFixed(word32 x, unsigned int y) +{ + assert(y < 32); + return y ? __rlwinm(x,32-y,0,31) : x; +} + +template<> inline word32 rotlVariable(word32 x, unsigned int y) +{ + assert(y < 32); + return (__rlwnm(x,y,0,31)); +} + +template<> inline word32 rotrVariable(word32 x, unsigned int y) +{ + assert(y < 32); + return (__rlwnm(x,32-y,0,31)); +} + +template<> inline word32 rotlMod(word32 x, unsigned int y) +{ + return (__rlwnm(x,y,0,31)); +} + +template<> inline word32 rotrMod(word32 x, unsigned int y) +{ + return (__rlwnm(x,32-y,0,31)); +} + +#endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC) + +// ************** endian reversal *************** + +template +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 +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 +inline T ConditionalByteReverse(ByteOrder order, T value) +{ + return NativeByteOrderIs(order) ? value : ByteReverse(value); +} + +template +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 +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 +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 +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(block)); +#endif + return ConditionalByteReverse(order, *reinterpret_cast(block)); +} + +template +inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block) +{ + result = GetWord(assumeAligned, order, block); +} + +template +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(block)); + assert(IsAligned(xorBlock)); +#endif + *reinterpret_cast(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast(xorBlock) : 0); +} + +template +class GetBlock +{ +public: + GetBlock(const void *block) + : m_block((const byte *)block) {} + + template + inline GetBlock & operator()(U &x) + { + CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T)); + x = GetWord(A, B::ToEnum(), m_block); + m_block += sizeof(T); + return *this; + } + +private: + const byte *m_block; +}; + +template +class PutBlock +{ +public: + PutBlock(const void *xorBlock, void *block) + : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {} + + template + inline PutBlock & 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 +struct BlockGetAndPut +{ + // function needed because of C++ grammatical ambiguity between expression-statements and declarations + static inline GetBlock Get(const void *block) {return GetBlock(block);} + typedef PutBlock Put; +}; + +template +std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER) +{ + if (!NativeByteOrderIs(order)) + value = ByteReverse(value); + + return std::string((char *)&value, sizeof(value)); +} + +template +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 struct SafeShifter; + +template<> struct SafeShifter +{ + template + static inline T RightShift(T value, unsigned int bits) + { + return 0; + } + + template + static inline T LeftShift(T value, unsigned int bits) + { + return 0; + } +}; + +template<> struct SafeShifter +{ + template + static inline T RightShift(T value, unsigned int bits) + { + return value >> bits; + } + + template + static inline T LeftShift(T value, unsigned int bits) + { + return value << bits; + } +}; + +template +inline T SafeRightShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); +} + +template +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; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; + +//! 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 +{ +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::CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const + {AbstractRing::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::Encryption m0; + CFB_Mode::Decryption m1; + OFB_Mode::Encryption m2; + CTR_Mode::Encryption m3; + ECB_Mode::Encryption m4; + CBC_Mode::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 ¶ms) +{ + 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 CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE +{ + unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); +}; + +template +void ModePolicyCommonTemplate::CipherSetKey(const NameValuePairs ¶ms, 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 +{ +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 +{ +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 +{ +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 ¶ms); + 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 ¶ms = 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 ¶ms) + { + 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 CipherModeFinalTemplate_CipherHolder : protected ObjectHolder, public AlgorithmImpl > +{ +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 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 >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; + +//! CFB mode +template +struct CFB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > > > Decryption; +}; + +//! CFB mode, external cipher +struct CFB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef CipherModeFinalTemplate_ExternalCipher > > > Decryption; +}; + +//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A +template +struct CFB_FIPS_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > > > > 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 > > > > Encryption; + typedef CipherModeFinalTemplate_ExternalCipher > > > > Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; + +//! OFB mode +template +struct OFB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef Encryption Decryption; +}; + +//! OFB mode, external cipher +struct OFB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef Encryption Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher > > >; + +//! CTR mode +template +struct CTR_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef Encryption Decryption; +}; + +//! CTR mode, external cipher +struct CTR_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef Encryption Decryption; +}; + +//! ECB mode +template +struct ECB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +//! ECB mode, external cipher +struct ECB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef Encryption Decryption; +}; + +//! CBC mode +template +struct CBC_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +//! CBC mode, external cipher +struct CBC_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef CipherModeFinalTemplate_ExternalCipher Decryption; +}; + +//! CBC mode with ciphertext stealing +template +struct CBC_CTS_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +//! CBC mode with ciphertext stealing, external cipher +struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef CipherModeFinalTemplate_ExternalCipher 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; + +class ModExpPrecomputation : public DL_GroupPrecomputation +{ +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 & 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 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::const_iterator it = m_lengths.begin(); + unsigned int i; + for (i=0; i 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 + +NAMESPACE_BEGIN(CryptoPP) + +//! Message Queue +class CRYPTOPP_DLL MessageQueue : public AutoSignaling +{ +public: + MessageQueue(unsigned int nodeSize=256); + + void IsolatedInitialize(const NameValuePairs ¶meters) + {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 m_lengths; + std::deque m_messageCounts; +}; + + +//! A filter that checks messages on two channels for equality +class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable > +{ +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 MQV_Domain : public AuthenticatedKeyAgreementDomain +{ +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef MQV_Domain Domain; + + MQV_Domain() {} + + MQV_Domain(const GroupParameters ¶ms) + : m_groupParameters(params) {} + + MQV_Domain(BufferedTransformation &bt) + {m_groupParameters.BERDecode(bt);} + + template + MQV_Domain(T1 v1, T2 v2) + {m_groupParameters.Initialize(v1, v2);} + + template + MQV_Domain(T1 v1, T2 v2, T3 v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + template + 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 ¶ms = 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 ¶ms = 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 ¶ms = 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 & AccessAbstractGroupParameters() {return m_groupParameters;} + const DL_GroupParameters & GetAbstractGroupParameters() const {return m_groupParameters;} + + GroupParameters m_groupParameters; +}; + +//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA MQV +typedef MQV_Domain 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 +#include + +#ifdef _OPENMP +// needed in MSVC 2005 to generate correct manifest +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +const word s_lastSmallPrime = 32719; + +struct NewPrimeTable +{ + std::vector * operator()() const + { + const unsigned int maxPrimeTableSize = 3511; + + std::auto_ptr > pPrimeTable(new std::vector); + std::vector &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 &primeTable = Singleton, 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]3 && b>1 && b3 && b>1 && b>a; + + Integer z = a_exp_b_mod_c(b, m, n); + if (z==1 || z==nminus1) + return true; + for (unsigned j=1; j3); + + Integer b; + for (unsigned int i=0; i2); + + 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().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 &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 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 &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>= 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>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(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 + +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 > 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, 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(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(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 + +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 ¶meters) 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 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 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 ¶meters) 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 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 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(), 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 ¶meters) const; + DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; + +protected: + virtual unsigned int DigestSize() const =0; + virtual HashTransformation * NewHash() const =0; + virtual MaskGeneratingFunction * NewMGF() const =0; +}; + +//! EME-OAEP, for use with classes derived from TF_ES +template +class OAEP : public OAEP_Base, public EncryptionStandard +{ +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} + typedef OAEP 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; + +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 +#include +#endif + +#ifdef CRYPTOPP_UNIX_AVAILABLE +#include +#include +#include +#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().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 +#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 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 m_rng; +}; + +template +void AutoSeededX917RNG::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 +void AutoSeededX917RNG::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; + +//! this is AutoSeededX917RNG\ in FIPS mode, otherwise it's AutoSeededRandomPool +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +typedef AutoSeededX917RNG 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 + +NAMESPACE_BEGIN(CryptoPP) + +// more in dll.cpp +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::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::length = sizeof(PKCS_DigestDecoration::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 ¶meters) 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 ¶meters) 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 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) + +//! EME-PKCS1-v1_5 +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 ¶meters) const; + DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; +}; + +template 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; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +#endif + +//! EMSA-PKCS1-v1_5 +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 struct HashIdentifierLookup2 + { + static HashIdentifier Lookup() + { + return HashIdentifier(PKCS_DigestDecoration::decoration, PKCS_DigestDecoration::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 +#include + +NAMESPACE_BEGIN(CryptoPP) + +template +void PolynomialOver::Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring) +{ + m_coefficients.resize(parameter.m_coefficientCount); + for (unsigned int i=0; i +void PolynomialOver::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 +unsigned int PolynomialOver::CoefficientCount(const Ring &ring) const +{ + unsigned count = m_coefficients.size(); + while (count && ring.Equal(m_coefficients[count-1], ring.Identity())) + count--; + const_cast &>(m_coefficients).resize(count); + return count; +} + +template +typename PolynomialOver::CoefficientType PolynomialOver::GetCoefficient(unsigned int i, const Ring &ring) const +{ + return (i < m_coefficients.size()) ? m_coefficients[i] : ring.Identity(); +} + +template +PolynomialOver& PolynomialOver::operator=(const PolynomialOver& t) +{ + if (this != &t) + { + m_coefficients.resize(t.m_coefficients.size()); + for (unsigned int i=0; i +PolynomialOver& PolynomialOver::Accumulate(const PolynomialOver& 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 +PolynomialOver& PolynomialOver::Reduce(const PolynomialOver& 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 +typename PolynomialOver::CoefficientType PolynomialOver::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 +PolynomialOver& PolynomialOver::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 +PolynomialOver& PolynomialOver::ShiftRight(unsigned int n, const Ring &ring) +{ + unsigned int count = CoefficientCount(ring); + if (count > n) + { + for (unsigned int i=0; i +void PolynomialOver::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 +void PolynomialOver::Negate(const Ring &ring) +{ + unsigned int count = CoefficientCount(ring); + for (unsigned int i=0; i +void PolynomialOver::swap(PolynomialOver &t) +{ + m_coefficients.swap(t.m_coefficients); +} + +template +bool PolynomialOver::Equals(const PolynomialOver& t, const Ring &ring) const +{ + unsigned int count = CoefficientCount(ring); + + if (count != t.CoefficientCount(ring)) + return false; + + for (unsigned int i=0; i +PolynomialOver PolynomialOver::Plus(const PolynomialOver& t, const Ring &ring) const +{ + unsigned int i; + unsigned int count = CoefficientCount(ring); + unsigned int tCount = t.CoefficientCount(ring); + + if (count > tCount) + { + PolynomialOver result(ring, count); + + for (i=0; i result(ring, tCount); + + for (i=0; i +PolynomialOver PolynomialOver::Minus(const PolynomialOver& t, const Ring &ring) const +{ + unsigned int i; + unsigned int count = CoefficientCount(ring); + unsigned int tCount = t.CoefficientCount(ring); + + if (count > tCount) + { + PolynomialOver result(ring, count); + + for (i=0; i result(ring, tCount); + + for (i=0; i +PolynomialOver PolynomialOver::Inverse(const Ring &ring) const +{ + unsigned int count = CoefficientCount(ring); + PolynomialOver result(ring, count); + + for (unsigned int i=0; i +PolynomialOver PolynomialOver::Times(const PolynomialOver& t, const Ring &ring) const +{ + if (IsZero(ring) || t.IsZero(ring)) + return PolynomialOver(); + + unsigned int count1 = CoefficientCount(ring), count2 = t.CoefficientCount(ring); + PolynomialOver result(ring, count1 + count2 - 1); + + for (unsigned int i=0; i +PolynomialOver PolynomialOver::DividedBy(const PolynomialOver& t, const Ring &ring) const +{ + PolynomialOver remainder, quotient; + Divide(remainder, quotient, *this, t, ring); + return quotient; +} + +template +PolynomialOver PolynomialOver::Modulo(const PolynomialOver& t, const Ring &ring) const +{ + PolynomialOver remainder, quotient; + Divide(remainder, quotient, *this, t, ring); + return remainder; +} + +template +PolynomialOver PolynomialOver::MultiplicativeInverse(const Ring &ring) const +{ + return Degree(ring)==0 ? ring.MultiplicativeInverse(m_coefficients[0]) : ring.Identity(); +} + +template +bool PolynomialOver::IsUnit(const Ring &ring) const +{ + return Degree(ring)==0 && ring.IsUnit(m_coefficients[0]); +} + +template +std::istream& PolynomialOver::Input(std::istream &in, const Ring &ring) +{ + char c; + unsigned int length = 0; + SecBlock 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(str, ring); + + return in; +} + +template +std::ostream& PolynomialOver::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 +void PolynomialOver::Divide(PolynomialOver &r, PolynomialOver &q, const PolynomialOver &a, const PolynomialOver &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 +void RingOfPolynomialsOver::CalculateAlpha(std::vector &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const +{ + for (unsigned int j=0; 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 +typename RingOfPolynomialsOver::Element RingOfPolynomialsOver::Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const +{ + assert(n > 0); + + std::vector alpha(n); + CalculateAlpha(alpha, x, y, n); + + std::vector 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(coefficients.begin(), coefficients.end()); +} + +template +typename RingOfPolynomialsOver::CoefficientType RingOfPolynomialsOver::InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const +{ + assert(n > 0); + + std::vector 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 +void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n) +{ + for (unsigned int i=0; i +void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n) +{ + assert(n > 0); + + std::vector a(2*n-1); + unsigned int i; + + for (i=0; i1; i--) + a[i-1] = ring.Multiply(a[2*i], a[2*i-1]); + + a[0] = ring.MultiplicativeIdentity(); + + for (i=0; i +Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n) +{ + Element result = ring.Identity(); + for (unsigned int i=0; i +const PolynomialOverFixedRing &PolynomialOverFixedRing::Zero() +{ + return Singleton().Ref(); +} + +template +const PolynomialOverFixedRing &PolynomialOverFixedRing::One() +{ + return Singleton().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 +#include + +NAMESPACE_BEGIN(CryptoPP) + +//! represents single-variable polynomials over arbitrary rings +/*! \nosubgrouping */ +template class PolynomialOver +{ +public: + //! \name ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + //! division by zero exception + class DivideByZero : public Exception + { + public: + DivideByZero() : Exception(OTHER_ERROR, "PolynomialOver: 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; + }; + + 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 &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 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 + PolynomialOver(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, 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& operator=(const PolynomialOver& t); + + //! + void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, 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 &t); + //@} + + + //! \name BASIC ARITHMETIC ON POLYNOMIALS + //@{ + bool Equals(const PolynomialOver &t, const Ring &ring) const; + bool IsZero(const Ring &ring) const {return CoefficientCount(ring)==0;} + + PolynomialOver Plus(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver Minus(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver Inverse(const Ring &ring) const; + + PolynomialOver Times(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver DividedBy(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver Modulo(const PolynomialOver& t, const Ring &ring) const; + PolynomialOver MultiplicativeInverse(const Ring &ring) const; + bool IsUnit(const Ring &ring) const; + + PolynomialOver& Accumulate(const PolynomialOver& t, const Ring &ring); + PolynomialOver& Reduce(const PolynomialOver& t, const Ring &ring); + + //! + PolynomialOver Doubled(const Ring &ring) const {return Plus(*this, ring);} + //! + PolynomialOver Squared(const Ring &ring) const {return Times(*this, ring);} + + CoefficientType EvaluateAt(const CoefficientType &x, const Ring &ring) const; + + PolynomialOver& ShiftLeft(unsigned int n, const Ring &ring); + PolynomialOver& 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 &r, PolynomialOver &q, const PolynomialOver &a, const PolynomialOver &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 m_coefficients; +}; + +//! Polynomials over a fixed ring +/*! Having a fixed ring allows overloaded operators */ +template class PolynomialOverFixedRing : private PolynomialOver +{ + typedef PolynomialOver B; + typedef PolynomialOverFixedRing 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 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 ¶meter) : 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 ¶meter) {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 RingOfPolynomialsOver : public AbstractEuclideanDomain > +{ +public: + typedef T CoefficientRing; + typedef PolynomialOver Element; + typedef typename Element::CoefficientType CoefficientType; + typedef typename Element::RandomizationParameter RandomizationParameter; + + RingOfPolynomialsOver(const CoefficientRing &ring) : m_ring(ring) {} + + Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) + {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: 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 &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const; + + CoefficientRing m_ring; +}; + +template +void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n); +template +void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n); +template +Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n); + +//! +template +inline bool operator==(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Equals(b, a.ms_fixedRing);} +//! +template +inline bool operator!=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return !(a==b);} + +//! +template +inline bool operator> (const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() > b.Degree();} +//! +template +inline bool operator>=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() >= b.Degree();} +//! +template +inline bool operator< (const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() < b.Degree();} +//! +template +inline bool operator<=(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return a.Degree() <= b.Degree();} + +//! +template +inline CryptoPP::PolynomialOverFixedRing operator+(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Plus(b, a.ms_fixedRing));} +//! +template +inline CryptoPP::PolynomialOverFixedRing operator-(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Minus(b, a.ms_fixedRing));} +//! +template +inline CryptoPP::PolynomialOverFixedRing operator*(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Times(b, a.ms_fixedRing));} +//! +template +inline CryptoPP::PolynomialOverFixedRing operator/(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.DividedBy(b, a.ms_fixedRing));} +//! +template +inline CryptoPP::PolynomialOverFixedRing operator%(const CryptoPP::PolynomialOverFixedRing &a, const CryptoPP::PolynomialOverFixedRing &b) + {return CryptoPP::PolynomialOverFixedRing(a.Modulo(b, a.ms_fixedRing));} + +NAMESPACE_END + +NAMESPACE_BEGIN(std) +template inline void swap(CryptoPP::PolynomialOver &a, CryptoPP::PolynomialOver &b) +{ + a.swap(b); +} +template inline void swap(CryptoPP::PolynomialOverFixedRing &a, CryptoPP::PolynomialOverFixedRing &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 + +NAMESPACE_BEGIN(CryptoPP) + +// more in dll.cpp +template<> const byte EMSA2HashId::id = 0x31; +template<> const byte EMSA2HashId::id = 0x32; +template<> const byte EMSA2HashId::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(), 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 class PSSR_MEM_BaseWithHashId; +template<> class PSSR_MEM_BaseWithHashId : public EMSA2HashIdLookup {}; +template<> class PSSR_MEM_BaseWithHashId : public PSSR_MEM_Base {}; + +template +class PSSR_MEM : public PSSR_MEM_BaseWithHashId +{ + 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();} +}; + +//! PSSR-MGF1 +struct PSSR : public SignatureStandard +{ + typedef PSSR_MEM SignatureMessageEncodingMethod; +}; + +//! PSS-MGF1 +struct PSS : public SignatureStandard +{ + typedef PSSR_MEM 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(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(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(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(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(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 ¶meters) 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 ¶meters) 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: +

+                  x1
+                 / \
+                y1  z1
+                 |  |
+            x2  x2
+                 |  |
+                y2  z2
+                 |  |
+            x3  x3
+                 |  |
+                y3  z3
+
+ - 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 + +// 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 ¶meters) const =0; + + virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs ¶meters) const =0; +}; + +// ******************************************************** + +//! _ +template +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 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 CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl, 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 > +{ +public: + DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase > +{ +public: + void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +// ******************************************************** + +typedef std::pair 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 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 PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder +{ +public: + HashTransformation & AccessHash() {return this->m_object;} +}; + +//! _ +template +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 > +{ +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 > +{ +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 +struct TF_CryptoSchemeOptions +{ + typedef T1 AlgorithmInfo; + typedef T2 Keys; + typedef typename Keys::PrivateKey PrivateKey; + typedef typename Keys::PublicKey PublicKey; + typedef T3 MessageEncodingMethod; +}; + +//! _ +template +struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions +{ + typedef T4 HashFunction; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl +{ +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; + } + PK_MessageAccumulator * NewVerificationAccumulator() const + { + return new PK_MessageAccumulatorImpl; + } + +protected: + const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const + {return Singleton().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 L; + return L::Lookup(); + } + size_t GetDigestSize() const + { + typedef CPP_TYPENAME SchemeOptions::HashFunction H; + return H::DIGESTSIZE; + } +}; + +//! _ +template +class TF_ObjectImplExtRef : public TF_ObjectImplBase +{ +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 CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase +{ +public: + typedef KEY_CLASS KeyClass; + + const KeyClass & GetKey() const {return m_trapdoorFunction;} + KeyClass & AccessKey() {return m_trapdoorFunction;} + +private: + KeyClass m_trapdoorFunction; +}; + +//! _ +template +class TF_DecryptorImpl : public TF_ObjectImpl +{ +}; + +//! _ +template +class TF_EncryptorImpl : public TF_ObjectImpl +{ +}; + +//! _ +template +class TF_SignerImpl : public TF_ObjectImpl +{ +}; + +//! _ +template +class TF_VerifierImpl : public TF_ObjectImpl +{ +}; + +// ******************************************************** + +//! _ +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 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 CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters +{ + typedef DL_GroupParameters 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 & GetGroupPrecomputation() const =0; + virtual const DL_FixedBasePrecomputation & GetBasePrecomputation() const =0; + virtual DL_FixedBasePrecomputation & 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 *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 BASE = DL_GroupParameters > +class DL_GroupParametersImpl : public BASE +{ +public: + typedef GROUP_PRECOMP GroupPrecomputation; + typedef typename GROUP_PRECOMP::Element Element; + typedef BASE_PRECOMP BasePrecomputation; + + const DL_GroupPrecomputation & GetGroupPrecomputation() const {return m_groupPrecomputation;} + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return m_gpc;} + DL_FixedBasePrecomputation & AccessBasePrecomputation() {return m_gpc;} + +protected: + GROUP_PRECOMP m_groupPrecomputation; + BASE_PRECOMP m_gpc; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_Key +{ +public: + virtual const DL_GroupParameters & GetAbstractGroupParameters() const =0; + virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; +}; + +//! interface for DL public keys +template +class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key +{ + typedef DL_PublicKey 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 ¶ms = this->GetAbstractGroupParameters(); + return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent); + } + virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const + { + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp); + } + + virtual const DL_FixedBasePrecomputation & GetPublicPrecomputation() const =0; + virtual DL_FixedBasePrecomputation & AccessPublicPrecomputation() =0; +}; + +//! interface for DL private keys +template +class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key +{ + typedef DL_PrivateKey ThisClass; + +public: + typedef T Element; + + void MakePublicKey(DL_PublicKey &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 +void DL_PublicKey::AssignFrom(const NameValuePairs &source) +{ + DL_PrivateKey *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 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 DL_PrivateKeyImpl : public DL_PrivateKey, public DL_KeyImpl +{ +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 >(this, name, valueType, pValue).Assignable(); + } + + void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper >(this, source); + } + + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) + { + if (!params.GetThisObject(this->AccessGroupParameters())) + this->AccessGroupParameters().GenerateRandom(rng, params); +// std::pair 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 & GetAbstractGroupParameters() const {return this->GetGroupParameters();} + DL_GroupParameters & 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 DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE +{ +public: + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) + { + 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 DL_PublicKeyImpl : public DL_PublicKey, public DL_KeyImpl +{ +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 >(this, name, valueType, pValue).Assignable(); + } + + void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper >(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 & GetAbstractGroupParameters() const {return this->GetGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} + + // DL_PublicKey + const DL_FixedBasePrecomputation & GetPublicPrecomputation() const {return m_ypc;} + DL_FixedBasePrecomputation & AccessPublicPrecomputation() {return m_ypc;} + + // non-inherited + bool operator==(const DL_PublicKeyImpl &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 CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm +{ +public: + virtual void Sign(const DL_GroupParameters ¶ms, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0; + virtual bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0; + virtual Integer RecoverPresignature(const DL_GroupParameters ¶ms, const DL_PublicKey &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 ¶ms) const + {return params.GetSubgroupOrder().ByteCount();} + virtual size_t SLen(const DL_GroupParameters ¶ms) const + {return params.GetSubgroupOrder().ByteCount();} +}; + +//! interface for DL key agreement algorithms +template +class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm +{ +public: + typedef T Element; + + virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const =0; + virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0; +}; + +//! interface for key derivation algorithms used in DL cryptosystems +template +class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm +{ +public: + virtual bool ParameterSupported(const char *name) const {return false;} + virtual void Derive(const DL_GroupParameters &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 ¶meters) const =0; + virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_Base +{ +protected: + typedef KI KeyInterface; + typedef typename KI::Element Element; + + const DL_GroupParameters & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();} + + virtual KeyInterface & AccessKeyInterface() =0; + virtual const KeyInterface & GetKeyInterface() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base +{ +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 & GetSignatureAlgorithm() const =0; + virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0; + virtual HashIdentifier GetHashIdentifier() const =0; + virtual size_t GetDigestSize() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase > +{ +public: + // for validation testing + void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const + { + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &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(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(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &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 &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = 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 CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase > +{ +public: + void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const + { + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = 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(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &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(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &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 CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base +{ +public: + typedef typename DL_Base::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 & GetKeyAgreementAlgorithm() const =0; + virtual const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const =0; + virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase > +{ +public: + typedef T Element; + + DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + { + try + { + const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); + const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); + const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &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 CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase > +{ +public: + typedef T Element; + + void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + { + const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); + const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); + const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &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 +struct DL_SchemeOptionsBase +{ + typedef T1 AlgorithmInfo; + typedef T2 GroupParameters; + typedef typename GroupParameters::Element Element; +}; + +//! _ +template +struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase +{ + typedef T2 Keys; + typedef typename Keys::PrivateKey PrivateKey; + typedef typename Keys::PublicKey PublicKey; +}; + +//! _ +template +struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions +{ + typedef T3 SignatureAlgorithm; + typedef T4 MessageEncodingMethod; + typedef T5 HashFunction; +}; + +//! _ +template +struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions +{ + typedef T3 KeyAgreementAlgorithm; + typedef T4 KeyDerivationAlgorithm; + typedef T5 SymmetricEncryptionAlgorithm; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl +{ +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::Lookup(); + } + size_t GetDigestSize() const + { + typedef CPP_TYPENAME SchemeOptions::HashFunction H; + return H::DIGESTSIZE; + } + +private: + KEY m_key; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase +{ +public: + typedef typename KEY::Element Element; + +protected: + const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const + {return Singleton().Ref();} + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const + {return Singleton().Ref();} + const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const + {return Singleton().Ref();} + const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const + {return Singleton().Ref();} + HashIdentifier GetHashIdentifier() const + {return HashIdentifier();} + const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const + {return Singleton().Ref();} +}; + +//! _ +template +class DL_SignerImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> +{ +public: + PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const + { + std::auto_ptr p(new PK_MessageAccumulatorImpl); + this->RestartMessageAccumulator(rng, *p); + return p.release(); + } +}; + +//! _ +template +class DL_VerifierImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> +{ +public: + PK_MessageAccumulator * NewVerificationAccumulator() const + { + return new PK_MessageAccumulatorImpl; + } +}; + +//! _ +template +class DL_EncryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> +{ +}; + +//! _ +template +class DL_DecryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> +{ +}; + +// ******************************************************** + +//! _ +template +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 ¶ms = 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 ¶ms = 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 & GetKeyAgreementAlgorithm() const =0; + virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; + const DL_GroupParameters & GetAbstractGroupParameters() const {return const_cast *>(this)->AccessAbstractGroupParameters();} +}; + +enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION}; +typedef EnumToType NoCofactorMultiplication; +typedef EnumToType CompatibleCofactorMultiplication; +typedef EnumToType IncompatibleCofactorMultiplication; + +//! DH key agreement algorithm +template +class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm +{ +public: + typedef ELEMENT Element; + + static const char * CRYPTOPP_API StaticAlgorithmName() + {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";} + + Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &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 ¶ms, 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 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 + PK_FinalTemplate(T1 &v1, T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} + + template + 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 + 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 + PK_FinalTemplate(const T1 &v1, const T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + 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 + 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 + 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 + 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 + PK_FinalTemplate(T1 &v1, const T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + 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 + 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 + 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 + 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 TF_ES; + +//! Trapdoor Function Based Encryption Scheme +template > +class TF_ES : public KEYS +{ + typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod; + +public: + //! see EncryptionStandard for a list of standards + typedef STANDARD Standard; + typedef TF_CryptoSchemeOptions SchemeOptions; + + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();} + + //! implements PK_Decryptor interface + typedef PK_FinalTemplate > Decryptor; + //! implements PK_Encryptor interface + typedef PK_FinalTemplate > Encryptor; +}; + +template // VC60 workaround: doesn't work if KEYS is first parameter +class TF_SS; + +//! Trapdoor Function Based Signature Scheme +template > // 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 SchemeOptions; + + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} + + //! implements PK_Signer interface + typedef PK_FinalTemplate > Signer; + //! implements PK_Verifier interface + typedef PK_FinalTemplate > Verifier; +}; + +template +class DL_SS; + +//! Discrete Log Based Signature Scheme +template > +class DL_SS : public KEYS +{ + typedef DL_SignatureSchemeOptions SchemeOptions; + +public: + static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";} + + //! implements PK_Signer interface + typedef PK_FinalTemplate > Signer; + //! implements PK_Verifier interface + typedef PK_FinalTemplate > Verifier; +}; + +//! Discrete Log Based Encryption Scheme +template +class DL_ES : public KEYS +{ + typedef DL_CryptoSchemeOptions SchemeOptions; + +public: + //! implements PK_Decryptor interface + typedef PK_FinalTemplate > Decryptor; + //! implements PK_Encryptor interface + typedef PK_FinalTemplate > 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 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 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 > m_keyLength; +}; +*/ + +template +unsigned int PKCS5_PBKDF1::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 +unsigned int PKCS5_PBKDF2_HMAC::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 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 +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 +unsigned int PKCS12_PBKDF::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 0) + { + hash.CalculateDigest(Ai, buffer, buffer.size()); + + if (timeInSeconds) + { + timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size()); + timer.StartTimer(); + } + + for (i=1; inext; 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 ¶meters) +{ + 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(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 ¶meters) +{ + 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 + +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 +{ +public: + ByteQueue(size_t nodeSize=0); + ByteQueue(const ByteQueue ©); + ~ByteQueue(); + + lword MaxRetrievable() const + {return CurrentSize();} + bool AnyRetrievable() const + {return !IsEmpty();} + + void IsolatedInitialize(const NameValuePairs ¶meters); + 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 + { + 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 ¶meters); + + 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 ©); + 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(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(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 +struct RabinES : public TF_ES +{ +}; + +//! Rabin signature +template +struct RabinSS : public TF_SS +{ +}; + +// More typedefs for backwards compatibility +class SHA1; +typedef RabinES >::Decryptor RabinDecryptor; +typedef RabinES >::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 + +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 m_key; + FixedSizeSecBlock m_seed; + member_ptr 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 +// 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 + * author Antoon Bosselaers + * author Paulo Barreto + * + * 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 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 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 +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(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;} +}; + +/// Rijndael +class CRYPTOPP_DLL Rijndael : public Rijndael_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + 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 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; + typedef BlockCipherFinal 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 +#include + +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= 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 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 +{ +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::Verifier x1(1, 1); + RSASS::Signer x2(NullRNG(), 1); + RSASS::Verifier x3(x2); + RSASS::Verifier x4(x2.GetKey()); + RSASS::Verifier x5(x3); +#ifndef __MWERKS__ + RSASS::Signer x6 = x2; + x3 = x2; + x6 = x2; +#endif + RSAES::Encryptor x7(x2); +#ifndef __GNUC__ + RSAES::Encryptor x8(x3); +#endif + RSAES >::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::Signer signer(*this); + RSASS::Verifier verifier(signer); + SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); + + RSAES >::Decryptor decryptor(*this); + RSAES >::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(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(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(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(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; +}; + +//! RSA cryptosystem +template +struct RSAES : public TF_ES +{ +}; + +//! RSA signature scheme with appendix +/*! See documentation of PKCS1v15 for a list of hash functions that can be used with it. */ +template +struct RSASS : public TF_SS +{ +}; + +struct CRYPTOPP_DLL RSA_ISO +{ + static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA-ISO";} + typedef RSAFunction_ISO PublicKey; + typedef InvertibleRSAFunction_ISO PrivateKey; +}; + +template +struct RSASS_ISO : public TF_SS +{ +}; + +// The two RSA encryption schemes defined in PKCS #1 v2.0 +typedef RSAES::Decryptor RSAES_PKCS1v15_Decryptor; +typedef RSAES::Encryptor RSAES_PKCS1v15_Encryptor; + +typedef RSAES >::Decryptor RSAES_OAEP_SHA_Decryptor; +typedef RSAES >::Encryptor RSAES_OAEP_SHA_Encryptor; + +// The three RSA signature schemes defined in PKCS #1 v2.0 +typedef RSASS::Signer RSASSA_PKCS1v15_SHA_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_SHA_Verifier; + +namespace Weak { +typedef RSASS::Signer RSASSA_PKCS1v15_MD2_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_MD2_Verifier; + +typedef RSASS::Signer RSASSA_PKCS1v15_MD5_Signer; +typedef RSASS::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(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(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 +struct RWSS : public TF_SS +{ +}; + +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 ¶ms) +{ + 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 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 ¶ms); + + 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 CRYPTOPP_NO_VTABLE SAFER_Impl : public BlockCipherImpl +{ +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";} +}; + +/// SAFER-K +class SAFER_K : public SAFER_K_Info, public SAFER, public BlockCipherDocumentation +{ +public: + typedef BlockCipherFinal > Encryption; + typedef BlockCipherFinal > 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";} +}; + +/// SAFER-SK +class SAFER_SK : public SAFER_SK_Info, public SAFER, public BlockCipherDocumentation +{ +public: + typedef BlockCipherFinal > Encryption; + typedef BlockCipherFinal > 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 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 +void SEAL_Policy::CipherSetKey(const NameValuePairs ¶ms, 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 +void SEAL_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + assert(length==4); + m_outsideCounter = IV ? GetWord(false, BIG_ENDIAN_ORDER, IV) : 0; + m_startCount = m_outsideCounter; + m_insideCounter = 0; +} + +template +void SEAL_Policy::SeekToIteration(lword iterationCount) +{ + m_outsideCounter = m_startCount + (unsigned int)(iterationCount / m_iterationsPerCount); + m_insideCounter = (unsigned int)(iterationCount % m_iterationsPerCount); +} + +template +void SEAL_Policy::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; +template class SEAL_Policy; + +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 +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 CRYPTOPP_NO_VTABLE SEAL_Policy : public AdditiveCipherConcretePolicy, public SEAL_Info +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, 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 m_T; + FixedSizeSecBlock m_S; + SecBlock m_R; + + word32 m_startCount, m_iterationsPerCount; + word32 m_outsideCounter, m_insideCounter; +}; + +//! SEAL +template +struct SEAL : public SEAL_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, SEAL_Info > 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 + +NAMESPACE_BEGIN(CryptoPP) + +// ************** secure memory allocation *************** + +template +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::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::value_type value_type;\ +typedef typename AllocatorBase::size_type size_type;\ +typedef typename AllocatorBase::difference_type difference_type;\ +typedef typename AllocatorBase::pointer pointer;\ +typedef typename AllocatorBase::const_pointer const_pointer;\ +typedef typename AllocatorBase::reference reference;\ +typedef typename AllocatorBase::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 +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 AllocatorWithCleanup : public AllocatorBase +{ +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 struct rebind { typedef AllocatorWithCleanup other; }; +#if _MSC_VER >= 1500 + AllocatorWithCleanup() {} + template AllocatorWithCleanup(const AllocatorWithCleanup &) {} +#endif +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +#if CRYPTOPP_BOOL_X86 +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; // for Integer +#endif + +template +class NullAllocator : public AllocatorBase +{ +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 , bool T_Align16 = false> +class FixedSizeAllocatorWithCleanup : public AllocatorBase +{ +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 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) + : 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) + { + if (this != &t) + { + New(t.m_size); + memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T)); + } + } + + SecBlock& operator=(const SecBlock &t) + { + Assign(t); + return *this; + } + + // append to this object + SecBlock& operator+=(const SecBlock &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 operator+(const SecBlock &t) + { + SecBlock 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) const + { + return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T)); + } + + bool operator!=(const SecBlock &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 &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 SecByteBlock; +typedef SecBlock > AlignedSecByteBlock; +typedef SecBlock SecWordBlock; + +//! a SecBlock with fixed size, allocated statically +template > +class FixedSizeSecBlock : public SecBlock +{ +public: + explicit FixedSizeSecBlock() : SecBlock(S) {} +}; + +template +class FixedSizeAlignedSecBlock : public FixedSizeSecBlock, T_Align16> > +{ +}; + +//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded +template > > +class SecBlockWithHint : public SecBlock +{ +public: + explicit SecBlockWithHint(size_t size) : SecBlock(size) {} +}; + +template +inline bool operator==(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (true);} +template +inline bool operator!=(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (false);} + +NAMESPACE_END + +NAMESPACE_BEGIN(std) +template +inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &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 +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 +class FixedBlockSize +{ +public: + CRYPTOPP_CONSTANT(BLOCKSIZE = N) +}; + +// ************** rounds *************** + +//! to be inherited by ciphers with fixed number of rounds +template +class FixedRounds +{ +public: + CRYPTOPP_CONSTANT(ROUNDS = R) +}; + +//! to be inherited by ciphers with variable number of rounds +template // 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 ¶m, 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 +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 +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 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 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 CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl > > +{ +public: + unsigned int BlockSize() const {return this->BLOCKSIZE;} +}; + +//! _ +template +class BlockCipherFinal : public ClonableImpl, 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 MessageAuthenticationCodeImpl : public AlgorithmImpl, INFO> +{ +}; + +//! _ +template +class MessageAuthenticationCodeFinal : public ClonableImpl, MessageAuthenticationCodeImpl > +{ +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 ¶ms) +{ + AssertValidKeyLength(length); + + word64 key01, key23; + GetBlock 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>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(key23, 8); + else + key01 = rotrFixed(key01, 8); + } +} + +void SEED::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + typedef BlockGetAndPut Block; + word32 a0, a1, b0, b1, t0, t1; + Block::Get(inBlock)(a0)(a1)(b0)(b1); + + for (int i=0; i, public FixedKeyLength<16>, public FixedRounds<16> +{ + static const char *StaticAlgorithmName() {return "SEED";} +}; + +/// SEED +class SEED : public SEED_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + FixedSizeSecBlock m_k; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal 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 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) + +/// SHA-1 +class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform +{ +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 +{ +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 +{ +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 +{ +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 +{ +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 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";} +}; + +/// SHACAL-2 +class SHACAL2 : public SHACAL2_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock 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; + typedef BlockCipherFinal 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 CRYPTOPP_NO_VTABLE ClonableImpl : public BASE +{ +public: + Clonable * Clone() const {return new DERIVED(*static_cast(this));} +}; + +//! _ +template +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 CRYPTOPP_NO_VTABLE Bufferless : public T +{ +public: + bool IsolatedFlush(bool hardFlush, bool blocking) {return false;} +}; + +//! _ +template +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: 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 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 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 CRYPTOPP_NO_VTABLE CustomSignalPropagation : public CustomFlushPropagation +{ +public: + virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0; + +private: + void IsolatedInitialize(const NameValuePairs ¶meters) {assert(false);} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE Multichannel : public CustomFlushPropagation +{ +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 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 > +{ +public: + Store() : m_messageEnd(false) {} + + void IsolatedInitialize(const NameValuePairs ¶meters) + { + 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 ¶meters) =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 +{ +public: + std::string AlgorithmName() const {return "BitBucket";} + void IsolatedInitialize(const NameValuePairs ¶meters) {} + 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 + +NAMESPACE_BEGIN(CryptoPP) + +template 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 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& rhs); // copy not allowed + void operator=(const member_ptr& rhs); // assignment not allowed + + T *m_p; +}; + +template member_ptr::~member_ptr() {delete m_p;} +template void member_ptr::reset(T *p) {delete m_p; m_p = p;} + +// ******************************************************** + +template class value_ptr : public member_ptr +{ +public: + value_ptr(const T &obj) : member_ptr(new T(obj)) {} + value_ptr(T *p = NULL) : member_ptr(p) {} + value_ptr(const value_ptr& rhs) + : member_ptr(rhs.m_p ? new T(*rhs.m_p) : NULL) {} + + value_ptr& operator=(const value_ptr& rhs); + bool operator==(const value_ptr& rhs) + { + return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p); + } +}; + +template value_ptr& value_ptr::operator=(const value_ptr& 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 clonable_ptr : public member_ptr +{ +public: + clonable_ptr(const T &obj) : member_ptr(obj.Clone()) {} + clonable_ptr(T *p = NULL) : member_ptr(p) {} + clonable_ptr(const clonable_ptr& rhs) + : member_ptr(rhs.m_p ? rhs.m_p->Clone() : NULL) {} + + clonable_ptr& operator=(const clonable_ptr& rhs); +}; + +template clonable_ptr& clonable_ptr::operator=(const clonable_ptr& 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 counted_ptr +{ +public: + explicit counted_ptr(T *p = 0); + counted_ptr(const T &r) : m_p(0) {attach(r);} + counted_ptr(const counted_ptr& 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 & operator=(const counted_ptr& rhs); + +private: + T *m_p; +}; + +template counted_ptr::counted_ptr(T *p) + : m_p(p) +{ + if (m_p) + m_p->m_referenceCount = 1; +} + +template counted_ptr::counted_ptr(const counted_ptr& rhs) + : m_p(rhs.m_p) +{ + if (m_p) + m_p->m_referenceCount++; +} + +template counted_ptr::~counted_ptr() +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; +} + +template void counted_ptr::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(&r); + m_p->m_referenceCount++; + } +} + +template T* counted_ptr::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 counted_ptr & counted_ptr::operator=(const counted_ptr& 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 vector_member_ptrs +{ +public: + vector_member_ptrs(size_t size=0) + : m_size(size), m_ptr(new member_ptr[size]) {} + ~vector_member_ptrs() + {delete [] this->m_ptr;} + + member_ptr& operator[](size_t index) + {assert(indexm_size); return this->m_ptr[index];} + const member_ptr& operator[](size_t index) const + {assert(indexm_size); return this->m_ptr[index];} + + size_t size() const {return this->m_size;} + void resize(size_t newSize) + { + member_ptr *newPtr = new member_ptr[newSize]; + for (size_t i=0; im_size && im_ptr[i].release()); + delete [] this->m_ptr; + this->m_size = newSize; + this->m_ptr = newPtr; + } + +private: + vector_member_ptrs(const vector_member_ptrs &c); // copy not allowed + void operator=(const vector_member_ptrs &x); // assignment not allowed + + size_t m_size; + member_ptr *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 +#include +#include +#include +#include +#include +#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(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(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 +#include "winpipes.h" +#else +#include +#include +#include +#include +#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 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, public FixedKeyLength<16>, FixedRounds<8> +{ + static const char *StaticAlgorithmName() {return "Square";} +}; + +/// Square +class Square : public Square_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock 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; + typedef BlockCipherFinal 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CRYPTOPP_INCLUDE_VECTOR_CC +// workaround needed on Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21 +#include +#endif + +// for alloca +#ifdef __sun +#include +#elif defined(__MINGW32__) || defined(__BORLANDC__) +#include +#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 +void AdditiveCipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + 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 +void AdditiveCipherTemplate::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 +void AdditiveCipherTemplate::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 +void AdditiveCipherTemplate::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 +void AdditiveCipherTemplate::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 +void CFB_CipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + 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 +void CFB_CipherTemplate::Resynchronize(const byte *iv, int length) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length)); + m_leftOver = policy.GetBytesPerIteration(); +} + +template +void CFB_CipherTemplate::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 +void CFB_EncryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) +{ + xorbuf(reg, message, length); + memcpy(output, reg, length); +} + +template +void CFB_DecryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) +{ + for (unsigned int i=0; i, 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 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 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 ¶ms, 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 +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();} +#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(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 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 ¶ms); + + 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 ¶ms, 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 +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 + struct RegisterOutput + { + RegisterOutput(byte *output, const byte *input, CipherDir dir) + : m_output(output), m_input(input), m_dir(dir) {} + + inline RegisterOutput& operator()(WordType ®isterWord) + { + assert(IsAligned(m_output)); + assert(IsAligned(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 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 ¶ms); + + size_t m_leftOver; +}; + +template > +class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return true;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); +}; + +template > +class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return false;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); +}; + +template +class CFB_RequireFullDataBlocks : public BASE +{ +public: + unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} +}; + +//! _ +template +class SymmetricCipherFinal : public AlgorithmImpl, 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(new SymmetricCipherFinal(*this));} +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "strciphr.cpp" +#endif + +NAMESPACE_BEGIN(CryptoPP) +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder; +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; +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 Block; + +void TEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms) +{ + 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 ¶ms) +{ + 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";} +}; + +/// TEA +class TEA : public TEA_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock 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; + typedef BlockCipherFinal 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";} +}; + +/// XTEA +class XTEA : public XTEA_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock 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; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct BTEA_Info : public FixedKeyLength<16> +{ + static const char *StaticAlgorithmName() {return "BTEA";} +}; + +//! corrected Block TEA (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, BTEA_Info>, public BTEA_Info + { + public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) + { + 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 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; + typedef BlockCipherFinal 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) + +/// Tiger +class Tiger : public IteratedHashWithStaticTransform +{ +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 +#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 +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 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 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 +{ +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 ¶ms); + 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 m_digest; + FixedSizeSecBlock m_key; +}; + +//! Two-Track-MAC +/*! 160 Bit MAC with 160 Bit Key */ +DOCUMENTED_TYPEDEF(MessageAuthenticationCodeFinal, 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 +#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 ¶ms) +{ + 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 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(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(true, BIG_ENDIAN_ORDER, out.BytePtr()) & mpoly; + m_polyState()[i*4+3] = GetWord(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(true, BIG_ENDIAN_ORDER, out.BytePtr()); + l3Key[i*2+1] = GetWord(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>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 +#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> 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(data, blocksRemainingInWord64); + else + VHASH_Update_Template(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(true, BIG_ENDIAN_ORDER, m_pad()); + t[1] = L3Hash(m_polyState()+4, m_l3Key()+2, len) + GetWord(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(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 +{ +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 ¶ms); + 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(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 +#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; +}; + +/// VMAC +template +class VMAC : public SimpleKeyingInterfaceImpl > +{ +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 +#include +#include +#include +#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 pThread((WaitingThreadData *)lParam); + WaitingThreadData &thread = *pThread; + std::vector 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 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 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 + +#ifdef USE_WINDOWS_STYLE_SOCKETS +#include +#else +#include +#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 m_handles; + std::vector 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 + +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> (WORD_BITS-shiftBits); + } + return carry; +} + +inline word ShiftWordsRightByBits(word *r, size_t n, unsigned int shiftBits) +{ + assert (shiftBits0; 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 Date: Sun, 24 Nov 2013 14:21:35 +0000 Subject: Moved expat --- lib/expat/ascii.h | 92 + lib/expat/asciitab.h | 36 + lib/expat/expat.h | 1014 +++++++ lib/expat/expat_external.h | 115 + lib/expat/iasciitab.h | 37 + lib/expat/internal.h | 73 + lib/expat/latin1tab.h | 36 + lib/expat/nametab.h | 150 ++ lib/expat/utf8tab.h | 37 + lib/expat/winconfig.h | 30 + lib/expat/xmlparse.c | 6294 ++++++++++++++++++++++++++++++++++++++++++++ lib/expat/xmlrole.c | 1482 +++++++++++ lib/expat/xmlrole.h | 114 + lib/expat/xmltok.c | 1684 ++++++++++++ lib/expat/xmltok.h | 316 +++ lib/expat/xmltok_impl.c | 1800 +++++++++++++ lib/expat/xmltok_impl.h | 46 + lib/expat/xmltok_ns.c | 119 + 18 files changed, 13475 insertions(+) create mode 100644 lib/expat/ascii.h create mode 100644 lib/expat/asciitab.h create mode 100644 lib/expat/expat.h create mode 100644 lib/expat/expat_external.h create mode 100644 lib/expat/iasciitab.h create mode 100644 lib/expat/internal.h create mode 100644 lib/expat/latin1tab.h create mode 100644 lib/expat/nametab.h create mode 100644 lib/expat/utf8tab.h create mode 100644 lib/expat/winconfig.h create mode 100644 lib/expat/xmlparse.c create mode 100644 lib/expat/xmlrole.c create mode 100644 lib/expat/xmlrole.h create mode 100644 lib/expat/xmltok.c create mode 100644 lib/expat/xmltok.h create mode 100644 lib/expat/xmltok_impl.c create mode 100644 lib/expat/xmltok_impl.h create mode 100644 lib/expat/xmltok_ns.c (limited to 'lib') 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 +#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 (), 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 +#undef WIN32_LEAN_AND_MEAN + +#include +#include + +#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 +#include /* memset(), memcpy() */ +#include + +#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 +#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 + +#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 +#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 + +#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 +#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 */ +#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 /* */ +#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_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 " */ + 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 " 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 " 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 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 */ -- cgit v1.2.3 From 9c10729f007aad4b75d9a3dbdf01b39a193e069c Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Sun, 24 Nov 2013 14:22:15 +0000 Subject: Moved iniFile --- lib/inifile/iniFile.cpp | 807 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/inifile/iniFile.h | 205 ++++++++++++ 2 files changed, 1012 insertions(+) create mode 100644 lib/inifile/iniFile.cpp create mode 100644 lib/inifile/iniFile.h (limited to 'lib') 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 + +// C Includes +#include + +// 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::iterator npos = keys[keyID].names.begin() + valueID; + vector::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::iterator npos = names.begin() + keyID; + vector::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::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::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 names; + std::vector values; + std::vector comments; + } ; + + std::vector keys; + std::vector names; + std::vector 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 .example.ini, and + writes its contents as .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 -- cgit v1.2.3 From 4c67f49c87feeec821a3b1e239157fd80992b798 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Sun, 24 Nov 2013 14:24:26 +0000 Subject: Moved JSONCPP --- lib/jsoncpp/include/json/autolink.h | 19 + lib/jsoncpp/include/json/config.h | 43 + lib/jsoncpp/include/json/features.h | 42 + lib/jsoncpp/include/json/forwards.h | 39 + lib/jsoncpp/include/json/json.h | 10 + lib/jsoncpp/include/json/reader.h | 196 +++ lib/jsoncpp/include/json/value.h | 1069 ++++++++++++++ lib/jsoncpp/include/json/writer.h | 174 +++ lib/jsoncpp/src/lib_json/json_batchallocator.h | 125 ++ lib/jsoncpp/src/lib_json/json_internalarray.inl | 448 ++++++ lib/jsoncpp/src/lib_json/json_internalmap.inl | 607 ++++++++ lib/jsoncpp/src/lib_json/json_reader.cpp | 885 ++++++++++++ lib/jsoncpp/src/lib_json/json_value.cpp | 1727 +++++++++++++++++++++++ lib/jsoncpp/src/lib_json/json_valueiterator.inl | 292 ++++ lib/jsoncpp/src/lib_json/json_writer.cpp | 829 +++++++++++ lib/jsoncpp/src/lib_json/sconscript | 8 + 16 files changed, 6513 insertions(+) create mode 100644 lib/jsoncpp/include/json/autolink.h create mode 100644 lib/jsoncpp/include/json/config.h create mode 100644 lib/jsoncpp/include/json/features.h create mode 100644 lib/jsoncpp/include/json/forwards.h create mode 100644 lib/jsoncpp/include/json/json.h create mode 100644 lib/jsoncpp/include/json/reader.h create mode 100644 lib/jsoncpp/include/json/value.h create mode 100644 lib/jsoncpp/include/json/writer.h create mode 100644 lib/jsoncpp/src/lib_json/json_batchallocator.h create mode 100644 lib/jsoncpp/src/lib_json/json_internalarray.inl create mode 100644 lib/jsoncpp/src/lib_json/json_internalmap.inl create mode 100644 lib/jsoncpp/src/lib_json/json_reader.cpp create mode 100644 lib/jsoncpp/src/lib_json/json_value.cpp create mode 100644 lib/jsoncpp/src/lib_json/json_valueiterator.inl create mode 100644 lib/jsoncpp/src/lib_json/json_writer.cpp create mode 100644 lib/jsoncpp/src/lib_json/sconscript (limited to 'lib') 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 +# 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 +# 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 +# include +# include +# include + +namespace Json { + + /** \brief Unserialize a JSON 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 JSON 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 JSON 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 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 ¤t, + Location end, + unsigned int &unicode ); + bool decodeUnicodeEscapeSequence( Token &token, + Location ¤t, + 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 ¤tValue(); + 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 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 +# include + +# ifndef JSON_USE_CPPTL_SMALLMAP +# include +# else +# include +# endif +# ifdef JSON_USE_CPPTL +# include +# 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 EnumMemberNames; +// typedef CppTL::AnyEnumerator 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 JSON 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 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 ObjectValues; +# else + typedef CppTL::SmallMap 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 InArgs; + typedef std::vector 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( newIndexes ); + } + virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) + { + if ( indexes ) + free( indexes ); + } + + virtual Value *allocateArrayPage() + { + return static_cast( 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 ¤t ); +#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 ¤t ); +#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 ¤t ); +#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 +# include +# include + +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 JSON 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 JSON 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 JSON 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 ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; + }; + + /** \brief Writes a Value in JSON 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 JSON 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 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 +# include + +# 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 +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( 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( newIndexes ); + } + virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) + { + if ( indexes ) + free( indexes ); + } + + virtual Value *allocateArrayPage() + { + return static_cast( 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( newIndexes ); + } + virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) + { + if ( indexes ) + free( indexes ); + } + + virtual Value *allocateArrayPage() + { + return static_cast( pagesAllocator_.allocate() ); + } + + virtual void releaseArrayPage( Value *value ) + { + if ( value ) + pagesAllocator_.release( value ); + } +private: + BatchAllocator arraysAllocator_; + BatchAllocator 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( this ); + it.currentItemIndex_ = 0; + it.currentPageIndex_ = pages_; +} + + +void +ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const +{ + it.array_ = const_cast( 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 mapsAllocator_; + BatchAllocator 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 ¤t->items_[index]; + } + } + return 0; +} + + +Value * +ValueInternalMap::find( const char *key ) +{ + const ValueInternalMap *constThis = this; + return const_cast( 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 = ¤t->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( this ); + it.bucketIndex_ = 0; + it.itemIndex_ = 0; + it.link_ = buckets_; +} + + +void +ValueInternalMap::makeEndIterator( IteratorState &it ) const +{ + it.map_ = const_cast( 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..7c94e612e --- /dev/null +++ b/lib/jsoncpp/src/lib_json/json_reader.cpp @@ -0,0 +1,885 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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(cp); + } + else if (cp <= 0x7FF) + { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } + else if (cp <= 0xFFFF) + { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } + else if (cp <= 0x10FFFF) + { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(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 begin(sin); + //std::istream_iterator 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_ = ¤tValue(); + } + + 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 ¤t, + 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 ¤t, + 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..89271cd00 --- /dev/null +++ b/lib/jsoncpp/src/lib_json/json_value.cpp @@ -0,0 +1,1727 @@ +#include +#include +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +# include +#endif +#include // 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( 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( 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( 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( 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( 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() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +//EnumValues +//Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// 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 ¤t ) + : 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 ¤t ) + : 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 ¤t ) + : 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..cdf4188f2 --- /dev/null +++ b/lib/jsoncpp/src/lib_json/json_writer.cpp @@ -0,0 +1,829 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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 *¤t ) +{ + *--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 (*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..f6520d185 --- /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' ) -- cgit v1.2.3 From d7ca8ea57b3a189fae5d7f69693ca656e6deedae Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Sun, 24 Nov 2013 14:27:32 +0000 Subject: Moved Lua --- lib/lua/COPYRIGHT | 34 ++ lib/lua/HISTORY | 183 +++++++ lib/lua/INSTALL | 99 ++++ lib/lua/Makefile | 128 +++++ lib/lua/README | 37 ++ lib/lua/src/Makefile | 182 +++++++ lib/lua/src/lapi.c | 1087 +++++++++++++++++++++++++++++++++++++++ lib/lua/src/lapi.h | 16 + lib/lua/src/lauxlib.c | 652 +++++++++++++++++++++++ lib/lua/src/lauxlib.h | 174 +++++++ lib/lua/src/lbaselib.c | 653 +++++++++++++++++++++++ lib/lua/src/lcode.c | 839 ++++++++++++++++++++++++++++++ lib/lua/src/lcode.h | 76 +++ lib/lua/src/ldblib.c | 397 ++++++++++++++ lib/lua/src/ldebug.c | 638 +++++++++++++++++++++++ lib/lua/src/ldebug.h | 33 ++ lib/lua/src/ldo.c | 518 +++++++++++++++++++ lib/lua/src/ldo.h | 57 +++ lib/lua/src/ldump.c | 164 ++++++ lib/lua/src/lfunc.c | 174 +++++++ lib/lua/src/lfunc.h | 34 ++ lib/lua/src/lgc.c | 711 +++++++++++++++++++++++++ lib/lua/src/lgc.h | 110 ++++ lib/lua/src/linit.c | 38 ++ lib/lua/src/liolib.c | 553 ++++++++++++++++++++ lib/lua/src/llex.c | 465 +++++++++++++++++ lib/lua/src/llex.h | 81 +++ lib/lua/src/llimits.h | 128 +++++ lib/lua/src/lmathlib.c | 263 ++++++++++ lib/lua/src/lmem.c | 86 ++++ lib/lua/src/lmem.h | 49 ++ lib/lua/src/loadlib.c | 666 ++++++++++++++++++++++++ lib/lua/src/lobject.c | 214 ++++++++ lib/lua/src/lobject.h | 381 ++++++++++++++ lib/lua/src/lopcodes.c | 102 ++++ lib/lua/src/lopcodes.h | 268 ++++++++++ lib/lua/src/loslib.c | 243 +++++++++ lib/lua/src/lparser.c | 1339 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/lua/src/lparser.h | 82 +++ lib/lua/src/lstate.c | 214 ++++++++ lib/lua/src/lstate.h | 169 ++++++ lib/lua/src/lstring.c | 111 ++++ lib/lua/src/lstring.h | 31 ++ lib/lua/src/lstrlib.c | 869 +++++++++++++++++++++++++++++++ lib/lua/src/ltable.c | 588 +++++++++++++++++++++ lib/lua/src/ltable.h | 40 ++ lib/lua/src/ltablib.c | 287 +++++++++++ lib/lua/src/ltm.c | 75 +++ lib/lua/src/ltm.h | 54 ++ lib/lua/src/lua.c | 392 ++++++++++++++ lib/lua/src/lua.h | 390 ++++++++++++++ lib/lua/src/luac.c | 202 ++++++++ lib/lua/src/luaconf.h | 763 +++++++++++++++++++++++++++ lib/lua/src/lualib.h | 53 ++ lib/lua/src/lundump.c | 227 ++++++++ lib/lua/src/lundump.h | 36 ++ lib/lua/src/lvm.c | 763 +++++++++++++++++++++++++++ lib/lua/src/lvm.h | 36 ++ lib/lua/src/lzio.c | 82 +++ lib/lua/src/lzio.h | 67 +++ lib/lua/src/print.c | 227 ++++++++ 61 files changed, 17630 insertions(+) create mode 100644 lib/lua/COPYRIGHT create mode 100644 lib/lua/HISTORY create mode 100644 lib/lua/INSTALL create mode 100644 lib/lua/Makefile create mode 100644 lib/lua/README create mode 100644 lib/lua/src/Makefile create mode 100644 lib/lua/src/lapi.c create mode 100644 lib/lua/src/lapi.h create mode 100644 lib/lua/src/lauxlib.c create mode 100644 lib/lua/src/lauxlib.h create mode 100644 lib/lua/src/lbaselib.c create mode 100644 lib/lua/src/lcode.c create mode 100644 lib/lua/src/lcode.h create mode 100644 lib/lua/src/ldblib.c create mode 100644 lib/lua/src/ldebug.c create mode 100644 lib/lua/src/ldebug.h create mode 100644 lib/lua/src/ldo.c create mode 100644 lib/lua/src/ldo.h create mode 100644 lib/lua/src/ldump.c create mode 100644 lib/lua/src/lfunc.c create mode 100644 lib/lua/src/lfunc.h create mode 100644 lib/lua/src/lgc.c create mode 100644 lib/lua/src/lgc.h create mode 100644 lib/lua/src/linit.c create mode 100644 lib/lua/src/liolib.c create mode 100644 lib/lua/src/llex.c create mode 100644 lib/lua/src/llex.h create mode 100644 lib/lua/src/llimits.h create mode 100644 lib/lua/src/lmathlib.c create mode 100644 lib/lua/src/lmem.c create mode 100644 lib/lua/src/lmem.h create mode 100644 lib/lua/src/loadlib.c create mode 100644 lib/lua/src/lobject.c create mode 100644 lib/lua/src/lobject.h create mode 100644 lib/lua/src/lopcodes.c create mode 100644 lib/lua/src/lopcodes.h create mode 100644 lib/lua/src/loslib.c create mode 100644 lib/lua/src/lparser.c create mode 100644 lib/lua/src/lparser.h create mode 100644 lib/lua/src/lstate.c create mode 100644 lib/lua/src/lstate.h create mode 100644 lib/lua/src/lstring.c create mode 100644 lib/lua/src/lstring.h create mode 100644 lib/lua/src/lstrlib.c create mode 100644 lib/lua/src/ltable.c create mode 100644 lib/lua/src/ltable.h create mode 100644 lib/lua/src/ltablib.c create mode 100644 lib/lua/src/ltm.c create mode 100644 lib/lua/src/ltm.h create mode 100644 lib/lua/src/lua.c create mode 100644 lib/lua/src/lua.h create mode 100644 lib/lua/src/luac.c create mode 100644 lib/lua/src/luaconf.h create mode 100644 lib/lua/src/lualib.h create mode 100644 lib/lua/src/lundump.c create mode 100644 lib/lua/src/lundump.h create mode 100644 lib/lua/src/lvm.c create mode 100644 lib/lua/src/lvm.h create mode 100644 lib/lua/src/lzio.c create mode 100644 lib/lua/src/lzio.h create mode 100644 lib/lua/src/print.c (limited to 'lib') 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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#include + + +/* 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; ifunc, 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 +#include + +#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 +#include +#include +#include + +#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 + +#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 +#include +#include + +#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 +#include +#include + + +#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; il.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 +#include +#include + +#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; itop - 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; itop++, 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 + +#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; ik[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; ip[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; ilocvars[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; iupvalues[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 + +#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; isizelocvars && 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 + +#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; isizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i=0; isizeupvalues; i++) { /* mark upvalue names */ + if (f->upvalues[i]) + stringmark(f->upvalues[i]); + } + for (i=0; isizep; i++) { /* mark nested protos */ + if (f->p[i]) + markobject(g, f->p[i]); + } + for (i=0; isizelocvars; 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; ic.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; il.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; imt[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 +#include +#include +#include + +#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 +#include +#include + +#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", + "..", "...", "==", ">=", "<=", "~=", + "", "", "", "", + 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; itsv.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 +#include + + +#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 +#include + +#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 + +#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 + +#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 +#include + + +#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 + +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 + + +#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 + + +/* 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 +#include +#include +#include +#include + +#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 + + +#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<

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<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< 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)*/ +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 +#include +#include +#include +#include + +#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 + +#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; inups; 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; if->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, " 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 + +#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; imt[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 + +#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; isize; 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 +#include +#include +#include +#include + +#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 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= 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)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 (ssrc_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 = ssrc_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 +#include + +#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; iarray[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; ilsizenode = 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; iarray[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 + +#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= 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 + +#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; itmname[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<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 +#include +#include +#include + +#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("")) - 1); + if (strstr(msg, LUA_QL("")) == 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 +#include + +#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 (`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 +#include +#include +#include + +#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; itop+(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; ip[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; i1); + 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 +#include + + +/* +** ================================================================== +** 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 +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include +#include +#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 +#include +#include +#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 +#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 +#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 +#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 + +#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; ik[i]); + for (i=0; ik[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; ip[i]=NULL; + for (i=0; ip[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; ilocvars[i].varname=NULL; + for (i=0; ilocvars[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; iupvalues[i]=NULL; + for (i=0; iupvalues[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 +#include +#include + +#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; jl.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 + +#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 +#include + +#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; ik[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; pc0) 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; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[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; iupvalues[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; ip[i],full); +} -- cgit v1.2.3 From 1de69f5b54045192db4b8240739f72bac1fd1d09 Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Sun, 24 Nov 2013 14:28:29 +0000 Subject: Moved zlib --- lib/zlib/adler32.c | 179 +++++ lib/zlib/compress.c | 80 +++ lib/zlib/crc32.c | 425 +++++++++++ lib/zlib/crc32.h | 441 ++++++++++++ lib/zlib/deflate.c | 1965 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/zlib/deflate.h | 346 +++++++++ lib/zlib/example.c | 601 ++++++++++++++++ lib/zlib/gzclose.c | 25 + lib/zlib/gzguts.h | 193 +++++ lib/zlib/gzlib.c | 620 ++++++++++++++++ lib/zlib/gzread.c | 589 +++++++++++++++ lib/zlib/gzwrite.c | 565 +++++++++++++++ lib/zlib/infback.c | 640 +++++++++++++++++ lib/zlib/inffast.c | 340 +++++++++ lib/zlib/inffast.h | 11 + lib/zlib/inffixed.h | 94 +++ lib/zlib/inflate.c | 1496 +++++++++++++++++++++++++++++++++++++++ lib/zlib/inflate.h | 122 ++++ lib/zlib/inftrees.c | 306 ++++++++ lib/zlib/inftrees.h | 62 ++ lib/zlib/minigzip.c | 631 +++++++++++++++++ lib/zlib/trees.c | 1224 ++++++++++++++++++++++++++++++++ lib/zlib/trees.h | 128 ++++ lib/zlib/uncompr.c | 59 ++ lib/zlib/zconf.h | 506 +++++++++++++ lib/zlib/zlib.h | 1744 +++++++++++++++++++++++++++++++++++++++++++++ lib/zlib/zutil.c | 324 +++++++++ lib/zlib/zutil.h | 252 +++++++ 28 files changed, 13968 insertions(+) create mode 100644 lib/zlib/adler32.c create mode 100644 lib/zlib/compress.c create mode 100644 lib/zlib/crc32.c create mode 100644 lib/zlib/crc32.h create mode 100644 lib/zlib/deflate.c create mode 100644 lib/zlib/deflate.h create mode 100644 lib/zlib/example.c create mode 100644 lib/zlib/gzclose.c create mode 100644 lib/zlib/gzguts.h create mode 100644 lib/zlib/gzlib.c create mode 100644 lib/zlib/gzread.c create mode 100644 lib/zlib/gzwrite.c create mode 100644 lib/zlib/infback.c create mode 100644 lib/zlib/inffast.c create mode 100644 lib/zlib/inffast.h create mode 100644 lib/zlib/inffixed.h create mode 100644 lib/zlib/inflate.c create mode 100644 lib/zlib/inflate.h create mode 100644 lib/zlib/inftrees.c create mode 100644 lib/zlib/inftrees.h create mode 100644 lib/zlib/minigzip.c create mode 100644 lib/zlib/trees.c create mode 100644 lib/zlib/trees.h create mode 100644 lib/zlib/uncompr.c create mode 100644 lib/zlib/zconf.h create mode 100644 lib/zlib/zlib.h create mode 100644 lib/zlib/zutil.c create mode 100644 lib/zlib/zutil.h (limited to 'lib') 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 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 +# 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)<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 + +#ifdef STDC +# include +# include +#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 +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif +#include + +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#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 +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include +# 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); /* 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 + +/* -- 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 + +/* + 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 + +#ifdef STDC +# include +# include +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# ifdef UNDER_CE +# include +# 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 /* 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 +# 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 /* 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 */ + +/* 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 +#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< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 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 +# 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<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 + /* 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 +# 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 /* for off_t */ +# endif +#endif + +#ifdef _WIN32 +# include /* 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 /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* 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 +# endif +# include +# include +#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 +# endif +# else /* MSC or DJGPP */ +# include +# 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 +# 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 /* 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 + 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 */ -- cgit v1.2.3 From 998fb17fdc150bc9c6b3d8da0dd37dfd1ae7b39a Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Sun, 24 Nov 2013 14:29:35 +0000 Subject: Moved tolua++ --- lib/tolua++/COPYRIGHT | 33 + lib/tolua++/INSTALL | 42 + lib/tolua++/Makefile | 5 + lib/tolua++/README | 30 + lib/tolua++/README-5.1 | 50 + lib/tolua++/SConstruct | 180 + lib/tolua++/include/tolua++.h | 186 + lib/tolua++/src/bin/SCsub | 12 + lib/tolua++/src/bin/lua/all.lua | 30 + lib/tolua++/src/bin/lua/array.lua | 233 + lib/tolua++/src/bin/lua/basic.lua | 414 + lib/tolua++/src/bin/lua/class.lua | 202 + lib/tolua++/src/bin/lua/clean.lua | 79 + lib/tolua++/src/bin/lua/code.lua | 105 + lib/tolua++/src/bin/lua/compat-5.1.lua | 57 + lib/tolua++/src/bin/lua/compat.lua | 193 + lib/tolua++/src/bin/lua/container.lua | 786 ++ lib/tolua++/src/bin/lua/custom.lua | 45 + lib/tolua++/src/bin/lua/declaration.lua | 579 ++ lib/tolua++/src/bin/lua/define.lua | 63 + lib/tolua++/src/bin/lua/doit.lua | 102 + lib/tolua++/src/bin/lua/enumerate.lua | 106 + lib/tolua++/src/bin/lua/feature.lua | 139 + lib/tolua++/src/bin/lua/function.lua | 577 ++ lib/tolua++/src/bin/lua/module.lua | 68 + lib/tolua++/src/bin/lua/namespace.lua | 52 + lib/tolua++/src/bin/lua/operator.lua | 220 + lib/tolua++/src/bin/lua/package.lua | 343 + lib/tolua++/src/bin/lua/template_class.lua | 82 + lib/tolua++/src/bin/lua/typedef.lua | 71 + lib/tolua++/src/bin/lua/variable.lua | 300 + lib/tolua++/src/bin/lua/verbatim.lua | 78 + lib/tolua++/src/bin/tolua.c | 169 + lib/tolua++/src/bin/tolua_scons.pkg | 31 + lib/tolua++/src/bin/toluabind.c | 8107 ++++++++++++++++++++ lib/tolua++/src/bin/toluabind.h | 8 + lib/tolua++/src/bin/toluabind_default.c | 8009 +++++++++++++++++++ lib/tolua++/src/bin/toluabind_default.h | 8 + lib/tolua++/src/lib/SCsub | 18 + lib/tolua++/src/lib/tolua_event.c | 536 ++ lib/tolua++/src/lib/tolua_event.h | 24 + lib/tolua++/src/lib/tolua_is.c | 621 ++ lib/tolua++/src/lib/tolua_map.c | 704 ++ lib/tolua++/src/lib/tolua_push.c | 171 + lib/tolua++/src/lib/tolua_to.c | 133 + lib/tolua++/win32/tolualib/tolualib.vcproj | 197 + .../tolualib/tolualib.vcproj.LAPTOPF.Kevin.user | 65 + lib/tolua++/win32/tolualib/tolualib.vcxproj | 80 + .../win32/tolualib/tolualib.vcxproj.filters | 39 + lib/tolua++/win32/tolualib/tolualib.vcxproj.user | 3 + lib/tolua++/win32/vc7/clean.bat | 15 + lib/tolua++/win32/vc7/toluapp.sln | 48 + lib/tolua++/win32/vc7/toluapp.vcproj | 439 ++ .../win32/vc7/toluapp.vcproj.LAPTOPF.Kevin.user | 121 + lib/tolua++/win32/vc7/toluapp.vcxproj | 176 + lib/tolua++/win32/vc7/toluapp.vcxproj.filters | 45 + lib/tolua++/win32/vc7/toluapp.vcxproj.user | 3 + 57 files changed, 25232 insertions(+) create mode 100644 lib/tolua++/COPYRIGHT create mode 100644 lib/tolua++/INSTALL create mode 100644 lib/tolua++/Makefile create mode 100644 lib/tolua++/README create mode 100644 lib/tolua++/README-5.1 create mode 100644 lib/tolua++/SConstruct create mode 100644 lib/tolua++/include/tolua++.h create mode 100644 lib/tolua++/src/bin/SCsub create mode 100644 lib/tolua++/src/bin/lua/all.lua create mode 100644 lib/tolua++/src/bin/lua/array.lua create mode 100644 lib/tolua++/src/bin/lua/basic.lua create mode 100644 lib/tolua++/src/bin/lua/class.lua create mode 100644 lib/tolua++/src/bin/lua/clean.lua create mode 100644 lib/tolua++/src/bin/lua/code.lua create mode 100644 lib/tolua++/src/bin/lua/compat-5.1.lua create mode 100644 lib/tolua++/src/bin/lua/compat.lua create mode 100644 lib/tolua++/src/bin/lua/container.lua create mode 100644 lib/tolua++/src/bin/lua/custom.lua create mode 100644 lib/tolua++/src/bin/lua/declaration.lua create mode 100644 lib/tolua++/src/bin/lua/define.lua create mode 100644 lib/tolua++/src/bin/lua/doit.lua create mode 100644 lib/tolua++/src/bin/lua/enumerate.lua create mode 100644 lib/tolua++/src/bin/lua/feature.lua create mode 100644 lib/tolua++/src/bin/lua/function.lua create mode 100644 lib/tolua++/src/bin/lua/module.lua create mode 100644 lib/tolua++/src/bin/lua/namespace.lua create mode 100644 lib/tolua++/src/bin/lua/operator.lua create mode 100644 lib/tolua++/src/bin/lua/package.lua create mode 100644 lib/tolua++/src/bin/lua/template_class.lua create mode 100644 lib/tolua++/src/bin/lua/typedef.lua create mode 100644 lib/tolua++/src/bin/lua/variable.lua create mode 100644 lib/tolua++/src/bin/lua/verbatim.lua create mode 100644 lib/tolua++/src/bin/tolua.c create mode 100644 lib/tolua++/src/bin/tolua_scons.pkg create mode 100644 lib/tolua++/src/bin/toluabind.c create mode 100644 lib/tolua++/src/bin/toluabind.h create mode 100644 lib/tolua++/src/bin/toluabind_default.c create mode 100644 lib/tolua++/src/bin/toluabind_default.h create mode 100644 lib/tolua++/src/lib/SCsub create mode 100644 lib/tolua++/src/lib/tolua_event.c create mode 100644 lib/tolua++/src/lib/tolua_event.h create mode 100644 lib/tolua++/src/lib/tolua_is.c create mode 100644 lib/tolua++/src/lib/tolua_map.c create mode 100644 lib/tolua++/src/lib/tolua_push.c create mode 100644 lib/tolua++/src/lib/tolua_to.c create mode 100644 lib/tolua++/win32/tolualib/tolualib.vcproj create mode 100644 lib/tolua++/win32/tolualib/tolualib.vcproj.LAPTOPF.Kevin.user create mode 100644 lib/tolua++/win32/tolualib/tolualib.vcxproj create mode 100644 lib/tolua++/win32/tolualib/tolualib.vcxproj.filters create mode 100644 lib/tolua++/win32/tolualib/tolualib.vcxproj.user create mode 100644 lib/tolua++/win32/vc7/clean.bat create mode 100644 lib/tolua++/win32/vc7/toluapp.sln create mode 100644 lib/tolua++/win32/vc7/toluapp.vcproj create mode 100644 lib/tolua++/win32/vc7/toluapp.vcproj.LAPTOPF.Kevin.user create mode 100644 lib/tolua++/win32/vc7/toluapp.vcxproj create mode 100644 lib/tolua++/win32/vc7/toluapp.vcxproj.filters create mode 100644 lib/tolua++/win32/vc7/toluapp.vcxproj.user (limited to 'lib') 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 /bin, /lib and /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..ed5344926 --- /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.h" +#include "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 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/bin/tolua.c b/lib/tolua++/src/bin/tolua.c new file mode 100644 index 000000000..cc9f9adcd --- /dev/null +++ b/lib/tolua++/src/bin/tolua.c @@ -0,0 +1,169 @@ +/* tolua +** Support code for Lua bindings. +** Written by Waldemar Celes +** TeCGraf/PUC-Rio +** Aug 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 "tolua++.h" + +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" + +#include +#include +#include + + +static void help (void) +{ + fprintf(stderr,"\n" + "usage: tolua++ [options] input_file\n" + "\n" + "Command line options are:\n" + " -v : print version information.\n" + " -o file : set output file; default is stdout.\n" + " -H file : create include file.\n" + " -n name : set package name; default is input file root name.\n" + " -p : parse only.\n" + " -P : parse and print structure information (for debug).\n" + " -S : disable support for c++ strings.\n" + " -1 : substract 1 to operator[] index (for compatibility with tolua5).\n" + " -L file : run lua file (with dofile()) before doing anything.\n" + " -D : disable automatic exporting of destructors for classes that have\n" + " constructors (for compatibility with tolua5)\n" + " -W : disable warnings for unsupported features (for compatibility\n" + " with tolua5)\n" + " -C : disable cleanup of included lua code (for easier debugging)\n" + " -E value[=value] : add extra values to the luastate\n" + " -t : export a list of types asociates with the C++ typeid name\n" + " -q : don't print warnings to the console\n" + " -h : print this message.\n" + "Should the input file be omitted, stdin is assumed;\n" + "in that case, the package name must be explicitly set.\n\n" + ); +} + +static void version (void) +{ + fprintf(stderr, "%s (written by W. Celes, A. Manzur)\n",TOLUA_VERSION); +} + +static void setfield (lua_State* L, int table, char* f, char* v) +{ + lua_pushstring(L,f); + lua_pushstring(L,v); + lua_settable(L,table); +} + +static void add_extra (lua_State* L, char* value) { + int len; + lua_getglobal(L, "_extra_parameters"); + len = luaL_getn(L, -1); + lua_pushstring(L, value); + lua_rawseti(L, -2, len+1); + lua_pop(L, 1); +}; + +static void error (char* o) +{ + fprintf(stderr,"tolua: unknown option '%s'\n",o); + help(); + exit(1); +} + +int main (int argc, char* argv[]) +{ + #ifdef LUA_VERSION_NUM /* lua 5.1 */ + lua_State* L = luaL_newstate(); + luaL_openlibs(L); + #else + lua_State* L = lua_open(); + luaopen_base(L); + luaopen_io(L); + luaopen_string(L); + luaopen_table(L); + luaopen_math(L); + luaopen_debug(L); + #endif + + lua_pushstring(L,TOLUA_VERSION); lua_setglobal(L,"TOLUA_VERSION"); + lua_pushstring(L,LUA_VERSION); lua_setglobal(L,"TOLUA_LUA_VERSION"); + + if (argc==1) + { + help(); + return 0; + } + else + { + int i, t; + lua_newtable(L); + lua_setglobal(L, "_extra_parameters"); + lua_newtable(L); + lua_pushvalue(L,-1); + lua_setglobal(L,"flags"); + t = lua_gettop(L); + for (i=1; i= 501 +TOLUA_API int luaopen_tolua (lua_State* tolua_S) { + return tolua_tolua_open(tolua_S); +}; +#endif + diff --git a/lib/tolua++/src/bin/toluabind.h b/lib/tolua++/src/bin/toluabind.h new file mode 100644 index 000000000..7f1f018c9 --- /dev/null +++ b/lib/tolua++/src/bin/toluabind.h @@ -0,0 +1,8 @@ +/* +** Lua binding: tolua +** Generated automatically by tolua++-1.0.92 on Sun Feb 15 22:29:48 2009. +*/ + +/* Exported function */ +TOLUA_API int tolua_tolua_open (lua_State* tolua_S); + diff --git a/lib/tolua++/src/bin/toluabind_default.c b/lib/tolua++/src/bin/toluabind_default.c new file mode 100644 index 000000000..b5db813bf --- /dev/null +++ b/lib/tolua++/src/bin/toluabind_default.c @@ -0,0 +1,8009 @@ +/* +** Lua binding: tolua +** Generated automatically by tolua++-1.0.92 on Fri Dec 28 21:37:36 2007. +*/ + +#ifndef __cplusplus +#include "stdlib.h" +#endif +#include "string.h" + +#include "tolua++.h" + +/* Exported function */ +TOLUA_API int tolua_tolua_open (lua_State* tolua_S); + + +/* function to register type */ +static void tolua_reg_types (lua_State* tolua_S) +{ +} + +/* Open function */ +TOLUA_API int tolua_tolua_open (lua_State* tolua_S) +{ + tolua_open(tolua_S); + tolua_reg_types(tolua_S); + tolua_module(tolua_S,NULL,0); + tolua_beginmodule(tolua_S,NULL); + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 105,102, 32,115,116,114,105,110,103, 46,102,105,110,100, 40, + 95, 86, 69, 82, 83, 73, 79, 78, 44, 32, 34, 53, 37, 46, 48, + 34, 41, 32,116,104,101,110, 13, 10, 9,114,101,116,117,114, + 110, 13, 10,101,110,100, 13, 10, 13, 10, 45, 45, 32, 34,108, + 111, 97,100,102,105,108,101, 34, 13, 10,108,111, 99, 97,108, + 32,102,117,110, 99,116,105,111,110, 32,112,112, 95,100,111, + 102,105,108,101, 40,112, 97,116,104, 41, 13, 10, 13, 10, 9, + 108,111, 99, 97,108, 32,108,111, 97,100,101,100, 32, 61, 32, + 102, 97,108,115,101, 13, 10, 9,108,111, 99, 97,108, 32,103, + 101,116,102,105,108,101, 32, 61, 32,102,117,110, 99,116,105, + 111,110, 40, 41, 13, 10, 13, 10, 9, 9,105,102, 32,108,111, + 97,100,101,100, 32,116,104,101,110, 13, 10, 9, 9, 9,114, + 101,116,117,114,110, 13, 10, 9, 9,101,108,115,101, 13, 10, + 9, 9, 9,108,111, 99, 97,108, 32,102,105,108,101, 44,101, + 114,114, 32, 61, 32,105,111, 46,111,112,101,110, 40,112, 97, + 116,104, 41, 13, 10, 9, 9, 9,105,102, 32,110,111,116, 32, + 102,105,108,101, 32,116,104,101,110, 13, 10, 9, 9, 9, 9, + 101,114,114,111,114, 40, 34,101,114,114,111,114, 32,108,111, + 97,100,105,110,103, 32,102,105,108,101, 32, 34, 46, 46,112, + 97,116,104, 46, 46, 34, 58, 32, 34, 46, 46,101,114,114, 41, + 13, 10, 9, 9, 9,101,110,100, 13, 10, 9, 9, 9,108,111, + 99, 97,108, 32,114,101,116, 32, 61, 32,102,105,108,101, 58, + 114,101, 97,100, 40, 34, 42, 97, 34, 41, 13, 10, 9, 9, 9, + 102,105,108,101, 58, 99,108,111,115,101, 40, 41, 13, 10, 13, + 10, 9, 9, 9,114,101,116, 32, 61, 32,115,116,114,105,110, + 103, 46,103,115,117, 98, 40,114,101,116, 44, 32, 34, 37, 46, + 37, 46, 37, 46, 37,115, 42, 37, 41, 34, 44, 32, 34, 46, 46, + 46, 41, 32,108,111, 99, 97,108, 32, 97,114,103, 32, 61, 32, + 123,110, 61,115,101,108,101, 99,116, 40, 39, 35, 39, 44, 32, + 46, 46, 46, 41, 44, 32, 46, 46, 46,125, 59, 34, 41, 13, 10, + 13, 10, 9, 9, 9,108,111, 97,100,101,100, 32, 61, 32,116, + 114,117,101, 13, 10, 9, 9, 9,114,101,116,117,114,110, 32, + 114,101,116, 13, 10, 9, 9,101,110,100, 13, 10, 9,101,110, + 100, 13, 10, 13, 10, 9,108,111, 99, 97,108, 32,102, 32, 61, + 32,108,111, 97,100, 40,103,101,116,102,105,108,101, 44, 32, + 112, 97,116,104, 41, 13, 10, 9,105,102, 32,110,111,116, 32, + 102, 32,116,104,101,110, 13, 10, 9, 13, 10, 9, 9,101,114, + 114,111,114, 40, 34,101,114,114,111,114, 32,108,111, 97,100, + 105,110,103, 32,102,105,108,101, 32, 34, 46, 46,112, 97,116, + 104, 41, 13, 10, 9,101,110,100, 13, 10, 9,114,101,116,117, + 114,110, 32,102, 40, 41, 13, 10,101,110,100, 13, 10, 13, 10, + 111,108,100, 95,100,111,102,105,108,101, 32, 61, 32,100,111, + 102,105,108,101, 13, 10,100,111,102,105,108,101, 32, 61, 32, + 112,112, 95,100,111,102,105,108,101, 13, 10, 13, 10, 13, 10, + 45, 45, 32,115,116,114,105,110,103, 46,103,115,117, 98, 13, + 10, 45, 45, 91, 91, 13, 10,108,111, 99, 97,108, 32,111,103, + 115,117, 98, 32, 61, 32,115,116,114,105,110,103, 46,103,115, + 117, 98, 13, 10,108,111, 99, 97,108, 32,102,117,110, 99,116, + 105,111,110, 32, 99,111,109,112,103,115,117, 98, 40, 97, 44, + 98, 44, 99, 44,100, 41, 13, 10, 32, 32,105,102, 32,116,121, + 112,101, 40, 99, 41, 32, 61, 61, 32, 34,102,117,110, 99,116, + 105,111,110, 34, 32,116,104,101,110, 13, 10, 32, 32, 32, 32, + 108,111, 99, 97,108, 32,111, 99, 32, 61, 32, 99, 13, 10, 32, + 32, 32, 32, 99, 32, 61, 32,102,117,110, 99,116,105,111,110, + 32, 40, 46, 46, 46, 41, 32,114,101,116,117,114,110, 32,111, + 99, 40, 46, 46, 46, 41, 32,111,114, 32, 39, 39, 32,101,110, + 100, 13, 10, 32, 32,101,110,100, 13, 10, 32, 32,114,101,116, + 117,114,110, 32,111,103,115,117, 98, 40, 97, 44, 98, 44, 99, + 44,100, 41, 13, 10,101,110,100, 13, 10,115,116,114,105,110, + 103, 46,114,101,112,108, 32, 61, 32,111,103,115,117, 98, 13, + 10, 45, 45, 93, 93, 13, 10, 13, 10, 45, 45,115,116,114,105, + 110,103, 46,103,115,117, 98, 32, 61, 32, 99,111,109,112,103, + 115,117, 98, 13,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/compat-5.1.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 10, 45, 45, 32, 82,101, 97,108, + 32,103,108,111, 98, 97,108,115, 10, 45, 45, 32, 95, 65, 76, + 69, 82, 84, 10, 45, 45, 32, 95, 69, 82, 82, 79, 82, 77, 69, + 83, 83, 65, 71, 69, 10, 45, 45, 32, 95, 86, 69, 82, 83, 73, + 79, 78, 10, 45, 45, 32, 95, 71, 10, 45, 45, 32, 97,115,115, + 101,114,116, 10, 45, 45, 32,101,114,114,111,114, 10, 45, 45, + 32,109,101,116, 97,116, 97, 98,108,101, 10, 45, 45, 32,110, + 101,120,116, 10, 45, 45, 32,112,114,105,110,116, 10, 45, 45, + 32,114,101,113,117,105,114,101, 10, 45, 45, 32,116,111,110, + 117,109, 98,101,114, 10, 45, 45, 32,116,111,115,116,114,105, + 110,103, 10, 45, 45, 32,116,121,112,101, 10, 45, 45, 32,117, + 110,112, 97, 99,107, 10, 10, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, + 45, 45, 32, 99,111,108,108,101, 99,116,103, 97,114, 98, 97, + 103,101, 10, 45, 45, 32,103, 99,105,110,102,111, 10, 10, 45, + 45, 32,103,108,111, 98, 97,108,115, 10, 10, 45, 45, 32, 99, + 97,108,108, 32, 32, 32, 45, 62, 32,112,114,111,116,101, 99, + 116, 40,102, 44, 32,101,114,114, 41, 10, 45, 45, 32,108,111, + 97,100,102,105,108,101, 10, 45, 45, 32,108,111, 97,100,115, + 116,114,105,110,103, 10, 10, 45, 45, 32,114, 97,119,103,101, + 116, 10, 45, 45, 32,114, 97,119,115,101,116, 10, 10, 45, 45, + 32,103,101,116, 97,114,103,115, 32, 61, 32, 77, 97,105,110, + 46,103,101,116, 97,114,103,115, 32, 63, 63, 10, 10,114, 97, + 119,116,121,112,101, 32, 61, 32,116,121,112,101, 10, 10,102, + 117,110, 99,116,105,111,110, 32,100,111, 95, 32, 40,102, 44, + 32,101,114,114, 41, 10, 32, 32,105,102, 32,110,111,116, 32, + 102, 32,116,104,101,110, 32,112,114,105,110,116, 40,101,114, + 114, 41, 59, 32,114,101,116,117,114,110, 32,101,110,100, 10, + 32, 32,108,111, 99, 97,108, 32, 97, 44, 98, 32, 61, 32,112, + 99, 97,108,108, 40,102, 41, 10, 32, 32,105,102, 32,110,111, + 116, 32, 97, 32,116,104,101,110, 32,112,114,105,110,116, 40, + 98, 41, 59, 32,114,101,116,117,114,110, 32,110,105,108, 10, + 32, 32,101,108,115,101, 32,114,101,116,117,114,110, 32, 98, + 32,111,114, 32,116,114,117,101, 10, 32, 32,101,110,100, 10, + 101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,100, + 111,115,116,114,105,110,103, 40,115, 41, 32,114,101,116,117, + 114,110, 32,100,111, 95, 40,108,111, 97,100,115,116,114,105, + 110,103, 40,115, 41, 41, 32,101,110,100, 10, 45, 45, 32,102, + 117,110, 99,116,105,111,110, 32,100,111,102,105,108,101, 40, + 115, 41, 32,114,101,116,117,114,110, 32,100,111, 95, 40,108, + 111, 97,100,102,105,108,101, 40,115, 41, 41, 32,101,110,100, + 10, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, 45, 45, 32, 84, 97, + 98,108,101, 32,108,105, 98,114, 97,114,121, 10,108,111, 99, + 97,108, 32,116, 97, 98, 32, 61, 32,116, 97, 98,108,101, 10, + 102,111,114,101, 97, 99,104, 32, 61, 32,116, 97, 98, 46,102, + 111,114,101, 97, 99,104, 10,102,111,114,101, 97, 99,104,105, + 32, 61, 32,116, 97, 98, 46,102,111,114,101, 97, 99,104,105, + 10,103,101,116,110, 32, 61, 32,116, 97, 98, 46,103,101,116, + 110, 10,116,105,110,115,101,114,116, 32, 61, 32,116, 97, 98, + 46,105,110,115,101,114,116, 10,116,114,101,109,111,118,101, + 32, 61, 32,116, 97, 98, 46,114,101,109,111,118,101, 10,115, + 111,114,116, 32, 61, 32,116, 97, 98, 46,115,111,114,116, 10, + 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 10, 45, 45, 32, 68,101, 98, + 117,103, 32,108,105, 98,114, 97,114,121, 10,108,111, 99, 97, + 108, 32,100, 98,103, 32, 61, 32,100,101, 98,117,103, 10,103, + 101,116,105,110,102,111, 32, 61, 32,100, 98,103, 46,103,101, + 116,105,110,102,111, 10,103,101,116,108,111, 99, 97,108, 32, + 61, 32,100, 98,103, 46,103,101,116,108,111, 99, 97,108, 10, + 115,101,116, 99, 97,108,108,104,111,111,107, 32, 61, 32,102, + 117,110, 99,116,105,111,110, 32, 40, 41, 32,101,114,114,111, + 114, 34, 96,115,101,116, 99, 97,108,108,104,111,111,107, 39, + 32,105,115, 32,100,101,112,114,101, 99, 97,116,101,100, 34, + 32,101,110,100, 10,115,101,116,108,105,110,101,104,111,111, + 107, 32, 61, 32,102,117,110, 99,116,105,111,110, 32, 40, 41, + 32,101,114,114,111,114, 34, 96,115,101,116,108,105,110,101, + 104,111,111,107, 39, 32,105,115, 32,100,101,112,114,101, 99, + 97,116,101,100, 34, 32,101,110,100, 10,115,101,116,108,111, + 99, 97,108, 32, 61, 32,100, 98,103, 46,115,101,116,108,111, + 99, 97,108, 10, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, 45, 45, + 32,109, 97,116,104, 32,108,105, 98,114, 97,114,121, 10,108, + 111, 99, 97,108, 32,109, 97,116,104, 32, 61, 32,109, 97,116, + 104, 10, 97, 98,115, 32, 61, 32,109, 97,116,104, 46, 97, 98, + 115, 10, 97, 99,111,115, 32, 61, 32,102,117,110, 99,116,105, + 111,110, 32, 40,120, 41, 32,114,101,116,117,114,110, 32,109, + 97,116,104, 46,100,101,103, 40,109, 97,116,104, 46, 97, 99, + 111,115, 40,120, 41, 41, 32,101,110,100, 10, 97,115,105,110, + 32, 61, 32,102,117,110, 99,116,105,111,110, 32, 40,120, 41, + 32,114,101,116,117,114,110, 32,109, 97,116,104, 46,100,101, + 103, 40,109, 97,116,104, 46, 97,115,105,110, 40,120, 41, 41, + 32,101,110,100, 10, 97,116, 97,110, 32, 61, 32,102,117,110, + 99,116,105,111,110, 32, 40,120, 41, 32,114,101,116,117,114, + 110, 32,109, 97,116,104, 46,100,101,103, 40,109, 97,116,104, + 46, 97,116, 97,110, 40,120, 41, 41, 32,101,110,100, 10, 97, + 116, 97,110, 50, 32, 61, 32,102,117,110, 99,116,105,111,110, + 32, 40,120, 44,121, 41, 32,114,101,116,117,114,110, 32,109, + 97,116,104, 46,100,101,103, 40,109, 97,116,104, 46, 97,116, + 97,110, 50, 40,120, 44,121, 41, 41, 32,101,110,100, 10, 99, + 101,105,108, 32, 61, 32,109, 97,116,104, 46, 99,101,105,108, + 10, 99,111,115, 32, 61, 32,102,117,110, 99,116,105,111,110, + 32, 40,120, 41, 32,114,101,116,117,114,110, 32,109, 97,116, + 104, 46, 99,111,115, 40,109, 97,116,104, 46,114, 97,100, 40, + 120, 41, 41, 32,101,110,100, 10,100,101,103, 32, 61, 32,109, + 97,116,104, 46,100,101,103, 10,101,120,112, 32, 61, 32,109, + 97,116,104, 46,101,120,112, 10,102,108,111,111,114, 32, 61, + 32,109, 97,116,104, 46,102,108,111,111,114, 10,102,114,101, + 120,112, 32, 61, 32,109, 97,116,104, 46,102,114,101,120,112, + 10,108,100,101,120,112, 32, 61, 32,109, 97,116,104, 46,108, + 100,101,120,112, 10,108,111,103, 32, 61, 32,109, 97,116,104, + 46,108,111,103, 10,108,111,103, 49, 48, 32, 61, 32,109, 97, + 116,104, 46,108,111,103, 49, 48, 10,109, 97,120, 32, 61, 32, + 109, 97,116,104, 46,109, 97,120, 10,109,105,110, 32, 61, 32, + 109, 97,116,104, 46,109,105,110, 10,109,111,100, 32, 61, 32, + 109, 97,116,104, 46,109,111,100, 10, 80, 73, 32, 61, 32,109, + 97,116,104, 46,112,105, 10, 45, 45, 63, 63, 63, 32,112,111, + 119, 32, 61, 32,109, 97,116,104, 46,112,111,119, 32, 32, 10, + 114, 97,100, 32, 61, 32,109, 97,116,104, 46,114, 97,100, 10, + 114, 97,110,100,111,109, 32, 61, 32,109, 97,116,104, 46,114, + 97,110,100,111,109, 10,114, 97,110,100,111,109,115,101,101, + 100, 32, 61, 32,109, 97,116,104, 46,114, 97,110,100,111,109, + 115,101,101,100, 10,115,105,110, 32, 61, 32,102,117,110, 99, + 116,105,111,110, 32, 40,120, 41, 32,114,101,116,117,114,110, + 32,109, 97,116,104, 46,115,105,110, 40,109, 97,116,104, 46, + 114, 97,100, 40,120, 41, 41, 32,101,110,100, 10,115,113,114, + 116, 32, 61, 32,109, 97,116,104, 46,115,113,114,116, 10,116, + 97,110, 32, 61, 32,102,117,110, 99,116,105,111,110, 32, 40, + 120, 41, 32,114,101,116,117,114,110, 32,109, 97,116,104, 46, + 116, 97,110, 40,109, 97,116,104, 46,114, 97,100, 40,120, 41, + 41, 32,101,110,100, 10, 10, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, + 45, 45, 32,115,116,114,105,110,103, 32,108,105, 98,114, 97, + 114,121, 10,108,111, 99, 97,108, 32,115,116,114, 32, 61, 32, + 115,116,114,105,110,103, 10,115,116,114, 98,121,116,101, 32, + 61, 32,115,116,114, 46, 98,121,116,101, 10,115,116,114, 99, + 104, 97,114, 32, 61, 32,115,116,114, 46, 99,104, 97,114, 10, + 115,116,114,102,105,110,100, 32, 61, 32,115,116,114, 46,102, + 105,110,100, 10,102,111,114,109, 97,116, 32, 61, 32,115,116, + 114, 46,102,111,114,109, 97,116, 10,103,115,117, 98, 32, 61, + 32,115,116,114, 46,103,115,117, 98, 10,115,116,114,108,101, + 110, 32, 61, 32,115,116,114, 46,108,101,110, 10,115,116,114, + 108,111,119,101,114, 32, 61, 32,115,116,114, 46,108,111,119, + 101,114, 10,115,116,114,114,101,112, 32, 61, 32,115,116,114, + 46,114,101,112, 10,115,116,114,115,117, 98, 32, 61, 32,115, + 116,114, 46,115,117, 98, 10,115,116,114,117,112,112,101,114, + 32, 61, 32,115,116,114, 46,117,112,112,101,114, 10, 10, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 10, 45, 45, 32,111,115, 32,108,105, + 98,114, 97,114,121, 10, 99,108,111, 99,107, 32, 61, 32,111, + 115, 46, 99,108,111, 99,107, 10,100, 97,116,101, 32, 61, 32, + 111,115, 46,100, 97,116,101, 10,100,105,102,102,116,105,109, + 101, 32, 61, 32,111,115, 46,100,105,102,102,116,105,109,101, + 10,101,120,101, 99,117,116,101, 32, 61, 32,111,115, 46,101, + 120,101, 99,117,116,101, 32, 45, 45, 63, 10,101,120,105,116, + 32, 61, 32,111,115, 46,101,120,105,116, 10,103,101,116,101, + 110,118, 32, 61, 32,111,115, 46,103,101,116,101,110,118, 10, + 114,101,109,111,118,101, 32, 61, 32,111,115, 46,114,101,109, + 111,118,101, 10,114,101,110, 97,109,101, 32, 61, 32,111,115, + 46,114,101,110, 97,109,101, 10,115,101,116,108,111, 99, 97, + 108,101, 32, 61, 32,111,115, 46,115,101,116,108,111, 99, 97, + 108,101, 10,116,105,109,101, 32, 61, 32,111,115, 46,116,105, + 109,101, 10,116,109,112,110, 97,109,101, 32, 61, 32,111,115, + 46,116,109,112,110, 97,109,101, 10, 10, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 10, 45, 45, 32, 99,111,109,112, 97,116,105, 98,105, + 108,105,116,121, 32,111,110,108,121, 10,103,101,116,103,108, + 111, 98, 97,108, 32, 61, 32,102,117,110, 99,116,105,111,110, + 32, 40,110, 41, 32,114,101,116,117,114,110, 32, 95, 71, 91, + 110, 93, 32,101,110,100, 10,115,101,116,103,108,111, 98, 97, + 108, 32, 61, 32,102,117,110, 99,116,105,111,110, 32, 40,110, + 44,118, 41, 32, 95, 71, 91,110, 93, 32, 61, 32,118, 32,101, + 110,100, 10, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, 10,108,111, + 99, 97,108, 32,105,111, 44, 32,116, 97, 98, 32, 61, 32,105, + 111, 44, 32,116, 97, 98,108,101, 10, 10, 45, 45, 32, 73, 79, + 32,108,105, 98,114, 97,114,121, 32, 40,102,105,108,101,115, + 41, 10, 95, 83, 84, 68, 73, 78, 32, 61, 32,105,111, 46,115, + 116,100,105,110, 10, 95, 83, 84, 68, 69, 82, 82, 32, 61, 32, + 105,111, 46,115,116,100,101,114,114, 10, 95, 83, 84, 68, 79, + 85, 84, 32, 61, 32,105,111, 46,115,116,100,111,117,116, 10, + 95, 73, 78, 80, 85, 84, 32, 61, 32,105,111, 46,115,116,100, + 105,110, 10, 95, 79, 85, 84, 80, 85, 84, 32, 61, 32,105,111, + 46,115,116,100,111,117,116, 10,115,101,101,107, 32, 61, 32, + 105,111, 46,115,116,100,105,110, 46,115,101,101,107, 32, 32, + 32, 45, 45, 32,115,105, 99,107, 32, 59, 45, 41, 10,116,109, + 112,102,105,108,101, 32, 61, 32,105,111, 46,116,109,112,102, + 105,108,101, 10, 99,108,111,115,101,102,105,108,101, 32, 61, + 32,105,111, 46, 99,108,111,115,101, 10,111,112,101,110,102, + 105,108,101, 32, 61, 32,105,111, 46,111,112,101,110, 10, 10, + 102,117,110, 99,116,105,111,110, 32,102,108,117,115,104, 32, + 40,102, 41, 10, 32, 32,105,102, 32,102, 32,116,104,101,110, + 32,102, 58,102,108,117,115,104, 40, 41, 10, 32, 32,101,108, + 115,101, 32, 95, 79, 85, 84, 80, 85, 84, 58,102,108,117,115, + 104, 40, 41, 10, 32, 32,101,110,100, 10,101,110,100, 10, 10, + 102,117,110, 99,116,105,111,110, 32,114,101, 97,100,102,114, + 111,109, 32, 40,110, 97,109,101, 41, 10, 32, 32,105,102, 32, + 110, 97,109,101, 32, 61, 61, 32,110,105,108, 32,116,104,101, + 110, 10, 32, 32, 32, 32,108,111, 99, 97,108, 32,102, 44, 32, + 101,114,114, 44, 32, 99,111,100, 32, 61, 32,105,111, 46, 99, + 108,111,115,101, 40, 95, 73, 78, 80, 85, 84, 41, 10, 32, 32, + 32, 32, 95, 73, 78, 80, 85, 84, 32, 61, 32,105,111, 46,115, + 116,100,105,110, 10, 32, 32, 32, 32,114,101,116,117,114,110, + 32,102, 44, 32,101,114,114, 44, 32, 99,111,100, 10, 32, 32, + 101,108,115,101, 10, 32, 32, 32, 32,108,111, 99, 97,108, 32, + 102, 44, 32,101,114,114, 44, 32, 99,111,100, 32, 61, 32,105, + 111, 46,111,112,101,110, 40,110, 97,109,101, 44, 32, 34,114, + 34, 41, 10, 32, 32, 32, 32, 95, 73, 78, 80, 85, 84, 32, 61, + 32,102, 32,111,114, 32, 95, 73, 78, 80, 85, 84, 10, 32, 32, + 32, 32,114,101,116,117,114,110, 32,102, 44, 32,101,114,114, + 44, 32, 99,111,100, 10, 32, 32,101,110,100, 10,101,110,100, + 10, 10,102,117,110, 99,116,105,111,110, 32,119,114,105,116, + 101,116,111, 32, 40,110, 97,109,101, 41, 10, 32, 32,105,102, + 32,110, 97,109,101, 32, 61, 61, 32,110,105,108, 32,116,104, + 101,110, 10, 32, 32, 32, 32,108,111, 99, 97,108, 32,102, 44, + 32,101,114,114, 44, 32, 99,111,100, 32, 61, 32,105,111, 46, + 99,108,111,115,101, 40, 95, 79, 85, 84, 80, 85, 84, 41, 10, + 32, 32, 32, 32, 95, 79, 85, 84, 80, 85, 84, 32, 61, 32,105, + 111, 46,115,116,100,111,117,116, 10, 32, 32, 32, 32,114,101, + 116,117,114,110, 32,102, 44, 32,101,114,114, 44, 32, 99,111, + 100, 10, 32, 32,101,108,115,101, 10, 32, 32, 32, 32,108,111, + 99, 97,108, 32,102, 44, 32,101,114,114, 44, 32, 99,111,100, + 32, 61, 32,105,111, 46,111,112,101,110, 40,110, 97,109,101, + 44, 32, 34,119, 34, 41, 10, 32, 32, 32, 32, 95, 79, 85, 84, + 80, 85, 84, 32, 61, 32,102, 32,111,114, 32, 95, 79, 85, 84, + 80, 85, 84, 10, 32, 32, 32, 32,114,101,116,117,114,110, 32, + 102, 44, 32,101,114,114, 44, 32, 99,111,100, 10, 32, 32,101, + 110,100, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111, + 110, 32, 97,112,112,101,110,100,116,111, 32, 40,110, 97,109, + 101, 41, 10, 32, 32,108,111, 99, 97,108, 32,102, 44, 32,101, + 114,114, 44, 32, 99,111,100, 32, 61, 32,105,111, 46,111,112, + 101,110, 40,110, 97,109,101, 44, 32, 34, 97, 34, 41, 10, 32, + 32, 95, 79, 85, 84, 80, 85, 84, 32, 61, 32,102, 32,111,114, + 32, 95, 79, 85, 84, 80, 85, 84, 10, 32, 32,114,101,116,117, + 114,110, 32,102, 44, 32,101,114,114, 44, 32, 99,111,100, 10, + 101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,114, + 101, 97,100, 32, 40, 46, 46, 46, 41, 10, 32, 32,108,111, 99, + 97,108, 32,102, 32, 61, 32, 95, 73, 78, 80, 85, 84, 10, 32, + 32,105,102, 32,114, 97,119,116,121,112,101, 40, 97,114,103, + 91, 49, 93, 41, 32, 61, 61, 32, 39,117,115,101,114,100, 97, + 116, 97, 39, 32,116,104,101,110, 10, 32, 32, 32, 32,102, 32, + 61, 32,116, 97, 98, 46,114,101,109,111,118,101, 40, 97,114, + 103, 44, 32, 49, 41, 10, 32, 32,101,110,100, 10, 32, 32,114, + 101,116,117,114,110, 32,102, 58,114,101, 97,100, 40,117,110, + 112, 97, 99,107, 40, 97,114,103, 41, 41, 10,101,110,100, 10, + 10,102,117,110, 99,116,105,111,110, 32,119,114,105,116,101, + 32, 40, 46, 46, 46, 41, 10, 32, 32,108,111, 99, 97,108, 32, + 102, 32, 61, 32, 95, 79, 85, 84, 80, 85, 84, 10, 32, 32,105, + 102, 32,114, 97,119,116,121,112,101, 40, 97,114,103, 91, 49, + 93, 41, 32, 61, 61, 32, 39,117,115,101,114,100, 97,116, 97, + 39, 32,116,104,101,110, 10, 32, 32, 32, 32,102, 32, 61, 32, + 116, 97, 98, 46,114,101,109,111,118,101, 40, 97,114,103, 44, + 32, 49, 41, 10, 32, 32,101,110,100, 10, 32, 32,114,101,116, + 117,114,110, 32,102, 58,119,114,105,116,101, 40,117,110,112, + 97, 99,107, 40, 97,114,103, 41, 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/compat.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32, 98, 97,115,105, 99, + 32,117,116,105,108,105,116,121, 32,102,117,110, 99,116,105, + 111,110,115, 10, 45, 45, 32, 87,114,105,116,116,101,110, 32, + 98,121, 32, 87, 97,108,100,101,109, 97,114, 32, 67,101,108, + 101,115, 10, 45, 45, 32, 84,101, 67, 71,114, 97,102, 47, 80, + 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74,117,108, 32, 49, + 57, 57, 56, 10, 45, 45, 32, 76, 97,115,116, 32,117,112,100, + 97,116,101, 58, 32, 65,112,114, 32, 50, 48, 48, 51, 10, 45, + 45, 32, 36, 73,100, 58, 32, 36, 10, 10, 45, 45, 32, 84,104, + 105,115, 32, 99,111,100,101, 32,105,115, 32,102,114,101,101, + 32,115,111,102,116,119, 97,114,101, 59, 32,121,111,117, 32, + 99, 97,110, 32,114,101,100,105,115,116,114,105, 98,117,116, + 101, 32,105,116, 32, 97,110,100, 47,111,114, 32,109,111,100, + 105,102,121, 32,105,116, 46, 10, 45, 45, 32, 84,104,101, 32, + 115,111,102,116,119, 97,114,101, 32,112,114,111,118,105,100, + 101,100, 32,104,101,114,101,117,110,100,101,114, 32,105,115, + 32,111,110, 32, 97,110, 32, 34, 97,115, 32,105,115, 34, 32, + 98, 97,115,105,115, 44, 32, 97,110,100, 10, 45, 45, 32,116, + 104,101, 32, 97,117,116,104,111,114, 32,104, 97,115, 32,110, + 111, 32,111, 98,108,105,103, 97,116,105,111,110, 32,116,111, + 32,112,114,111,118,105,100,101, 32,109, 97,105,110,116,101, + 110, 97,110, 99,101, 44, 32,115,117,112,112,111,114,116, 44, + 32,117,112,100, 97,116,101,115, 44, 10, 45, 45, 32,101,110, + 104, 97,110, 99,101,109,101,110,116,115, 44, 32,111,114, 32, + 109,111,100,105,102,105, 99, 97,116,105,111,110,115, 46, 10, + 10, 10, 45, 45, 32, 66, 97,115,105, 99, 32, 67, 32,116,121, + 112,101,115, 32, 97,110,100, 32,116,104,101,105,114, 32, 99, + 111,114,114,101,115,112,111,110,100,105,110,103, 32, 76,117, + 97, 32,116,121,112,101,115, 10, 45, 45, 32, 65,108,108, 32, + 111, 99, 99,117,114,114,101,110, 99,101,115, 32,111,102, 32, + 34, 99,104, 97,114, 42, 34, 32,119,105,108,108, 32, 98,101, + 32,114,101,112,108, 97, 99,101,100, 32, 98,121, 32, 34, 95, + 99,115,116,114,105,110,103, 34, 44, 10, 45, 45, 32, 97,110, + 100, 32, 97,108,108, 32,111, 99, 99,117,114,114,101,110, 99, + 101,115, 32,111,102, 32, 34,118,111,105,100, 42, 34, 32,119, + 105,108,108, 32, 98,101, 32,114,101,112,108, 97, 99,101,100, + 32, 98,121, 32, 34, 95,117,115,101,114,100, 97,116, 97, 34, + 10, 95, 98, 97,115,105, 99, 32, 61, 32,123, 10, 32, 91, 39, + 118,111,105,100, 39, 93, 32, 61, 32, 39, 39, 44, 10, 32, 91, + 39, 99,104, 97,114, 39, 93, 32, 61, 32, 39,110,117,109, 98, + 101,114, 39, 44, 10, 32, 91, 39,105,110,116, 39, 93, 32, 61, + 32, 39,110,117,109, 98,101,114, 39, 44, 10, 32, 91, 39,115, + 104,111,114,116, 39, 93, 32, 61, 32, 39,110,117,109, 98,101, + 114, 39, 44, 10, 32, 91, 39,108,111,110,103, 39, 93, 32, 61, + 32, 39,110,117,109, 98,101,114, 39, 44, 10, 32, 91, 39,117, + 110,115,105,103,110,101,100, 39, 93, 32, 61, 32, 39,110,117, + 109, 98,101,114, 39, 44, 10, 32, 91, 39,102,108,111, 97,116, + 39, 93, 32, 61, 32, 39,110,117,109, 98,101,114, 39, 44, 10, + 32, 91, 39,100,111,117, 98,108,101, 39, 93, 32, 61, 32, 39, + 110,117,109, 98,101,114, 39, 44, 10, 32, 91, 39, 95, 99,115, + 116,114,105,110,103, 39, 93, 32, 61, 32, 39,115,116,114,105, + 110,103, 39, 44, 10, 32, 91, 39, 95,117,115,101,114,100, 97, + 116, 97, 39, 93, 32, 61, 32, 39,117,115,101,114,100, 97,116, + 97, 39, 44, 10, 32, 91, 39, 99,104, 97,114, 42, 39, 93, 32, + 61, 32, 39,115,116,114,105,110,103, 39, 44, 10, 32, 91, 39, + 118,111,105,100, 42, 39, 93, 32, 61, 32, 39,117,115,101,114, + 100, 97,116, 97, 39, 44, 10, 32, 91, 39, 98,111,111,108, 39, + 93, 32, 61, 32, 39, 98,111,111,108,101, 97,110, 39, 44, 10, + 32, 91, 39,108,117, 97, 95, 79, 98,106,101, 99,116, 39, 93, + 32, 61, 32, 39,118, 97,108,117,101, 39, 44, 10, 32, 91, 39, + 76, 85, 65, 95, 86, 65, 76, 85, 69, 39, 93, 32, 61, 32, 39, + 118, 97,108,117,101, 39, 44, 32, 32, 32, 32, 45, 45, 32,102, + 111,114, 32, 99,111,109,112, 97,116,105, 98,105,108,105,116, + 121, 32,119,105,116,104, 32,116,111,108,117, 97, 32, 52, 46, + 48, 10, 32, 91, 39,108,117, 97, 95, 83,116, 97,116,101, 42, + 39, 93, 32, 61, 32, 39,115,116, 97,116,101, 39, 44, 10, 32, + 91, 39, 95,108,115,116, 97,116,101, 39, 93, 32, 61, 32, 39, + 115,116, 97,116,101, 39, 44, 10, 32, 91, 39,108,117, 97, 95, + 70,117,110, 99,116,105,111,110, 39, 93, 32, 61, 32, 39,118, + 97,108,117,101, 39, 44, 10,125, 10, 10, 95, 98, 97,115,105, + 99, 95, 99,116,121,112,101, 32, 61, 32,123, 10, 32,110,117, + 109, 98,101,114, 32, 61, 32, 34,108,117, 97, 95, 78,117,109, + 98,101,114, 34, 44, 10, 32,115,116,114,105,110,103, 32, 61, + 32, 34, 99,111,110,115,116, 32, 99,104, 97,114, 42, 34, 44, + 10, 32,117,115,101,114,100, 97,116, 97, 32, 61, 32, 34,118, + 111,105,100, 42, 34, 44, 10, 32, 98,111,111,108,101, 97,110, + 32, 61, 32, 34, 98,111,111,108, 34, 44, 10, 32,118, 97,108, + 117,101, 32, 61, 32, 34,105,110,116, 34, 44, 10, 32,115,116, + 97,116,101, 32, 61, 32, 34,108,117, 97, 95, 83,116, 97,116, + 101, 42, 34, 44, 10,125, 10, 10, 45, 45, 32,102,117,110, 99, + 116,105,111,110,115, 32,116,104,101, 32, 97,114,101, 32,117, + 115,101,100, 32,116,111, 32,100,111, 32, 97, 32, 39,114, 97, + 119, 32,112,117,115,104, 39, 32,111,102, 32, 98, 97,115,105, + 99, 32,116,121,112,101,115, 10, 95, 98, 97,115,105, 99, 95, + 114, 97,119, 95,112,117,115,104, 32, 61, 32,123,125, 10, 10, + 45, 45, 32, 76,105,115,116, 32,111,102, 32,117,115,101,114, + 32,100,101,102,105,110,101,100, 32,116,121,112,101,115, 10, + 45, 45, 32, 69, 97, 99,104, 32,116,121,112,101, 32, 99,111, + 114,114,101,115,112,111,110,100,115, 32,116,111, 32, 97, 32, + 118, 97,114,105, 97, 98,108,101, 32,110, 97,109,101, 32,116, + 104, 97,116, 32,115,116,111,114,101,115, 32,105,116,115, 32, + 116, 97,103, 32,118, 97,108,117,101, 46, 10, 95,117,115,101, + 114,116,121,112,101, 32, 61, 32,123,125, 10, 10, 45, 45, 32, + 76,105,115,116, 32,111,102, 32,116,121,112,101,115, 32,116, + 104, 97,116, 32,104, 97,118,101, 32,116,111, 32, 98,101, 32, + 99,111,108,108,101, 99,116,101,100, 10, 95, 99,111,108,108, + 101, 99,116, 32, 61, 32,123,125, 10, 10, 45, 45, 32, 76,105, + 115,116, 32,111,102, 32,116,121,112,101,115, 10, 95,103,108, + 111, 98, 97,108, 95,116,121,112,101,115, 32, 61, 32,123,110, + 61, 48,125, 10, 95,103,108,111, 98, 97,108, 95,116,121,112, + 101,115, 95,104, 97,115,104, 32, 61, 32,123,125, 10, 10, 45, + 45, 32,108,105,115,116, 32,111,102, 32, 99,108, 97,115,115, + 101,115, 10, 95,103,108,111, 98, 97,108, 95, 99,108, 97,115, + 115,101,115, 32, 61, 32,123,125, 10, 10, 45, 45, 32, 76,105, + 115,116, 32,111,102, 32,101,110,117,109, 32, 99,111,110,115, + 116, 97,110,116,115, 10, 95,103,108,111, 98, 97,108, 95,101, + 110,117,109,115, 32, 61, 32,123,125, 10, 10, 45, 45, 32, 76, + 105,115,116, 32,111,102, 32, 97,117,116,111, 32,114,101,110, + 97,109,105,110,103, 10, 95,114,101,110, 97,109,105,110,103, + 32, 61, 32,123,125, 10,102,117,110, 99,116,105,111,110, 32, + 97,112,112,101,110,100,114,101,110, 97,109,105,110,103, 32, + 40,115, 41, 10, 32,108,111, 99, 97,108, 32, 98, 44,101, 44, + 111,108,100, 44,110,101,119, 32, 61, 32,115,116,114,102,105, + 110,100, 40,115, 44, 34, 37,115, 42, 40, 46, 45, 41, 37,115, + 42, 64, 37,115, 42, 40, 46, 45, 41, 37,115, 42, 36, 34, 41, + 10, 9,105,102, 32,110,111,116, 32, 98, 32,116,104,101,110, + 10, 9, 32,101,114,114,111,114, 40, 34, 35, 73,110,118, 97, + 108,105,100, 32,114,101,110, 97,109,105,110,103, 32,115,121, + 110,116, 97,120, 59, 32,105,116, 32,115,104,111,117,108,100, + 32, 98,101, 32,111,102, 32,116,104,101, 32,102,111,114,109, + 58, 32,112, 97,116,116,101,114,110, 64,112, 97,116,116,101, + 114,110, 34, 41, 10, 9,101,110,100, 10, 9,116,105,110,115, + 101,114,116, 40, 95,114,101,110, 97,109,105,110,103, 44,123, + 111,108,100, 61,111,108,100, 44, 32,110,101,119, 61,110,101, + 119,125, 41, 10,101,110,100, 10, 10,102,117,110, 99,116,105, + 111,110, 32, 97,112,112,108,121,114,101,110, 97,109,105,110, + 103, 32, 40,115, 41, 10, 9,102,111,114, 32,105, 61, 49, 44, + 103,101,116,110, 40, 95,114,101,110, 97,109,105,110,103, 41, + 32,100,111, 10, 9, 32,108,111, 99, 97,108, 32,109, 44,110, + 32, 61, 32,103,115,117, 98, 40,115, 44, 95,114,101,110, 97, + 109,105,110,103, 91,105, 93, 46,111,108,100, 44, 95,114,101, + 110, 97,109,105,110,103, 91,105, 93, 46,110,101,119, 41, 10, + 9, 9,105,102, 32,110, 32,126, 61, 32, 48, 32,116,104,101, + 110, 10, 9, 9, 32,114,101,116,117,114,110, 32,109, 10, 9, + 9,101,110,100, 10, 9,101,110,100, 10, 9,114,101,116,117, + 114,110, 32,110,105,108, 10,101,110,100, 10, 10, 45, 45, 32, + 69,114,114,111,114, 32,104, 97,110,100,108,101,114, 10,102, + 117,110, 99,116,105,111,110, 32,116,111,108,117, 97, 95,101, + 114,114,111,114, 32, 40,115, 44,102, 41, 10,105,102, 32, 95, + 99,117,114,114, 95, 99,111,100,101, 32,116,104,101,110, 10, + 9,112,114,105,110,116, 40, 34, 42, 42, 42, 99,117,114,114, + 32, 99,111,100,101, 32,102,111,114, 32,101,114,114,111,114, + 32,105,115, 32, 34, 46, 46,116,111,115,116,114,105,110,103, + 40, 95, 99,117,114,114, 95, 99,111,100,101, 41, 41, 10, 9, + 112,114,105,110,116, 40,100,101, 98,117,103, 46,116,114, 97, + 99,101, 98, 97, 99,107, 40, 41, 41, 10,101,110,100, 10, 32, + 108,111, 99, 97,108, 32,111,117,116, 32, 61, 32, 95, 79, 85, + 84, 80, 85, 84, 10, 32, 95, 79, 85, 84, 80, 85, 84, 32, 61, + 32, 95, 83, 84, 68, 69, 82, 82, 10, 32,105,102, 32,115,116, + 114,115,117, 98, 40,115, 44, 49, 44, 49, 41, 32, 61, 61, 32, + 39, 35, 39, 32,116,104,101,110, 10, 32, 32,119,114,105,116, + 101, 40, 34, 92,110, 42, 42, 32,116,111,108,117, 97, 58, 32, + 34, 46, 46,115,116,114,115,117, 98, 40,115, 44, 50, 41, 46, + 46, 34, 46, 92,110, 92,110, 34, 41, 10, 32, 32,105,102, 32, + 95, 99,117,114,114, 95, 99,111,100,101, 32,116,104,101,110, + 10, 32, 32, 32,108,111, 99, 97,108, 32, 95, 44, 95, 44,115, + 32, 61, 32,115,116,114,102,105,110,100, 40, 95, 99,117,114, + 114, 95, 99,111,100,101, 44, 34, 94, 37,115, 42, 40, 46, 45, + 92,110, 41, 34, 41, 32, 45, 45, 32,101,120,116,114, 97, 99, + 116, 32,102,105,114,115,116, 32,108,105,110,101, 10, 32, 32, + 32,105,102, 32,115, 61, 61,110,105,108, 32,116,104,101,110, + 32,115, 32, 61, 32, 95, 99,117,114,114, 95, 99,111,100,101, + 32,101,110,100, 10, 32, 32, 32,115, 32, 61, 32,103,115,117, + 98, 40,115, 44, 34, 95,117,115,101,114,100, 97,116, 97, 34, + 44, 34,118,111,105,100, 42, 34, 41, 32, 45, 45, 32,114,101, + 116,117,114,110, 32,119,105,116,104, 32, 39,118,111,105,100, + 42, 39, 10, 32, 32, 32,115, 32, 61, 32,103,115,117, 98, 40, + 115, 44, 34, 95, 99,115,116,114,105,110,103, 34, 44, 34, 99, + 104, 97,114, 42, 34, 41, 32, 32, 45, 45, 32,114,101,116,117, + 114,110, 32,119,105,116,104, 32, 39, 99,104, 97,114, 42, 39, + 10, 32, 32, 32,115, 32, 61, 32,103,115,117, 98, 40,115, 44, + 34, 95,108,115,116, 97,116,101, 34, 44, 34,108,117, 97, 95, + 83,116, 97,116,101, 42, 34, 41, 32, 32, 45, 45, 32,114,101, + 116,117,114,110, 32,119,105,116,104, 32, 39,108,117, 97, 95, + 83,116, 97,116,101, 42, 39, 10, 32, 32, 32,119,114,105,116, + 101, 40, 34, 67,111,100,101, 32, 98,101,105,110,103, 32,112, + 114,111, 99,101,115,115,101,100, 58, 92,110, 34, 46, 46,115, + 46, 46, 34, 92,110, 34, 41, 10, 32, 32,101,110,100, 10, 32, + 101,108,115,101, 10, 32,105,102, 32,110,111,116, 32,102, 32, + 116,104,101,110, 32,102, 32, 61, 32, 34, 40,102, 32,105,115, + 32,110,105,108, 41, 34, 32,101,110,100, 10, 32, 32,112,114, + 105,110,116, 40, 34, 92,110, 42, 42, 32,116,111,108,117, 97, + 32,105,110,116,101,114,110, 97,108, 32,101,114,114,111,114, + 58, 32, 34, 46, 46,102, 46, 46,115, 46, 46, 34, 46, 92,110, + 92,110, 34, 41, 10, 32, 32,114,101,116,117,114,110, 10, 32, + 101,110,100, 10, 32, 95, 79, 85, 84, 80, 85, 84, 32, 61, 32, + 111,117,116, 10,101,110,100, 10, 10,102,117,110, 99,116,105, + 111,110, 32,119, 97,114,110,105,110,103, 32, 40,109,115,103, + 41, 10, 32,105,102, 32,102,108, 97,103,115, 46,113, 32,116, + 104,101,110, 32,114,101,116,117,114,110, 32,101,110,100, 10, + 32,108,111, 99, 97,108, 32,111,117,116, 32, 61, 32, 95, 79, + 85, 84, 80, 85, 84, 10, 32, 95, 79, 85, 84, 80, 85, 84, 32, + 61, 32, 95, 83, 84, 68, 69, 82, 82, 10, 32,119,114,105,116, + 101, 40, 34, 92,110, 42, 42, 32,116,111,108,117, 97, 32,119, + 97,114,110,105,110,103, 58, 32, 34, 46, 46,109,115,103, 46, + 46, 34, 46, 92,110, 92,110, 34, 41, 10, 32, 95, 79, 85, 84, + 80, 85, 84, 32, 61, 32,111,117,116, 10,101,110,100, 10, 10, + 45, 45, 32,114,101,103,105,115,116,101,114, 32, 97,110, 32, + 117,115,101,114, 32,100,101,102,105,110,101,100, 32,116,121, + 112,101, 58, 32,114,101,116,117,114,110,115, 32,102,117,108, + 108, 32,116,121,112,101, 10,102,117,110, 99,116,105,111,110, + 32,114,101,103,116,121,112,101, 32, 40,116, 41, 10, 9, 45, + 45,105,102, 32,105,115, 98, 97,115,105, 99, 40,116, 41, 32, + 116,104,101,110, 10, 9, 45, 45, 9,114,101,116,117,114,110, + 32,116, 10, 9, 45, 45,101,110,100, 10, 9,108,111, 99, 97, + 108, 32,102,116, 32, 61, 32,102,105,110,100,116,121,112,101, + 40,116, 41, 10, 10, 9,105,102, 32,110,111,116, 32, 95,117, + 115,101,114,116,121,112,101, 91,102,116, 93, 32,116,104,101, + 110, 10, 9, 9,114,101,116,117,114,110, 32, 97,112,112,101, + 110,100,117,115,101,114,116,121,112,101, 40,116, 41, 10, 9, + 101,110,100, 10, 9,114,101,116,117,114,110, 32,102,116, 10, + 101,110,100, 10, 10, 45, 45, 32,114,101,116,117,114,110, 32, + 116,121,112,101, 32,110, 97,109,101, 58, 32,114,101,116,117, + 114,110,115, 32,102,117,108,108, 32,116,121,112,101, 10,102, + 117,110, 99,116,105,111,110, 32,116,121,112,101,118, 97,114, + 40,116,121,112,101, 41, 10, 9,105,102, 32,116,121,112,101, + 32, 61, 61, 32, 39, 39, 32,111,114, 32,116,121,112,101, 32, + 61, 61, 32, 39,118,111,105,100, 39, 32,116,104,101,110, 10, + 9, 9,114,101,116,117,114,110, 32,116,121,112,101, 10, 9, + 101,108,115,101, 10, 9, 9,108,111, 99, 97,108, 32,102,116, + 32, 61, 32,102,105,110,100,116,121,112,101, 40,116,121,112, + 101, 41, 10, 9, 9,105,102, 32,102,116, 32,116,104,101,110, + 10, 9, 9, 9,114,101,116,117,114,110, 32,102,116, 10, 9, + 9,101,110,100, 10, 9, 9, 95,117,115,101,114,116,121,112, + 101, 91,116,121,112,101, 93, 32, 61, 32,116,121,112,101, 10, + 9, 9,114,101,116,117,114,110, 32,116,121,112,101, 10, 9, + 101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, 99,104,101, + 99,107, 32,105,102, 32, 98, 97,115,105, 99, 32,116,121,112, + 101, 10,102,117,110, 99,116,105,111,110, 32,105,115, 98, 97, + 115,105, 99, 32, 40,116,121,112,101, 41, 10, 32,108,111, 99, + 97,108, 32,116, 32, 61, 32,103,115,117, 98, 40,116,121,112, + 101, 44, 39, 99,111,110,115,116, 32, 39, 44, 39, 39, 41, 10, + 32,108,111, 99, 97,108, 32,109, 44,116, 32, 61, 32, 97,112, + 112,108,121,116,121,112,101,100,101,102, 40, 39, 39, 44, 32, + 116, 41, 10, 32,108,111, 99, 97,108, 32, 98, 32, 61, 32, 95, + 98, 97,115,105, 99, 91,116, 93, 10, 32,105,102, 32, 98, 32, + 116,104,101,110, 10, 32, 32,114,101,116,117,114,110, 32, 98, + 44, 95, 98, 97,115,105, 99, 95, 99,116,121,112,101, 91, 98, + 93, 10, 32,101,110,100, 10, 32,114,101,116,117,114,110, 32, + 110,105,108, 10,101,110,100, 10, 10, 45, 45, 32,115,112,108, + 105,116, 32,115,116,114,105,110,103, 32,117,115,105,110,103, + 32, 97, 32,116,111,107,101,110, 10,102,117,110, 99,116,105, + 111,110, 32,115,112,108,105,116, 32, 40,115, 44,116, 41, 10, + 32,108,111, 99, 97,108, 32,108, 32, 61, 32,123,110, 61, 48, + 125, 10, 32,108,111, 99, 97,108, 32,102, 32, 61, 32,102,117, + 110, 99,116,105,111,110, 32, 40,115, 41, 10, 32, 32,108, 46, + 110, 32, 61, 32,108, 46,110, 32, 43, 32, 49, 10, 32, 32,108, + 91,108, 46,110, 93, 32, 61, 32,115, 10, 32, 32,114,101,116, + 117,114,110, 32, 34, 34, 10, 32,101,110,100, 10, 32,108,111, + 99, 97,108, 32,112, 32, 61, 32, 34, 37,115, 42, 40, 46, 45, + 41, 37,115, 42, 34, 46, 46,116, 46, 46, 34, 37,115, 42, 34, + 10, 32,115, 32, 61, 32,103,115,117, 98, 40,115, 44, 34, 94, + 37,115, 43, 34, 44, 34, 34, 41, 10, 32,115, 32, 61, 32,103, + 115,117, 98, 40,115, 44, 34, 37,115, 43, 36, 34, 44, 34, 34, + 41, 10, 32,115, 32, 61, 32,103,115,117, 98, 40,115, 44,112, + 44,102, 41, 10, 32,108, 46,110, 32, 61, 32,108, 46,110, 32, + 43, 32, 49, 10, 32,108, 91,108, 46,110, 93, 32, 61, 32,103, + 115,117, 98, 40,115, 44, 34, 40, 37,115, 37,115, 42, 41, 36, + 34, 44, 34, 34, 41, 10, 32,114,101,116,117,114,110, 32,108, + 10,101,110,100, 10, 10, 45, 45, 32,115,112,108,105,116,115, + 32, 97, 32,115,116,114,105,110,103, 32,117,115,105,110,103, + 32, 97, 32,112, 97,116,116,101,114,110, 44, 32, 99,111,110, + 115,105,100,101,114,105,110,103, 32,116,104,101, 32,115,112, + 97, 99,105, 97,108, 32, 99, 97,115,101,115, 32,111,102, 32, + 67, 32, 99,111,100,101, 32, 40,116,101,109,112,108, 97,116, + 101,115, 44, 32,102,117,110, 99,116,105,111,110, 32,112, 97, + 114, 97,109,101,116,101,114,115, 44, 32,101,116, 99, 41, 10, + 45, 45, 32,112, 97,116,116,101,114,110, 32, 99, 97,110, 39, + 116, 32, 99,111,110,116, 97,105,110, 32,116,104,101, 32, 39, + 94, 39, 32, 40, 97,115, 32,117,115,101,100, 32,116,111, 32, + 105,100,101,110,116,105,102,121, 32,116,104,101, 32, 98,101, + 103,105,110,105,110,103, 32,111,102, 32,116,104,101, 32,108, + 105,110,101, 41, 10, 45, 45, 32, 97,108,115,111, 32,115,116, + 114,105,112,115, 32,119,104,105,116,101,115,112, 97, 99,101, + 10,102,117,110, 99,116,105,111,110, 32,115,112,108,105,116, + 95, 99, 95,116,111,107,101,110,115, 40,115, 44, 32,112, 97, + 116, 41, 10, 10, 9,115, 32, 61, 32,115,116,114,105,110,103, + 46,103,115,117, 98, 40,115, 44, 32, 34, 94, 37,115, 42, 34, + 44, 32, 34, 34, 41, 10, 9,115, 32, 61, 32,115,116,114,105, + 110,103, 46,103,115,117, 98, 40,115, 44, 32, 34, 37,115, 42, + 36, 34, 44, 32, 34, 34, 41, 10, 10, 9,108,111, 99, 97,108, + 32,116,111,107,101,110, 95, 98,101,103,105,110, 32, 61, 32, + 49, 10, 9,108,111, 99, 97,108, 32,116,111,107,101,110, 95, + 101,110,100, 32, 61, 32, 49, 10, 9,108,111, 99, 97,108, 32, + 111,102,115, 32, 61, 32, 49, 10, 9,108,111, 99, 97,108, 32, + 114,101,116, 32, 61, 32,123,110, 61, 48,125, 10, 10, 9,102, + 117,110, 99,116,105,111,110, 32, 97,100,100, 95,116,111,107, + 101,110, 40,111,102,115, 41, 10, 10, 9, 9,108,111, 99, 97, + 108, 32,116, 32, 61, 32,115,116,114,105,110,103, 46,115,117, + 98, 40,115, 44, 32,116,111,107,101,110, 95, 98,101,103,105, + 110, 44, 32,111,102,115, 41, 10, 9, 9,116, 32, 61, 32,115, + 116,114,105,110,103, 46,103,115,117, 98, 40,116, 44, 32, 34, + 94, 37,115, 42, 34, 44, 32, 34, 34, 41, 10, 9, 9,116, 32, + 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,116, + 44, 32, 34, 37,115, 42, 36, 34, 44, 32, 34, 34, 41, 10, 9, + 9,114,101,116, 46,110, 32, 61, 32,114,101,116, 46,110, 32, + 43, 32, 49, 10, 9, 9,114,101,116, 91,114,101,116, 46,110, + 93, 32, 61, 32,116, 10, 9,101,110,100, 10, 10, 9,119,104, + 105,108,101, 32,111,102,115, 32, 60, 61, 32,115,116,114,105, + 110,103, 46,108,101,110, 40,115, 41, 32,100,111, 10, 10, 9, + 9,108,111, 99, 97,108, 32,115,117, 98, 32, 61, 32,115,116, + 114,105,110,103, 46,115,117, 98, 40,115, 44, 32,111,102,115, + 44, 32, 45, 49, 41, 10, 9, 9,108,111, 99, 97,108, 32, 98, + 44,101, 32, 61, 32,115,116,114,105,110,103, 46,102,105,110, + 100, 40,115,117, 98, 44, 32, 34, 94, 34, 46, 46,112, 97,116, + 41, 10, 9, 9,105,102, 32, 98, 32,116,104,101,110, 10, 9, + 9, 9, 97,100,100, 95,116,111,107,101,110, 40,111,102,115, + 45, 49, 41, 10, 9, 9, 9,111,102,115, 32, 61, 32,111,102, + 115, 43,101, 10, 9, 9, 9,116,111,107,101,110, 95, 98,101, + 103,105,110, 32, 61, 32,111,102,115, 10, 9, 9,101,108,115, + 101, 10, 9, 9, 9,108,111, 99, 97,108, 32, 99,104, 97,114, + 32, 61, 32,115,116,114,105,110,103, 46,115,117, 98, 40,115, + 44, 32,111,102,115, 44, 32,111,102,115, 41, 10, 9, 9, 9, + 105,102, 32, 99,104, 97,114, 32, 61, 61, 32, 34, 40, 34, 32, + 111,114, 32, 99,104, 97,114, 32, 61, 61, 32, 34, 60, 34, 32, + 116,104,101,110, 10, 10, 9, 9, 9, 9,108,111, 99, 97,108, + 32, 98,108,111, 99,107, 10, 9, 9, 9, 9,105,102, 32, 99, + 104, 97,114, 32, 61, 61, 32, 34, 40, 34, 32,116,104,101,110, + 32, 98,108,111, 99,107, 32, 61, 32, 34, 94, 37, 98, 40, 41, + 34, 32,101,110,100, 10, 9, 9, 9, 9,105,102, 32, 99,104, + 97,114, 32, 61, 61, 32, 34, 60, 34, 32,116,104,101,110, 32, + 98,108,111, 99,107, 32, 61, 32, 34, 94, 37, 98, 60, 62, 34, + 32,101,110,100, 10, 10, 9, 9, 9, 9, 98, 44,101, 32, 61, + 32,115,116,114,105,110,103, 46,102,105,110,100, 40,115,117, + 98, 44, 32, 98,108,111, 99,107, 41, 10, 9, 9, 9, 9,105, + 102, 32,110,111,116, 32, 98, 32,116,104,101,110, 10, 9, 9, + 9, 9, 9, 45, 45, 32,117,110,116,101,114,109,105,110, 97, + 116,101,100, 32, 98,108,111, 99,107, 63, 10, 9, 9, 9, 9, + 9,111,102,115, 32, 61, 32,111,102,115, 43, 49, 10, 9, 9, + 9, 9,101,108,115,101, 10, 9, 9, 9, 9, 9,111,102,115, + 32, 61, 32,111,102,115, 32, 43, 32,101, 10, 9, 9, 9, 9, + 101,110,100, 10, 10, 9, 9, 9,101,108,115,101, 10, 9, 9, + 9, 9,111,102,115, 32, 61, 32,111,102,115, 43, 49, 10, 9, + 9, 9,101,110,100, 10, 9, 9,101,110,100, 10, 10, 9,101, + 110,100, 10, 9, 97,100,100, 95,116,111,107,101,110, 40,111, + 102,115, 41, 10, 9, 45, 45,105,102, 32,114,101,116, 46,110, + 32, 61, 61, 32, 48, 32,116,104,101,110, 10, 10, 9, 45, 45, + 9,114,101,116, 46,110, 61, 49, 10, 9, 45, 45, 9,114,101, + 116, 91, 49, 93, 32, 61, 32, 34, 34, 10, 9, 45, 45,101,110, + 100, 10, 10, 9,114,101,116,117,114,110, 32,114,101,116, 10, + 10,101,110,100, 10, 10, 45, 45, 32, 99,111,110, 99, 97,116, + 101,110, 97,116,101, 32,115,116,114,105,110,103,115, 32,111, + 102, 32, 97, 32,116, 97, 98,108,101, 10,102,117,110, 99,116, + 105,111,110, 32, 99,111,110, 99, 97,116, 32, 40,116, 44,102, + 44,108, 44,106,115,116,114, 41, 10, 9,106,115,116,114, 32, + 61, 32,106,115,116,114, 32,111,114, 32, 34, 32, 34, 10, 32, + 108,111, 99, 97,108, 32,115, 32, 61, 32, 39, 39, 10, 32,108, + 111, 99, 97,108, 32,105, 61,102, 10, 32,119,104,105,108,101, + 32,105, 60, 61,108, 32,100,111, 10, 32, 32,115, 32, 61, 32, + 115, 46, 46,116, 91,105, 93, 10, 32, 32,105, 32, 61, 32,105, + 43, 49, 10, 32, 32,105,102, 32,105, 32, 60, 61, 32,108, 32, + 116,104,101,110, 32,115, 32, 61, 32,115, 46, 46,106,115,116, + 114, 32,101,110,100, 10, 32,101,110,100, 10, 32,114,101,116, + 117,114,110, 32,115, 10,101,110,100, 10, 10, 45, 45, 32, 99, + 111,110, 99, 97,116,101,110, 97,116,101, 32, 97,108,108, 32, + 112, 97,114, 97,109,101,116,101,114,115, 44, 32,102,111,108, + 108,111,119,105,110,103, 32,111,117,116,112,117,116, 32,114, + 117,108,101,115, 10,102,117,110, 99,116,105,111,110, 32, 99, + 111,110, 99, 97,116,112, 97,114, 97,109, 32, 40,108,105,110, + 101, 44, 32, 46, 46, 46, 41, 10, 32,108,111, 99, 97,108, 32, + 105, 61, 49, 10, 32,119,104,105,108,101, 32,105, 60, 61, 97, + 114,103, 46,110, 32,100,111, 10, 32, 32,105,102, 32, 95, 99, + 111,110,116, 32, 97,110,100, 32,110,111,116, 32,115,116,114, + 102,105,110,100, 40, 95, 99,111,110,116, 44, 39, 91, 37, 40, + 44, 34, 93, 39, 41, 32, 97,110,100, 10, 32, 32, 32, 32, 32, + 115,116,114,102,105,110,100, 40, 97,114,103, 91,105, 93, 44, + 34, 94, 91, 37, 97, 95,126, 93, 34, 41, 32,116,104,101,110, + 10, 9, 32, 32, 32, 32,108,105,110,101, 32, 61, 32,108,105, + 110,101, 32, 46, 46, 32, 39, 32, 39, 10, 32, 32,101,110,100, + 10, 32, 32,108,105,110,101, 32, 61, 32,108,105,110,101, 32, + 46, 46, 32, 97,114,103, 91,105, 93, 10, 32, 32,105,102, 32, + 97,114,103, 91,105, 93, 32,126, 61, 32, 39, 39, 32,116,104, + 101,110, 10, 32, 32, 32, 95, 99,111,110,116, 32, 61, 32,115, + 116,114,115,117, 98, 40, 97,114,103, 91,105, 93, 44, 45, 49, + 44, 45, 49, 41, 10, 32, 32,101,110,100, 10, 32, 32,105, 32, + 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 32,105,102, 32, + 115,116,114,102,105,110,100, 40, 97,114,103, 91, 97,114,103, + 46,110, 93, 44, 34, 91, 37, 47, 37, 41, 37, 59, 37,123, 37, + 125, 93, 36, 34, 41, 32,116,104,101,110, 10, 32, 32, 95, 99, + 111,110,116, 61,110,105,108, 32,108,105,110,101, 32, 61, 32, + 108,105,110,101, 32, 46, 46, 32, 39, 92,110, 39, 10, 32,101, + 110,100, 10, 9,114,101,116,117,114,110, 32,108,105,110,101, + 10,101,110,100, 10, 10, 45, 45, 32,111,117,116,112,117,116, + 32,108,105,110,101, 10,102,117,110, 99,116,105,111,110, 32, + 111,117,116,112,117,116, 32, 40, 46, 46, 46, 41, 10, 32,108, + 111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104,105,108,101, + 32,105, 60, 61, 97,114,103, 46,110, 32,100,111, 10, 32, 32, + 105,102, 32, 95, 99,111,110,116, 32, 97,110,100, 32,110,111, + 116, 32,115,116,114,102,105,110,100, 40, 95, 99,111,110,116, + 44, 39, 91, 37, 40, 44, 34, 93, 39, 41, 32, 97,110,100, 10, + 32, 32, 32, 32, 32,115,116,114,102,105,110,100, 40, 97,114, + 103, 91,105, 93, 44, 34, 94, 91, 37, 97, 95,126, 93, 34, 41, + 32,116,104,101,110, 10, 9, 32, 32, 32, 32,119,114,105,116, + 101, 40, 39, 32, 39, 41, 10, 32, 32,101,110,100, 10, 32, 32, + 119,114,105,116,101, 40, 97,114,103, 91,105, 93, 41, 10, 32, + 32,105,102, 32, 97,114,103, 91,105, 93, 32,126, 61, 32, 39, + 39, 32,116,104,101,110, 10, 32, 32, 32, 95, 99,111,110,116, + 32, 61, 32,115,116,114,115,117, 98, 40, 97,114,103, 91,105, + 93, 44, 45, 49, 44, 45, 49, 41, 10, 32, 32,101,110,100, 10, + 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, + 32,105,102, 32,115,116,114,102,105,110,100, 40, 97,114,103, + 91, 97,114,103, 46,110, 93, 44, 34, 91, 37, 47, 37, 41, 37, + 59, 37,123, 37,125, 93, 36, 34, 41, 32,116,104,101,110, 10, + 32, 32, 95, 99,111,110,116, 61,110,105,108, 32,119,114,105, + 116,101, 40, 39, 92,110, 39, 41, 10, 32,101,110,100, 10,101, + 110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,103,101, + 116, 95,112,114,111,112,101,114,116,121, 95,109,101,116,104, + 111,100,115, 40,112,116,121,112,101, 44, 32,110, 97,109,101, + 41, 10, 10, 9,105,102, 32,103,101,116, 95,112,114,111,112, + 101,114,116,121, 95,109,101,116,104,111,100,115, 95,104,111, + 111,107, 32, 97,110,100, 32,103,101,116, 95,112,114,111,112, + 101,114,116,121, 95,109,101,116,104,111,100,115, 95,104,111, + 111,107, 40,112,116,121,112,101, 44,110, 97,109,101, 41, 32, + 116,104,101,110, 10, 9, 9,114,101,116,117,114,110, 32,103, + 101,116, 95,112,114,111,112,101,114,116,121, 95,109,101,116, + 104,111,100,115, 95,104,111,111,107, 40,112,116,121,112,101, + 44, 32,110, 97,109,101, 41, 10, 9,101,110,100, 10, 10, 9, + 105,102, 32,112,116,121,112,101, 32, 61, 61, 32, 34,100,101, + 102, 97,117,108,116, 34, 32,116,104,101,110, 32, 45, 45, 32, + 103,101,116, 95,110, 97,109,101, 44, 32,115,101,116, 95,110, + 97,109,101, 10, 9, 9,114,101,116,117,114,110, 32, 34,103, + 101,116, 95, 34, 46, 46,110, 97,109,101, 44, 32, 34,115,101, + 116, 95, 34, 46, 46,110, 97,109,101, 10, 9,101,110,100, 10, + 10, 9,105,102, 32,112,116,121,112,101, 32, 61, 61, 32, 34, + 113,116, 34, 32,116,104,101,110, 32, 45, 45, 32,110, 97,109, + 101, 44, 32,115,101,116, 78, 97,109,101, 10, 9, 9,114,101, + 116,117,114,110, 32,110, 97,109,101, 44, 32, 34,115,101,116, + 34, 46, 46,115,116,114,105,110,103, 46,117,112,112,101,114, + 40,115,116,114,105,110,103, 46,115,117, 98, 40,110, 97,109, + 101, 44, 32, 49, 44, 32, 49, 41, 41, 46, 46,115,116,114,105, + 110,103, 46,115,117, 98, 40,110, 97,109,101, 44, 32, 50, 44, + 32, 45, 49, 41, 10, 9,101,110,100, 10, 10, 9,105,102, 32, + 112,116,121,112,101, 32, 61, 61, 32, 34,111,118,101,114,108, + 111, 97,100, 34, 32,116,104,101,110, 32, 45, 45, 32,110, 97, + 109,101, 44, 32,110, 97,109,101, 10, 9, 9,114,101,116,117, + 114,110, 32,110, 97,109,101, 44,110, 97,109,101, 10, 9,101, + 110,100, 10, 10, 9,114,101,116,117,114,110, 32,110,105,108, + 10,101,110,100, 10, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 32,116,104,101, 32,104,111,111,107,115, + 10, 10, 45, 45, 32, 99, 97,108,108,101,100, 32,114,105,103, + 104,116, 32, 97,102,116,101,114, 32,112,114,111, 99,101,115, + 115,105,110,103, 32,116,104,101, 32, 36, 91,105, 99,104,108, + 93,102,105,108,101, 32,100,105,114,101, 99,116,105,118,101, + 115, 44, 10, 45, 45, 32,114,105,103,104,116, 32, 98,101,102, + 111,114,101, 32,112,114,111, 99,101,115,115,105,110,103, 32, + 97,110,121,116,104,105,110,103, 32,101,108,115,101, 10, 45, + 45, 32,116, 97,107,101,115, 32,116,104,101, 32,112, 97, 99, + 107, 97,103,101, 32,111, 98,106,101, 99,116, 32, 97,115, 32, + 116,104,101, 32,112, 97,114, 97,109,101,116,101,114, 10,102, + 117,110, 99,116,105,111,110, 32,112,114,101,112,114,111, 99, + 101,115,115, 95,104,111,111,107, 40,112, 41, 10, 9, 45, 45, + 32,112, 46, 99,111,100,101, 32,104, 97,115, 32, 97,108,108, + 32,116,104,101, 32,105,110,112,117,116, 32, 99,111,100,101, + 32,102,114,111,109, 32,116,104,101, 32,112,107,103, 10,101, + 110,100, 10, 10, 10, 45, 45, 32, 99, 97,108,108,101,100, 32, + 102,111,114, 32,101,118,101,114,121, 32, 36,105,102,105,108, + 101, 32,100,105,114,101, 99,116,105,118,101, 10, 45, 45, 32, + 116, 97,107,101,115, 32, 97, 32,116, 97, 98,108,101, 32,119, + 105,116,104, 32, 97, 32,115,116,114,105,110,103, 32, 99, 97, + 108,108,101,100, 32, 39, 99,111,100,101, 39, 32,105,110,115, + 105,100,101, 44, 32,116,104,101, 32,102,105,108,101,110, 97, + 109,101, 44, 32, 97,110,100, 32, 97,110,121, 32,101,120,116, + 114, 97, 32, 97,114,103,117,109,101,110,116,115, 10, 45, 45, + 32,112, 97,115,115,101,100, 32,116,111, 32, 36,105,102,105, + 108,101, 46, 32,110,111, 32,114,101,116,117,114,110, 32,118, + 97,108,117,101, 10,102,117,110, 99,116,105,111,110, 32,105, + 110, 99,108,117,100,101, 95,102,105,108,101, 95,104,111,111, + 107, 40,116, 44, 32,102,105,108,101,110, 97,109,101, 44, 32, + 46, 46, 46, 41, 10, 10,101,110,100, 10, 10, 45, 45, 32, 99, + 97,108,108,101,100, 32, 97,102,116,101,114, 32,112,114,111, + 99,101,115,115,105,110,103, 32, 97,110,121,116,104,105,110, + 103, 32,116,104, 97,116, 39,115, 32,110,111,116, 32, 99,111, + 100,101, 32, 40,108,105,107,101, 32, 39, 36,114,101,110, 97, + 109,105,110,103, 39, 44, 32, 99,111,109,109,101,110,116,115, + 44, 32,101,116, 99, 41, 10, 45, 45, 32, 97,110,100, 32,114, + 105,103,104,116, 32, 98,101,102,111,114,101, 32,112, 97,114, + 115,105,110,103, 32,116,104,101, 32, 97, 99,116,117, 97,108, + 32, 99,111,100,101, 46, 10, 45, 45, 32,116, 97,107,101,115, + 32,116,104,101, 32, 80, 97, 99,107, 97,103,101, 32,111, 98, + 106,101, 99,116, 32,119,105,116,104, 32, 97,108,108, 32,116, + 104,101, 32, 99,111,100,101, 32,111,110, 32,116,104,101, 32, + 39, 99,111,100,101, 39, 32,107,101,121, 46, 32,110,111, 32, + 114,101,116,117,114,110, 32,118, 97,108,117,101, 10,102,117, + 110, 99,116,105,111,110, 32,112,114,101,112, 97,114,115,101, + 95,104,111,111,107, 40,112, 97, 99,107, 97,103,101, 41, 10, + 10,101,110,100, 10, 10, 10, 45, 45, 32, 99, 97,108,108,101, + 100, 32, 97,102,116,101,114, 32,119,114,105,116,105,110,103, + 32, 97,108,108, 32,116,104,101, 32,111,117,116,112,117,116, + 46, 10, 45, 45, 32,116, 97,107,101,115, 32,116,104,101, 32, + 80, 97, 99,107, 97,103,101, 32,111, 98,106,101, 99,116, 10, + 102,117,110, 99,116,105,111,110, 32,112,111,115,116, 95,111, + 117,116,112,117,116, 95,104,111,111,107, 40,112, 97, 99,107, + 97,103,101, 41, 10, 10,101,110,100, 10, 10, 10, 45, 45, 32, + 99, 97,108,108,101,100, 32,102,114,111,109, 32, 39,103,101, + 116, 95,112,114,111,112,101,114,116,121, 95,109,101,116,104, + 111,100,115, 39, 32,116,111, 32,103,101,116, 32,116,104,101, + 32,109,101,116,104,111,100,115, 32,116,111, 32,114,101,116, + 114,105,101,118,101, 32, 97, 32,112,114,111,112,101,114,116, + 121, 10, 45, 45, 32, 97, 99, 99,111,114,100,105,110,103, 32, + 116,111, 32,105,116,115, 32,116,121,112,101, 10,102,117,110, + 99,116,105,111,110, 32,103,101,116, 95,112,114,111,112,101, + 114,116,121, 95,109,101,116,104,111,100,115, 95,104,111,111, + 107, 40,112,114,111,112,101,114,116,121, 95,116,121,112,101, + 44, 32,110, 97,109,101, 41, 10, 10,101,110,100, 10, 10, 45, + 45, 32, 99, 97,108,108,101,100, 32,102,114,111,109, 32, 67, + 108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 58,100, + 111,112, 97,114,115,101, 32,119,105,116,104, 32,116,104,101, + 32,115,116,114,105,110,103, 32, 98,101,105,110,103, 32,112, + 97,114,115,101,100, 10, 45, 45, 32,114,101,116,117,114,110, + 32,110,105,108, 44, 32,111,114, 32, 97, 32,115,117, 98,115, + 116,114,105,110,103, 10,102,117,110, 99,116,105,111,110, 32, + 112, 97,114,115,101,114, 95,104,111,111,107, 40,115, 41, 10, + 10, 9,114,101,116,117,114,110, 32,110,105,108, 10,101,110, + 100, 10, 10, 45, 45, 32, 99,117,115,116,111,109, 32,112,117, + 115,104,101,114,115, 10, 10, 95,112,117,115,104, 95,102,117, + 110, 99,116,105,111,110,115, 32, 61, 32,123,125, 10, 95,105, + 115, 95,102,117,110, 99,116,105,111,110,115, 32, 61, 32,123, + 125, 10, 95,116,111, 95,102,117,110, 99,116,105,111,110,115, + 32, 61, 32,123,125, 10, 10, 95, 98, 97,115,101, 95,112,117, + 115,104, 95,102,117,110, 99,116,105,111,110,115, 32, 61, 32, + 123,125, 10, 95, 98, 97,115,101, 95,105,115, 95,102,117,110, + 99,116,105,111,110,115, 32, 61, 32,123,125, 10, 95, 98, 97, + 115,101, 95,116,111, 95,102,117,110, 99,116,105,111,110,115, + 32, 61, 32,123,125, 10, 10,108,111, 99, 97,108, 32,102,117, + 110, 99,116,105,111,110, 32,115,101, 97,114, 99,104, 95, 98, + 97,115,101, 40,116, 44, 32,102,117,110, 99,115, 41, 10, 10, + 9,108,111, 99, 97,108, 32, 99,108, 97,115,115, 32, 61, 32, + 95,103,108,111, 98, 97,108, 95, 99,108, 97,115,115,101,115, + 91,116, 93, 10, 10, 9,119,104,105,108,101, 32, 99,108, 97, + 115,115, 32,100,111, 10, 9, 9,105,102, 32,102,117,110, 99, + 115, 91, 99,108, 97,115,115, 46,116,121,112,101, 93, 32,116, + 104,101,110, 10, 9, 9, 9,114,101,116,117,114,110, 32,102, + 117,110, 99,115, 91, 99,108, 97,115,115, 46,116,121,112,101, + 93, 10, 9, 9,101,110,100, 10, 9, 9, 99,108, 97,115,115, + 32, 61, 32, 95,103,108,111, 98, 97,108, 95, 99,108, 97,115, + 115,101,115, 91, 99,108, 97,115,115, 46, 98,116,121,112,101, + 93, 10, 9,101,110,100, 10, 9,114,101,116,117,114,110, 32, + 110,105,108, 10,101,110,100, 10, 10,102,117,110, 99,116,105, + 111,110, 32,103,101,116, 95,112,117,115,104, 95,102,117,110, + 99,116,105,111,110, 40,116, 41, 10, 9,114,101,116,117,114, + 110, 32, 95,112,117,115,104, 95,102,117,110, 99,116,105,111, + 110,115, 91,116, 93, 32,111,114, 32,115,101, 97,114, 99,104, + 95, 98, 97,115,101, 40,116, 44, 32, 95, 98, 97,115,101, 95, + 112,117,115,104, 95,102,117,110, 99,116,105,111,110,115, 41, + 32,111,114, 32, 34,116,111,108,117, 97, 95,112,117,115,104, + 117,115,101,114,116,121,112,101, 34, 10,101,110,100, 10, 10, + 102,117,110, 99,116,105,111,110, 32,103,101,116, 95,116,111, + 95,102,117,110, 99,116,105,111,110, 40,116, 41, 10, 9,114, + 101,116,117,114,110, 32, 95,116,111, 95,102,117,110, 99,116, + 105,111,110,115, 91,116, 93, 32,111,114, 32,115,101, 97,114, + 99,104, 95, 98, 97,115,101, 40,116, 44, 32, 95, 98, 97,115, + 101, 95,116,111, 95,102,117,110, 99,116,105,111,110,115, 41, + 32,111,114, 32, 34,116,111,108,117, 97, 95,116,111,117,115, + 101,114,116,121,112,101, 34, 10,101,110,100, 10, 10,102,117, + 110, 99,116,105,111,110, 32,103,101,116, 95,105,115, 95,102, + 117,110, 99,116,105,111,110, 40,116, 41, 10, 9,114,101,116, + 117,114,110, 32, 95,105,115, 95,102,117,110, 99,116,105,111, + 110,115, 91,116, 93, 32,111,114, 32,115,101, 97,114, 99,104, + 95, 98, 97,115,101, 40,116, 44, 32, 95, 98, 97,115,101, 95, + 105,115, 95,102,117,110, 99,116,105,111,110,115, 41, 32,111, + 114, 32, 34,116,111,108,117, 97, 95,105,115,117,115,101,114, + 116,121,112,101, 34, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/basic.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32, 97, 98,115,116,114, + 97, 99,116, 32,102,101, 97,116,117,114,101, 32, 99,108, 97, + 115,115, 10, 45, 45, 32, 87,114,105,116,116,101,110, 32, 98, + 121, 32, 87, 97,108,100,101,109, 97,114, 32, 67,101,108,101, + 115, 10, 45, 45, 32, 84,101, 67, 71,114, 97,102, 47, 80, 85, + 67, 45, 82,105,111, 10, 45, 45, 32, 74,117,108, 32, 49, 57, + 57, 56, 10, 45, 45, 32, 36, 73,100, 58, 32, 36, 10, 10, 45, + 45, 32, 84,104,105,115, 32, 99,111,100,101, 32,105,115, 32, + 102,114,101,101, 32,115,111,102,116,119, 97,114,101, 59, 32, + 121,111,117, 32, 99, 97,110, 32,114,101,100,105,115,116,114, + 105, 98,117,116,101, 32,105,116, 32, 97,110,100, 47,111,114, + 32,109,111,100,105,102,121, 32,105,116, 46, 10, 45, 45, 32, + 84,104,101, 32,115,111,102,116,119, 97,114,101, 32,112,114, + 111,118,105,100,101,100, 32,104,101,114,101,117,110,100,101, + 114, 32,105,115, 32,111,110, 32, 97,110, 32, 34, 97,115, 32, + 105,115, 34, 32, 98, 97,115,105,115, 44, 32, 97,110,100, 10, + 45, 45, 32,116,104,101, 32, 97,117,116,104,111,114, 32,104, + 97,115, 32,110,111, 32,111, 98,108,105,103, 97,116,105,111, + 110, 32,116,111, 32,112,114,111,118,105,100,101, 32,109, 97, + 105,110,116,101,110, 97,110, 99,101, 44, 32,115,117,112,112, + 111,114,116, 44, 32,117,112,100, 97,116,101,115, 44, 10, 45, + 45, 32,101,110,104, 97,110, 99,101,109,101,110,116,115, 44, + 32,111,114, 32,109,111,100,105,102,105, 99, 97,116,105,111, + 110,115, 46, 10, 10, 10, 45, 45, 32, 70,101, 97,116,117,114, + 101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 82,101,112,114, + 101,115,101,110,116,115, 32,116,104,101, 32, 98, 97,115,101, + 32, 99,108, 97,115,115, 32,111,102, 32, 97,108,108, 32,109, + 97,112,112,101,100, 32,102,101, 97,116,117,114,101, 46, 10, + 99,108, 97,115,115, 70,101, 97,116,117,114,101, 32, 61, 32, + 123, 10,125, 10, 99,108, 97,115,115, 70,101, 97,116,117,114, + 101, 46, 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97, + 115,115, 70,101, 97,116,117,114,101, 10, 10, 45, 45, 32,119, + 114,105,116,101, 32,115,117,112,112,111,114,116, 32, 99,111, + 100,101, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 70,101, 97,116,117,114,101, 58,115,117,112, 99,111, + 100,101, 32, 40, 41, 10,101,110,100, 10, 10, 45, 45, 32,111, + 117,116,112,117,116, 32,116, 97,103, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 70,101, 97,116,117,114, + 101, 58,100,101, 99,108,116,121,112,101, 32, 40, 41, 10,101, + 110,100, 10, 10, 45, 45, 32,114,101,103,105,115,116,101,114, + 32,102,101, 97,116,117,114,101, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, + 58,114,101,103,105,115,116,101,114, 32, 40,112,114,101, 41, + 10,101,110,100, 10, 10, 45, 45, 32,116,114, 97,110,115,108, + 97,116,101, 32,118,101,114, 98, 97,116,105,109, 10,102,117, + 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 70,101, 97, + 116,117,114,101, 58,112,114,101, 97,109, 98,108,101, 32, 40, + 41, 10,101,110,100, 10, 10, 45, 45, 32, 99,104,101, 99,107, + 32,105,102, 32,105,116, 32,105,115, 32, 97, 32,118, 97,114, + 105, 97, 98,108,101, 10,102,117,110, 99,116,105,111,110, 32, + 99,108, 97,115,115, 70,101, 97,116,117,114,101, 58,105,115, + 118, 97,114,105, 97, 98,108,101, 32, 40, 41, 10, 32,114,101, + 116,117,114,110, 32,102, 97,108,115,101, 10,101,110,100, 10, + 10, 45, 45, 32, 99,104,101, 99,107, 32,105,102, 32,105,116, + 32,114,101,113,117,105,114,101,115, 32, 99,111,108,108,101, + 99,116,105,111,110, 10,102,117,110, 99,116,105,111,110, 32, + 99,108, 97,115,115, 70,101, 97,116,117,114,101, 58,114,101, + 113,117,105,114,101, 99,111,108,108,101, 99,116,105,111,110, + 32, 40,116, 41, 10, 32,114,101,116,117,114,110, 32,102, 97, + 108,115,101, 10,101,110,100, 10, 10, 45, 45, 32, 98,117,105, + 108,100, 32,110, 97,109,101,115, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, + 58, 98,117,105,108,100,110, 97,109,101,115, 32, 40, 41, 10, + 32,105,102, 32,115,101,108,102, 46,110, 97,109,101, 32, 97, + 110,100, 32,115,101,108,102, 46,110, 97,109,101,126, 61, 39, + 39, 32,116,104,101,110, 10, 32, 32,108,111, 99, 97,108, 32, + 110, 32, 61, 32,115,112,108,105,116, 40,115,101,108,102, 46, + 110, 97,109,101, 44, 39, 64, 39, 41, 10, 32, 32,115,101,108, + 102, 46,110, 97,109,101, 32, 61, 32,110, 91, 49, 93, 10, 32, + 32,115,101,108,102, 46,110, 97,109,101, 32, 61, 32,115,116, + 114,105,110,103, 46,103,115,117, 98, 40,115,101,108,102, 46, + 110, 97,109,101, 44, 32, 34, 58, 37,100, 42, 36, 34, 44, 32, + 34, 34, 41, 10, 32, 32,105,102, 32,110,111,116, 32,110, 91, + 50, 93, 32,116,104,101,110, 10, 32, 32, 32,110, 91, 50, 93, + 32, 61, 32, 97,112,112,108,121,114,101,110, 97,109,105,110, + 103, 40,110, 91, 49, 93, 41, 10, 32, 32,101,110,100, 10, 32, + 32,115,101,108,102, 46,108,110, 97,109,101, 32, 61, 32,110, + 91, 50, 93, 32,111,114, 32,103,115,117, 98, 40,110, 91, 49, + 93, 44, 34, 37, 91, 46, 45, 37, 93, 34, 44, 34, 34, 41, 10, + 32, 32,115,101,108,102, 46,108,110, 97,109,101, 32, 61, 32, + 115,116,114,105,110,103, 46,103,115,117, 98, 40,115,101,108, + 102, 46,108,110, 97,109,101, 44, 32, 34, 58, 37,100, 42, 36, + 34, 44, 32, 34, 34, 41, 10, 32, 32,115,101,108,102, 46,111, + 114,105,103,105,110, 97,108, 95,110, 97,109,101, 32, 61, 32, + 115,101,108,102, 46,110, 97,109,101, 10, 32, 32,115,101,108, + 102, 46,108,110, 97,109,101, 32, 61, 32, 99,108,101, 97,110, + 95,116,101,109,112,108, 97,116,101, 40,115,101,108,102, 46, + 108,110, 97,109,101, 41, 10, 32,101,110,100, 10, 32,105,102, + 32,110,111,116, 32,115,101,108,102, 46,105,115, 95,112, 97, + 114, 97,109,101,116,101,114, 32,116,104,101,110, 10, 9, 32, + 115,101,108,102, 46,110, 97,109,101, 32, 61, 32,103,101,116, + 111,110,108,121,110, 97,109,101,115,112, 97, 99,101, 40, 41, + 32, 46, 46, 32,115,101,108,102, 46,110, 97,109,101, 10, 32, + 101,110,100, 10, 10, 32,108,111, 99, 97,108, 32,112, 97,114, + 101,110,116, 32, 61, 32, 99,108, 97,115,115, 67,111,110,116, + 97,105,110,101,114, 46, 99,117,114,114, 10, 32,105,102, 32, + 112, 97,114,101,110,116, 32,116,104,101,110, 10, 32, 9,115, + 101,108,102, 46, 97, 99, 99,101,115,115, 32, 61, 32,112, 97, + 114,101,110,116, 46, 99,117,114,114, 95,109,101,109, 98,101, + 114, 95, 97, 99, 99,101,115,115, 10, 9,115,101,108,102, 46, + 103,108,111, 98, 97,108, 95, 97, 99, 99,101,115,115, 32, 61, + 32,115,101,108,102, 58, 99,104,101, 99,107, 95,112,117, 98, + 108,105, 99, 95, 97, 99, 99,101,115,115, 40, 41, 10, 32,101, + 108,115,101, 10, 32,101,110,100, 10,101,110,100, 10, 10,102, + 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 70,101, + 97,116,117,114,101, 58, 99,104,101, 99,107, 95,112,117, 98, + 108,105, 99, 95, 97, 99, 99,101,115,115, 40, 41, 10, 10, 9, + 105,102, 32,116,121,112,101, 40,115,101,108,102, 46,103,108, + 111, 98, 97,108, 95, 97, 99, 99,101,115,115, 41, 32, 61, 61, + 32, 34, 98,111,111,108,101, 97,110, 34, 32,116,104,101,110, + 10, 9, 9,114,101,116,117,114,110, 32,115,101,108,102, 46, + 103,108,111, 98, 97,108, 95, 97, 99, 99,101,115,115, 10, 9, + 101,110,100, 10, 10, 9,105,102, 32,115,101,108,102, 46, 97, + 99, 99,101,115,115, 32, 97,110,100, 32,115,101,108,102, 46, + 97, 99, 99,101,115,115, 32,126, 61, 32, 48, 32,116,104,101, + 110, 10, 9, 9,114,101,116,117,114,110, 32,102, 97,108,115, + 101, 10, 9,101,110,100, 10, 10, 9,108,111, 99, 97,108, 32, + 112, 97,114,101,110,116, 32, 61, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 10, 9, + 119,104,105,108,101, 32,112, 97,114,101,110,116, 32,100,111, + 10, 9, 9,105,102, 32,112, 97,114,101,110,116, 46, 97, 99, + 99,101,115,115, 32, 97,110,100, 32,112, 97,114,101,110,116, + 46, 97, 99, 99,101,115,115, 32,126, 61, 32, 48, 32,116,104, + 101,110, 10, 9, 9, 9,114,101,116,117,114,110, 32,102, 97, + 108,115,101, 10, 9, 9,101,110,100, 10, 9, 9,112, 97,114, + 101,110,116, 32, 61, 32,112, 97,114,101,110,116, 46,112,114, + 111,120, 10, 9,101,110,100, 10, 9,114,101,116,117,114,110, + 32,116,114,117,101, 10,101,110,100, 10, 10,102,117,110, 99, + 116,105,111,110, 32, 99,108,101, 97,110, 95,116,101,109,112, + 108, 97,116,101, 40,116, 41, 10, 10, 9,114,101,116,117,114, + 110, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,116, + 44, 32, 34, 91, 60, 62, 58, 44, 32, 37, 42, 93, 34, 44, 32, + 34, 95, 34, 41, 10,101,110,100, 10, 10, 45, 45, 32, 99,104, + 101, 99,107, 32,105,102, 32,102,101, 97,116,117,114,101, 32, + 105,115, 32,105,110,115,105,100,101, 32, 97, 32, 99,111,110, + 116, 97,105,110,101,114, 32,100,101,102,105,110,105,116,105, + 111,110, 10, 45, 45, 32,105,116, 32,114,101,116,117,114,110, + 115, 32,116,104,101, 32, 99,111,110,116, 97,105,110,101,114, + 32, 99,108, 97,115,115, 32,110, 97,109,101, 32,111,114, 32, + 110,105,108, 46, 10,102,117,110, 99,116,105,111,110, 32, 99, + 108, 97,115,115, 70,101, 97,116,117,114,101, 58,105,110, 99, + 111,110,116, 97,105,110,101,114, 32, 40,119,104,105, 99,104, + 41, 10, 32,105,102, 32,115,101,108,102, 46,112, 97,114,101, + 110,116, 32,116,104,101,110, 10, 32, 32,108,111, 99, 97,108, + 32,112, 97,114,101,110,116, 32, 61, 32,115,101,108,102, 46, + 112, 97,114,101,110,116, 10, 32, 32,119,104,105,108,101, 32, + 112, 97,114,101,110,116, 32,100,111, 10, 32, 32, 32,105,102, + 32,112, 97,114,101,110,116, 46, 99,108, 97,115,115,116,121, + 112,101, 32, 61, 61, 32,119,104,105, 99,104, 32,116,104,101, + 110, 10, 32, 32, 32, 32,114,101,116,117,114,110, 32,112, 97, + 114,101,110,116, 46,110, 97,109,101, 10, 32, 32, 32,101,110, + 100, 10, 32, 32, 32,112, 97,114,101,110,116, 32, 61, 32,112, + 97,114,101,110,116, 46,112, 97,114,101,110,116, 10, 32, 32, + 101,110,100, 10, 32,101,110,100, 10, 32,114,101,116,117,114, + 110, 32,110,105,108, 10,101,110,100, 10, 10,102,117,110, 99, + 116,105,111,110, 32, 99,108, 97,115,115, 70,101, 97,116,117, + 114,101, 58,105,110, 99,108, 97,115,115, 32, 40, 41, 10, 32, + 114,101,116,117,114,110, 32,115,101,108,102, 58,105,110, 99, + 111,110,116, 97,105,110,101,114, 40, 39, 99,108, 97,115,115, + 39, 41, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 58, + 105,110,109,111,100,117,108,101, 32, 40, 41, 10, 32,114,101, + 116,117,114,110, 32,115,101,108,102, 58,105,110, 99,111,110, + 116, 97,105,110,101,114, 40, 39,109,111,100,117,108,101, 39, + 41, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, + 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 58,105, + 110,110, 97,109,101,115,112, 97, 99,101, 32, 40, 41, 10, 32, + 114,101,116,117,114,110, 32,115,101,108,102, 58,105,110, 99, + 111,110,116, 97,105,110,101,114, 40, 39,110, 97,109,101,115, + 112, 97, 99,101, 39, 41, 10,101,110,100, 10, 10, 45, 45, 32, + 114,101,116,117,114,110, 32, 67, 32, 98,105,110,100,105,110, + 103, 32,102,117,110, 99,116,105,111,110, 32,110, 97,109,101, + 32, 98, 97,115,101,100, 32,111,110, 32,110, 97,109,101, 10, + 45, 45, 32,116,104,101, 32, 99,108,105,101,110,116, 32,115, + 112,101, 99,105,102,105,101,115, 32, 97, 32,112,114,101,102, + 105,120, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 70,101, 97,116,117,114,101, 58, 99,102,117,110, 99, + 110, 97,109,101, 32, 40,110, 41, 10, 10, 32,105,102, 32,115, + 101,108,102, 46,112, 97,114,101,110,116, 32,116,104,101,110, + 10, 32, 32,110, 32, 61, 32,115,101,108,102, 46,112, 97,114, + 101,110,116, 58, 99,102,117,110, 99,110, 97,109,101, 40,110, + 41, 10, 32,101,110,100, 10, 10, 32,108,111, 99, 97,108, 32, + 102,110, 97,109,101, 32, 61, 32,115,101,108,102, 46,108,110, + 97,109,101, 10, 32,105,102, 32,110,111,116, 32,102,110, 97, + 109,101, 32,111,114, 32,102,110, 97,109,101, 32, 61, 61, 32, + 39, 39, 32,116,104,101,110, 10, 32, 9,102,110, 97,109,101, + 32, 61, 32,115,101,108,102, 46,110, 97,109,101, 10, 32,101, + 110,100, 10, 32, 32,110, 32, 61, 32,115,116,114,105,110,103, + 46,103,115,117, 98, 40,110, 46, 46, 39, 95, 39, 46, 46, 32, + 40,102,110, 97,109,101, 41, 44, 32, 34, 91, 60, 62, 58, 44, + 32, 92, 46, 37, 42, 38, 93, 34, 44, 32, 34, 95, 34, 41, 10, + 10, 32, 32,114,101,116,117,114,110, 32,110, 10,101,110,100, + 32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/feature.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,118,101,114, 98, 97, + 116,105,109, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114, + 105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, + 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, + 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, + 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73, + 100, 58, 32,118,101,114, 98, 97,116,105,109, 46,108,117, 97, + 44,118, 32, 49, 46, 51, 32, 50, 48, 48, 48, 47, 48, 49, 47, + 50, 52, 32, 50, 48, 58, 52, 49, 58, 49, 54, 32, 99,101,108, + 101,115, 32, 69,120,112, 32, 36, 10, 10, 45, 45, 32, 84,104, + 105,115, 32, 99,111,100,101, 32,105,115, 32,102,114,101,101, + 32,115,111,102,116,119, 97,114,101, 59, 32,121,111,117, 32, + 99, 97,110, 32,114,101,100,105,115,116,114,105, 98,117,116, + 101, 32,105,116, 32, 97,110,100, 47,111,114, 32,109,111,100, + 105,102,121, 32,105,116, 46, 10, 45, 45, 32, 84,104,101, 32, + 115,111,102,116,119, 97,114,101, 32,112,114,111,118,105,100, + 101,100, 32,104,101,114,101,117,110,100,101,114, 32,105,115, + 32,111,110, 32, 97,110, 32, 34, 97,115, 32,105,115, 34, 32, + 98, 97,115,105,115, 44, 32, 97,110,100, 10, 45, 45, 32,116, + 104,101, 32, 97,117,116,104,111,114, 32,104, 97,115, 32,110, + 111, 32,111, 98,108,105,103, 97,116,105,111,110, 32,116,111, + 32,112,114,111,118,105,100,101, 32,109, 97,105,110,116,101, + 110, 97,110, 99,101, 44, 32,115,117,112,112,111,114,116, 44, + 32,117,112,100, 97,116,101,115, 44, 10, 45, 45, 32,101,110, + 104, 97,110, 99,101,109,101,110,116,115, 44, 32,111,114, 32, + 109,111,100,105,102,105, 99, 97,116,105,111,110,115, 46, 10, + 10, 10, 10, 45, 45, 32, 86,101,114, 98, 97,116,105,109, 32, + 99,108, 97,115,115, 10, 45, 45, 32, 82,101,112,114,101,115, + 101,110,116,115, 32, 97, 32,108,105,110,101, 32,116,114, 97, + 110,115,108, 97,116,101,100, 32,100,105,114,101, 99,116,101, + 100, 32,116,111, 32,116,104,101, 32, 98,105,110,100,105,110, + 103, 32,102,105,108,101, 46, 10, 45, 45, 32, 84,104,101, 32, + 102,111,108,108,111,119,105,110,103, 32,102,105,108,100,115, + 32, 97,114,101, 32,115,116,111,114,101,100, 58, 10, 45, 45, + 32, 32, 32,108,105,110,101, 32, 61, 32,108,105,110,101, 32, + 116,101,120,116, 10, 99,108, 97,115,115, 86,101,114, 98, 97, + 116,105,109, 32, 61, 32,123, 10, 32,108,105,110,101, 32, 61, + 32, 39, 39, 44, 10, 9, 99,111,110,100, 32, 61, 32,110,105, + 108, 44, 32, 32, 32, 32, 45, 45, 32, 99,111,110,100,105,116, + 105,111,110, 58, 32,119,104,101,114,101, 32,116,111, 32,103, + 101,110,101,114, 97,116,101, 32,116,104,101, 32, 99,111,100, + 101, 32, 40,115, 61,115,117,112,111,114,116, 44, 32,114, 61, + 114,101,103,105,115,116,101,114, 41, 10,125, 10, 99,108, 97, + 115,115, 86,101,114, 98, 97,116,105,109, 46, 95, 95,105,110, + 100,101,120, 32, 61, 32, 99,108, 97,115,115, 86,101,114, 98, + 97,116,105,109, 10,115,101,116,109,101,116, 97,116, 97, 98, + 108,101, 40, 99,108, 97,115,115, 86,101,114, 98, 97,116,105, + 109, 44, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 41, + 10, 10, 45, 45, 32,112,114,101, 97,109, 98,108,101, 32,118, + 101,114, 98, 97,116,105,109, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 86,101,114, 98, 97,116,105,109, + 58,112,114,101, 97,109, 98,108,101, 32, 40, 41, 10, 32,105, + 102, 32,115,101,108,102, 46, 99,111,110,100, 32, 61, 61, 32, + 39, 39, 32,116,104,101,110, 10, 32, 32,119,114,105,116,101, + 40,115,101,108,102, 46,108,105,110,101, 41, 10, 32,101,110, + 100, 10,101,110,100, 10, 10, 45, 45, 32,115,117,112,112,111, + 114,116, 32, 99,111,100,101, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 86,101,114, 98, 97,116,105,109, + 58,115,117,112, 99,111,100,101, 32, 40, 41, 10, 32,105,102, + 32,115,116,114,102,105,110,100, 40,115,101,108,102, 46, 99, + 111,110,100, 44, 39,115, 39, 41, 32,116,104,101,110, 10, 32, + 32,119,114,105,116,101, 40,115,101,108,102, 46,108,105,110, + 101, 41, 10, 32, 32,119,114,105,116,101, 40, 39, 92,110, 39, + 41, 10, 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, + 114,101,103,105,115,116,101,114, 32, 99,111,100,101, 10,102, + 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 86,101, + 114, 98, 97,116,105,109, 58,114,101,103,105,115,116,101,114, + 32, 40,112,114,101, 41, 10, 32,105,102, 32,115,116,114,102, + 105,110,100, 40,115,101,108,102, 46, 99,111,110,100, 44, 39, + 114, 39, 41, 32,116,104,101,110, 10, 32, 32,119,114,105,116, + 101, 40,115,101,108,102, 46,108,105,110,101, 41, 10, 32,101, + 110,100, 10,101,110,100, 10, 10, 10, 45, 45, 32, 80,114,105, + 110,116, 32,109,101,116,104,111,100, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 86,101,114, 98, 97,116, + 105,109, 58,112,114,105,110,116, 32, 40,105,100,101,110,116, + 44, 99,108,111,115,101, 41, 10, 32,112,114,105,110,116, 40, + 105,100,101,110,116, 46, 46, 34, 86,101,114, 98, 97,116,105, + 109,123, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 32,108,105,110,101, 32, 61, 32, 39, 34, + 46, 46,115,101,108,102, 46,108,105,110,101, 46, 46, 34, 39, + 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110, + 116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10, + 101,110,100, 10, 10, 10, 45, 45, 32, 73,110,116,101,114,110, + 97,108, 32, 99,111,110,115,116,114,117, 99,116,111,114, 10, + 102,117,110, 99,116,105,111,110, 32, 95, 86,101,114, 98, 97, + 116,105,109, 32, 40,116, 41, 10, 32,115,101,116,109,101,116, + 97,116, 97, 98,108,101, 40,116, 44, 99,108, 97,115,115, 86, + 101,114, 98, 97,116,105,109, 41, 10, 32, 97,112,112,101,110, + 100, 40,116, 41, 10, 32,114,101,116,117,114,110, 32,116, 10, + 101,110,100, 10, 10, 45, 45, 32, 67,111,110,115,116,114,117, + 99,116,111,114, 10, 45, 45, 32, 69,120,112,101, 99,116,115, + 32, 97, 32,115,116,114,105,110,103, 32,114,101,112,114,101, + 115,101,110,116,105,110,103, 32,116,104,101, 32,116,101,120, + 116, 32,108,105,110,101, 10,102,117,110, 99,116,105,111,110, + 32, 86,101,114, 98, 97,116,105,109, 32, 40,108, 44, 99,111, + 110,100, 41, 10, 32,105,102, 32,115,116,114,115,117, 98, 40, + 108, 44, 49, 44, 49, 41, 32, 61, 61, 32, 34, 39, 34, 32,116, + 104,101,110, 10, 32, 32,108, 32, 61, 32,115,116,114,115,117, + 98, 40,108, 44, 50, 41, 10, 32,101,108,115,101,105,102, 32, + 115,116,114,115,117, 98, 40,108, 44, 49, 44, 49, 41, 32, 61, + 61, 32, 39, 36, 39, 32,116,104,101,110, 10, 32, 32, 99,111, + 110,100, 32, 61, 32, 39,115,114, 39, 32, 32, 32, 32, 32, 32, + 32, 45, 45, 32,103,101,110,101,114, 97,116,101,115, 32,105, + 110, 32, 98,111,116,104, 32,115,117,112,111,114,116, 32, 97, + 110,100, 32,114,101,103,105,115,116,101,114, 32,102,114, 97, + 103,109,101,110,116,115, 10, 32, 32,108, 32, 61, 32,115,116, + 114,115,117, 98, 40,108, 44, 50, 41, 10, 32,101,110,100, 10, + 32,114,101,116,117,114,110, 32, 95, 86,101,114, 98, 97,116, + 105,109, 32,123, 10, 32, 32,108,105,110,101, 32, 61, 32,108, + 44, 10, 32, 32, 99,111,110,100, 32, 61, 32, 99,111,110,100, + 32,111,114, 32, 39, 39, 44, 10, 32,125, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/verbatim.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32, 99,111,100,101, 32, + 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105,116,116,101, + 110, 32, 98,121, 32, 87, 97,108,100,101,109, 97,114, 32, 67, + 101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71,114, 97,102, + 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74,117,108, + 32, 49, 57, 57, 57, 10, 45, 45, 32, 36, 73,100, 58, 32, 36, + 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111,100,101, 32, + 105,115, 32,102,114,101,101, 32,115,111,102,116,119, 97,114, + 101, 59, 32,121,111,117, 32, 99, 97,110, 32,114,101,100,105, + 115,116,114,105, 98,117,116,101, 32,105,116, 32, 97,110,100, + 47,111,114, 32,109,111,100,105,102,121, 32,105,116, 46, 10, + 45, 45, 32, 84,104,101, 32,115,111,102,116,119, 97,114,101, + 32,112,114,111,118,105,100,101,100, 32,104,101,114,101,117, + 110,100,101,114, 32,105,115, 32,111,110, 32, 97,110, 32, 34, + 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, 44, 32, 97, + 110,100, 10, 45, 45, 32,116,104,101, 32, 97,117,116,104,111, + 114, 32,104, 97,115, 32,110,111, 32,111, 98,108,105,103, 97, + 116,105,111,110, 32,116,111, 32,112,114,111,118,105,100,101, + 32,109, 97,105,110,116,101,110, 97,110, 99,101, 44, 32,115, + 117,112,112,111,114,116, 44, 32,117,112,100, 97,116,101,115, + 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101,109,101,110, + 116,115, 44, 32,111,114, 32,109,111,100,105,102,105, 99, 97, + 116,105,111,110,115, 46, 10, 10, 45, 45, 32,103,108,111, 98, + 97,108, 10, 99,111,100,101, 95,110, 32, 61, 32, 49, 10, 10, + 45, 45, 32, 67,111,100,101, 32, 99,108, 97,115,115, 10, 45, + 45, 32, 82,101,112,114,101,115,101,110,116,115, 32, 76,117, + 97, 32, 99,111,100,101, 32,116,111, 32, 98,101, 32, 99,111, + 109,112,105,108,101,100, 32, 97,110,100, 32,105,110, 99,108, + 117,100,101,100, 10, 45, 45, 32,105,110, 32,116,104,101, 32, + 105,110,105,116,105, 97,108,105,122, 97,116,105,111,110, 32, + 102,117,110, 99,116,105,111,110, 46, 10, 45, 45, 32, 84,104, + 101, 32,102,111,108,108,111,119,105,110,103, 32,102,105,101, + 108,100,115, 32, 97,114,101, 32,115,116,111,114,101,100, 58, + 10, 45, 45, 32, 32, 32,116,101,120,116, 32, 61, 32,116,101, + 120,116, 32, 99,111,100,101, 10, 99,108, 97,115,115, 67,111, + 100,101, 32, 61, 32,123, 10, 32,116,101,120,116, 32, 61, 32, + 39, 39, 44, 10,125, 10, 99,108, 97,115,115, 67,111,100,101, + 46, 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97,115, + 115, 67,111,100,101, 10,115,101,116,109,101,116, 97,116, 97, + 98,108,101, 40, 99,108, 97,115,115, 67,111,100,101, 44, 99, + 108, 97,115,115, 70,101, 97,116,117,114,101, 41, 10, 10, 45, + 45, 32,114,101,103,105,115,116,101,114, 32, 99,111,100,101, + 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, + 67,111,100,101, 58,114,101,103,105,115,116,101,114, 32, 40, + 112,114,101, 41, 10, 32,112,114,101, 32, 61, 32,112,114,101, + 32,111,114, 32, 39, 39, 10, 32, 45, 45, 32, 99,108,101, 97, + 110, 32, 76,117, 97, 32, 99,111,100,101, 10, 32,108,111, 99, + 97,108, 32,115, 32, 61, 32, 99,108,101, 97,110, 40,115,101, + 108,102, 46,116,101,120,116, 41, 10, 32,105,102, 32,110,111, + 116, 32,115, 32,116,104,101,110, 10, 32, 32, 45, 45,112,114, + 105,110,116, 40,115,101,108,102, 46,116,101,120,116, 41, 10, + 32, 32,101,114,114,111,114, 40, 34,112, 97,114,115,101,114, + 32,101,114,114,111,114, 32,105,110, 32,101,109, 98,101,100, + 100,101,100, 32, 99,111,100,101, 34, 41, 10, 32,101,110,100, + 10, 10, 32, 45, 45, 32,103,101,116, 32,102,105,114,115,116, + 32,108,105,110,101, 10, 32,108,111, 99, 97,108, 32, 95, 44, + 32, 95, 44, 32,102,105,114,115,116, 95,108,105,110,101, 61, + 115,116,114,105,110,103, 46,102,105,110,100, 40,115,101,108, + 102, 46,116,101,120,116, 44, 32, 34, 94, 40, 91, 94, 92,110, + 92,114, 93, 42, 41, 34, 41, 10, 32,105,102, 32,115,116,114, + 105,110,103, 46,102,105,110,100, 40,102,105,114,115,116, 95, + 108,105,110,101, 44, 32, 34, 94, 37,115, 42, 37, 45, 37, 45, + 34, 41, 32,116,104,101,110, 10, 9, 32,105,102, 32,115,116, + 114,105,110,103, 46,102,105,110,100, 40,102,105,114,115,116, + 95,108,105,110,101, 44, 32, 34, 94, 37, 45, 37, 45, 35, 35, + 34, 41, 32,116,104,101,110, 10, 9, 9,102,105,114,115,116, + 95,108,105,110,101, 32, 61, 32,115,116,114,105,110,103, 46, + 103,115,117, 98, 40,102,105,114,115,116, 95,108,105,110,101, + 44, 32, 34, 94, 37, 45, 37, 45, 35, 35, 34, 44, 32, 34, 34, + 41, 10, 9, 9,105,102, 32,102,108, 97,103,115, 91, 39, 67, + 39, 93, 32,116,104,101,110, 10, 9, 9, 9,115, 32, 61, 32, + 115,116,114,105,110,103, 46,103,115,117, 98, 40,115, 44, 32, + 34, 94, 37, 45, 37, 45, 35, 35, 91, 94, 92,110, 92,114, 93, + 42, 92,110, 34, 44, 32, 34, 34, 41, 10, 9, 9,101,110,100, + 10, 9, 32,101,110,100, 10, 32,101,108,115,101, 10, 32, 9, + 102,105,114,115,116, 95,108,105,110,101, 32, 61, 32, 34, 34, + 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, 99,111,110,118, + 101,114,116, 32,116,111, 32, 67, 10, 32,111,117,116,112,117, + 116, 40, 39, 92,110, 39, 46, 46,112,114,101, 46, 46, 39,123, + 32, 47, 42, 32, 98,101,103,105,110, 32,101,109, 98,101,100, + 100,101,100, 32,108,117, 97, 32, 99,111,100,101, 32, 42, 47, + 92,110, 39, 41, 10, 32,111,117,116,112,117,116, 40,112,114, + 101, 46, 46, 39, 32,105,110,116, 32,116,111,112, 32, 61, 32, + 108,117, 97, 95,103,101,116,116,111,112, 40,116,111,108,117, + 97, 95, 83, 41, 59, 39, 41, 10, 32,111,117,116,112,117,116, + 40,112,114,101, 46, 46, 39, 32,115,116, 97,116,105, 99, 32, + 117,110,115,105,103,110,101,100, 32, 99,104, 97,114, 32, 66, + 91, 93, 32, 61, 32,123, 92,110, 32, 32, 32, 39, 41, 10, 32, + 108,111, 99, 97,108, 32,116, 61,123,110, 61, 48,125, 10, 32, + 108,111, 99, 97,108, 32, 98, 32, 61, 32,103,115,117, 98, 40, + 115, 44, 39, 40, 46, 41, 39, 44,102,117,110, 99,116,105,111, + 110, 32, 40, 99, 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,108,111, 99, 97,108, 32,101, 32, 61, 32, 39, 39, 10, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32,116, 46,110, 61,116, 46, + 110, 43, 49, 32,105,102, 32,116, 46,110, 61, 61, 49, 53, 32, + 116,104,101,110, 32,116, 46,110, 61, 48, 32,101, 61, 39, 92, + 110, 39, 46, 46,112,114,101, 46, 46, 39, 32, 32, 39, 32,101, + 110,100, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,114,101, + 116,117,114,110, 32,102,111,114,109, 97,116, 40, 39, 37, 51, + 117, 44, 37,115, 39, 44,115,116,114, 98,121,116,101, 40, 99, + 41, 44,101, 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,101, + 110,100, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 41, 10, 32,111,117,116,112,117,116, 40, 98, 46, + 46,115,116,114, 98,121,116,101, 40, 34, 32, 34, 41, 41, 10, + 32,111,117,116,112,117,116, 40, 39, 92,110, 39, 46, 46,112, + 114,101, 46, 46, 39, 32,125, 59, 92,110, 39, 41, 10, 32,105, + 102, 32,102,105,114,115,116, 95,108,105,110,101, 32, 97,110, + 100, 32,102,105,114,115,116, 95,108,105,110,101, 32,126, 61, + 32, 34, 34, 32,116,104,101,110, 10, 32, 9,111,117,116,112, + 117,116, 40,112,114,101, 46, 46, 39, 32,116,111,108,117, 97, + 95,100,111, 98,117,102,102,101,114, 40,116,111,108,117, 97, + 95, 83, 44, 40, 99,104, 97,114, 42, 41, 66, 44,115,105,122, + 101,111,102, 40, 66, 41, 44, 34,116,111,108,117, 97, 32,101, + 109, 98,101,100,100,101,100, 58, 32, 39, 46, 46,102,105,114, + 115,116, 95,108,105,110,101, 46, 46, 39, 34, 41, 59, 39, 41, + 10, 32,101,108,115,101, 10, 32, 9,111,117,116,112,117,116, + 40,112,114,101, 46, 46, 39, 32,116,111,108,117, 97, 95,100, + 111, 98,117,102,102,101,114, 40,116,111,108,117, 97, 95, 83, + 44, 40, 99,104, 97,114, 42, 41, 66, 44,115,105,122,101,111, + 102, 40, 66, 41, 44, 34,116,111,108,117, 97, 58, 32,101,109, + 98,101,100,100,101,100, 32, 76,117, 97, 32, 99,111,100,101, + 32, 39, 46, 46, 99,111,100,101, 95,110, 46, 46, 39, 34, 41, + 59, 39, 41, 10, 32,101,110,100, 10, 32,111,117,116,112,117, + 116, 40,112,114,101, 46, 46, 39, 32,108,117, 97, 95,115,101, + 116,116,111,112, 40,116,111,108,117, 97, 95, 83, 44, 32,116, + 111,112, 41, 59, 39, 41, 10, 32,111,117,116,112,117,116, 40, + 112,114,101, 46, 46, 39,125, 32, 47, 42, 32,101,110,100, 32, + 111,102, 32,101,109, 98,101,100,100,101,100, 32,108,117, 97, + 32, 99,111,100,101, 32, 42, 47, 92,110, 92,110, 39, 41, 10, + 32, 99,111,100,101, 95,110, 32, 61, 32, 99,111,100,101, 95, + 110, 32, 43, 49, 10,101,110,100, 10, 10, 10, 45, 45, 32, 80, + 114,105,110,116, 32,109,101,116,104,111,100, 10,102,117,110, + 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111,100,101, + 58,112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99, + 108,111,115,101, 41, 10, 32,112,114,105,110,116, 40,105,100, + 101,110,116, 46, 46, 34, 67,111,100,101,123, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 116,101,120,116, 32, 61, 32, 91, 91, 34, 46, 46,115,101,108, + 102, 46,116,101,120,116, 46, 46, 34, 93, 93, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, 10, + 10, 10, 45, 45, 32, 73,110,116,101,114,110, 97,108, 32, 99, + 111,110,115,116,114,117, 99,116,111,114, 10,102,117,110, 99, + 116,105,111,110, 32, 95, 67,111,100,101, 32, 40,116, 41, 10, + 32,115,101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, + 44, 99,108, 97,115,115, 67,111,100,101, 41, 10, 32, 97,112, + 112,101,110,100, 40,116, 41, 10, 32,114,101,116,117,114,110, + 32,116, 10,101,110,100, 10, 10, 45, 45, 32, 67,111,110,115, + 116,114,117, 99,116,111,114, 10, 45, 45, 32, 69,120,112,101, + 99,116,115, 32, 97, 32,115,116,114,105,110,103, 32,114,101, + 112,114,101,115,101,110,116,105,110,103, 32,116,104,101, 32, + 99,111,100,101, 32,116,101,120,116, 10,102,117,110, 99,116, + 105,111,110, 32, 67,111,100,101, 32, 40,108, 41, 10, 32,114, + 101,116,117,114,110, 32, 95, 67,111,100,101, 32,123, 10, 32, + 32,116,101,120,116, 32, 61, 32,108, 10, 32,125, 10,101,110, + 100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/code.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,116,121,112,101,100, + 101,102, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105, + 116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, 97, + 114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71, + 114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, + 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73,100, + 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111, + 100,101, 32,105,115, 32,102,114,101,101, 32,115,111,102,116, + 119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32,114, + 101,100,105,115,116,114,105, 98,117,116,101, 32,105,116, 32, + 97,110,100, 47,111,114, 32,109,111,100,105,102,121, 32,105, + 116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116,119, + 97,114,101, 32,112,114,111,118,105,100,101,100, 32,104,101, + 114,101,117,110,100,101,114, 32,105,115, 32,111,110, 32, 97, + 110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, + 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97,117, + 116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98,108, + 105,103, 97,116,105,111,110, 32,116,111, 32,112,114,111,118, + 105,100,101, 32,109, 97,105,110,116,101,110, 97,110, 99,101, + 44, 32,115,117,112,112,111,114,116, 44, 32,117,112,100, 97, + 116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101, + 109,101,110,116,115, 44, 32,111,114, 32,109,111,100,105,102, + 105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 10, 45, 45, + 32, 84,121,112,101,100,101,102, 32, 99,108, 97,115,115, 10, + 45, 45, 32, 82,101,112,114,101,115,101,110,116,115, 32, 97, + 32,116,121,112,101, 32,115,121,110,111,110,121,109, 46, 10, + 45, 45, 32, 84,104,101, 32, 39,100,101, 32,102, 97, 99,116, + 111, 39, 32,116,121,112,101, 32,114,101,112,108, 97, 99,101, + 115, 32,116,104,101, 32,116,121,112,101,100,101,102, 32, 98, + 101,102,111,114,101, 32,116,104,101, 10, 45, 45, 32,114,101, + 109, 97,105,110,105,110,103, 32, 99,111,100,101, 32,105,115, + 32,112, 97,114,115,101,100, 46, 10, 45, 45, 32, 84,104,101, + 32,102,111,108,108,111,119,105,110,103, 32,102,105,101,108, + 100,115, 32, 97,114,101, 32,115,116,111,114,101,100, 58, 10, + 45, 45, 32, 32, 32,117,116,121,112,101, 32, 61, 32,116,121, + 112,101,100,101,102, 32,110, 97,109,101, 10, 45, 45, 32, 32, + 32,116,121,112,101, 32, 61, 32, 39,116,104,101, 32,102, 97, + 99,116,111, 39, 32,116,121,112,101, 10, 45, 45, 32, 32, 32, + 109,111,100, 32, 61, 32,109,111,100,105,102,105,101,114,115, + 32,116,111, 32,116,104,101, 32, 39,100,101, 32,102, 97, 99, + 116,111, 39, 32,116,121,112,101, 10, 99,108, 97,115,115, 84, + 121,112,101,100,101,102, 32, 61, 32,123, 10, 32,117,116,121, + 112,101, 32, 61, 32, 39, 39, 44, 10, 32,109,111,100, 32, 61, + 32, 39, 39, 44, 10, 32,116,121,112,101, 32, 61, 32, 39, 39, + 10,125, 10, 99,108, 97,115,115, 84,121,112,101,100,101,102, + 46, 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97,115, + 115, 84,121,112,101,100,101,102, 10, 10, 45, 45, 32, 80,114, + 105,110,116, 32,109,101,116,104,111,100, 10,102,117,110, 99, + 116,105,111,110, 32, 99,108, 97,115,115, 84,121,112,101,100, + 101,102, 58,112,114,105,110,116, 32, 40,105,100,101,110,116, + 44, 99,108,111,115,101, 41, 10, 32,112,114,105,110,116, 40, + 105,100,101,110,116, 46, 46, 34, 84,121,112,101,100,101,102, + 123, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110, + 116, 46, 46, 34, 32,117,116,121,112,101, 32, 61, 32, 39, 34, + 46, 46,115,101,108,102, 46,117,116,121,112,101, 46, 46, 34, + 39, 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 32,109,111,100, 32, 61, 32, 39, 34, 46, + 46,115,101,108,102, 46,109,111,100, 46, 46, 34, 39, 44, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115, + 101,108,102, 46,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, + 10, 10, 45, 45, 32, 82,101,116,117,114,110, 32,105,116, 39, + 115, 32,110,111,116, 32, 97, 32,118, 97,114,105, 97, 98,108, + 101, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 84,121,112,101,100,101,102, 58,105,115,118, 97,114,105, + 97, 98,108,101, 32, 40, 41, 10, 32,114,101,116,117,114,110, + 32,102, 97,108,115,101, 10,101,110,100, 10, 10, 45, 45, 32, + 73,110,116,101,114,110, 97,108, 32, 99,111,110,115,116,114, + 117, 99,116,111,114, 10,102,117,110, 99,116,105,111,110, 32, + 95, 84,121,112,101,100,101,102, 32, 40,116, 41, 10, 32,115, + 101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, 44, 99, + 108, 97,115,115, 84,121,112,101,100,101,102, 41, 10, 32,116, + 46,116,121,112,101, 32, 61, 32,114,101,115,111,108,118,101, + 95,116,101,109,112,108, 97,116,101, 95,116,121,112,101,115, + 40,116, 46,116,121,112,101, 41, 10, 32, 97,112,112,101,110, + 100,116,121,112,101,100,101,102, 40,116, 41, 10, 32,114,101, + 116,117,114,110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, + 67,111,110,115,116,114,117, 99,116,111,114, 10, 45, 45, 32, + 69,120,112,101, 99,116,115, 32,111,110,101, 32,115,116,114, + 105,110,103, 32,114,101,112,114,101,115,101,110,116,105,110, + 103, 32,116,104,101, 32,116,121,112,101, 32,100,101,102,105, + 110,105,116,105,111,110, 46, 10,102,117,110, 99,116,105,111, + 110, 32, 84,121,112,101,100,101,102, 32, 40,115, 41, 10, 32, + 105,102, 32,115,116,114,102,105,110,100, 40,115,116,114,105, + 110,103, 46,103,115,117, 98, 40,115, 44, 32, 39, 37, 98, 60, + 62, 39, 44, 32, 39, 39, 41, 44, 39, 91, 37, 42, 38, 93, 39, + 41, 32,116,104,101,110, 10, 32, 32,116,111,108,117, 97, 95, + 101,114,114,111,114, 40, 34, 35,105,110,118, 97,108,105,100, + 32,116,121,112,101,100,101,102, 58, 32,112,111,105,110,116, + 101,114,115, 32, 40, 97,110,100, 32,114,101,102,101,114,101, + 110, 99,101,115, 41, 32, 97,114,101, 32,110,111,116, 32,115, + 117,112,112,111,114,116,101,100, 34, 41, 10, 32,101,110,100, + 10, 32,108,111, 99, 97,108, 32,111, 32, 61, 32,123,109,111, + 100, 32, 61, 32, 39, 39,125, 10, 32,105,102, 32,115,116,114, + 105,110,103, 46,102,105,110,100, 40,115, 44, 32, 34, 91, 60, + 62, 93, 34, 41, 32,116,104,101,110, 10, 32, 9, 95, 44, 95, + 44,111, 46,116,121,112,101, 44,111, 46,117,116,121,112,101, + 32, 61, 32,115,116,114,105,110,103, 46,102,105,110,100, 40, + 115, 44, 32, 34, 94, 37,115, 42, 40, 91, 94, 60, 62, 93, 43, + 37, 98, 60, 62, 91, 94, 37,115, 93, 42, 41, 37,115, 43, 40, + 46, 45, 41, 36, 34, 41, 10, 32,101,108,115,101, 10, 32, 9, + 108,111, 99, 97,108, 32,116, 32, 61, 32,115,112,108,105,116, + 40,103,115,117, 98, 40,115, 44, 34, 37,115, 37,115, 42, 34, + 44, 34, 32, 34, 41, 44, 34, 32, 34, 41, 10, 32, 9,111, 32, + 61, 32,123, 10, 9, 32, 32,117,116,121,112,101, 32, 61, 32, + 116, 91,116, 46,110, 93, 44, 10, 9, 32, 32,116,121,112,101, + 32, 61, 32,116, 91,116, 46,110, 45, 49, 93, 44, 10, 9, 32, + 32,109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, 40,116, + 44, 49, 44,116, 46,110, 45, 50, 41, 44, 10, 9, 32,125, 10, + 32,101,110,100, 10, 32,114,101,116,117,114,110, 32, 95, 84, + 121,112,101,100,101,102, 40,111, 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/typedef.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32, 99,111,110,116, 97, + 105,110,101,114, 32, 97, 98,115,116,114, 97, 99,116, 32, 99, + 108, 97,115,115, 10, 45, 45, 32, 87,114,105,116,116,101,110, + 32, 98,121, 32, 87, 97,108,100,101,109, 97,114, 32, 67,101, + 108,101,115, 10, 45, 45, 32, 84,101, 67, 71,114, 97,102, 47, + 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74,117,108, 32, + 49, 57, 57, 56, 10, 45, 45, 32, 36, 73,100, 58, 32, 36, 10, + 10, 45, 45, 32, 84,104,105,115, 32, 99,111,100,101, 32,105, + 115, 32,102,114,101,101, 32,115,111,102,116,119, 97,114,101, + 59, 32,121,111,117, 32, 99, 97,110, 32,114,101,100,105,115, + 116,114,105, 98,117,116,101, 32,105,116, 32, 97,110,100, 47, + 111,114, 32,109,111,100,105,102,121, 32,105,116, 46, 10, 45, + 45, 32, 84,104,101, 32,115,111,102,116,119, 97,114,101, 32, + 112,114,111,118,105,100,101,100, 32,104,101,114,101,117,110, + 100,101,114, 32,105,115, 32,111,110, 32, 97,110, 32, 34, 97, + 115, 32,105,115, 34, 32, 98, 97,115,105,115, 44, 32, 97,110, + 100, 10, 45, 45, 32,116,104,101, 32, 97,117,116,104,111,114, + 32,104, 97,115, 32,110,111, 32,111, 98,108,105,103, 97,116, + 105,111,110, 32,116,111, 32,112,114,111,118,105,100,101, 32, + 109, 97,105,110,116,101,110, 97,110, 99,101, 44, 32,115,117, + 112,112,111,114,116, 44, 32,117,112,100, 97,116,101,115, 44, + 10, 45, 45, 32,101,110,104, 97,110, 99,101,109,101,110,116, + 115, 44, 32,111,114, 32,109,111,100,105,102,105, 99, 97,116, + 105,111,110,115, 46, 10, 10, 45, 45, 32,116, 97, 98,108,101, + 32,116,111, 32,115,116,111,114,101, 32,110, 97,109,101,115, + 112, 97, 99,101,100, 32,116,121,112,101,100,101,102,115, 47, + 101,110,117,109,115, 32,105,110, 32,103,108,111, 98, 97,108, + 32,115, 99,111,112,101, 10,103,108,111, 98, 97,108, 95,116, + 121,112,101,100,101,102,115, 32, 61, 32,123,125, 10,103,108, + 111, 98, 97,108, 95,101,110,117,109,115, 32, 61, 32,123,125, + 10, 10, 45, 45, 32, 67,111,110,116, 97,105,110,101,114, 32, + 99,108, 97,115,115, 10, 45, 45, 32, 82,101,112,114,101,115, + 101,110,116,115, 32, 97, 32, 99,111,110,116, 97,105,110,101, + 114, 32,111,102, 32,102,101, 97,116,117,114,101,115, 32,116, + 111, 32, 98,101, 32, 98,111,117,110,100, 10, 45, 45, 32,116, + 111, 32,108,117, 97, 46, 10, 99,108, 97,115,115, 67,111,110, + 116, 97,105,110,101,114, 32, 61, 10,123, 10, 32, 99,117,114, + 114, 32, 61, 32,110,105,108, 44, 10,125, 10, 99,108, 97,115, + 115, 67,111,110,116, 97,105,110,101,114, 46, 95, 95,105,110, + 100,101,120, 32, 61, 32, 99,108, 97,115,115, 67,111,110,116, + 97,105,110,101,114, 10,115,101,116,109,101,116, 97,116, 97, + 98,108,101, 40, 99,108, 97,115,115, 67,111,110,116, 97,105, + 110,101,114, 44, 99,108, 97,115,115, 70,101, 97,116,117,114, + 101, 41, 10, 10, 45, 45, 32,111,117,116,112,117,116, 32,116, + 97,103,115, 10,102,117,110, 99,116,105,111,110, 32, 99,108, + 97,115,115, 67,111,110,116, 97,105,110,101,114, 58,100,101, + 99,108,116,121,112,101, 32, 40, 41, 10, 32,112,117,115,104, + 40,115,101,108,102, 41, 10, 32,108,111, 99, 97,108, 32,105, + 61, 49, 10, 32,119,104,105,108,101, 32,115,101,108,102, 91, + 105, 93, 32,100,111, 10, 32, 32,115,101,108,102, 91,105, 93, + 58,100,101, 99,108,116,121,112,101, 40, 41, 10, 32, 32,105, + 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 32,112,111, + 112, 40, 41, 10,101,110,100, 10, 10, 10, 45, 45, 32,119,114, + 105,116,101, 32,115,117,112,112,111,114,116, 32, 99,111,100, + 101, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 67,111,110,116, 97,105,110,101,114, 58,115,117,112, 99, + 111,100,101, 32, 40, 41, 10, 10, 9,105,102, 32,110,111,116, + 32,115,101,108,102, 58, 99,104,101, 99,107, 95,112,117, 98, + 108,105, 99, 95, 97, 99, 99,101,115,115, 40, 41, 32,116,104, + 101,110, 10, 9, 9,114,101,116,117,114,110, 10, 9,101,110, + 100, 10, 10, 32,112,117,115,104, 40,115,101,108,102, 41, 10, + 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104,105, + 108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10, 32, + 32,105,102, 32,115,101,108,102, 91,105, 93, 58, 99,104,101, + 99,107, 95,112,117, 98,108,105, 99, 95, 97, 99, 99,101,115, + 115, 40, 41, 32,116,104,101,110, 10, 32, 32, 9,115,101,108, + 102, 91,105, 93, 58,115,117,112, 99,111,100,101, 40, 41, 10, + 32, 32,101,110,100, 10, 32, 32,105, 32, 61, 32,105, 43, 49, + 10, 32,101,110,100, 10, 32,112,111,112, 40, 41, 10,101,110, + 100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 67,111,110,116, 97,105,110,101,114, 58,104, 97,115, + 118, 97,114, 32, 40, 41, 10, 32,108,111, 99, 97,108, 32,105, + 61, 49, 10, 32,119,104,105,108,101, 32,115,101,108,102, 91, + 105, 93, 32,100,111, 10, 32, 32,105,102, 32,115,101,108,102, + 91,105, 93, 58,105,115,118, 97,114,105, 97, 98,108,101, 40, + 41, 32,116,104,101,110, 10, 9, 9, 32,114,101,116,117,114, + 110, 32, 49, 10, 9, 9,101,110,100, 10, 32, 32,105, 32, 61, + 32,105, 43, 49, 10, 32,101,110,100, 10, 9,114,101,116,117, + 114,110, 32, 48, 10,101,110,100, 10, 10, 45, 45, 32, 73,110, + 116,101,114,110, 97,108, 32, 99,111,110,116, 97,105,110,101, + 114, 32, 99,111,110,115,116,114,117, 99,116,111,114, 10,102, + 117,110, 99,116,105,111,110, 32, 95, 67,111,110,116, 97,105, + 110,101,114, 32, 40,115,101,108,102, 41, 10, 32,115,101,116, + 109,101,116, 97,116, 97, 98,108,101, 40,115,101,108,102, 44, + 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 41, + 10, 32,115,101,108,102, 46,110, 32, 61, 32, 48, 10, 32,115, + 101,108,102, 46,116,121,112,101,100,101,102,115, 32, 61, 32, + 123,116,111,108,117, 97, 95,110, 61, 48,125, 10, 32,115,101, + 108,102, 46,117,115,101,114,116,121,112,101,115, 32, 61, 32, + 123,125, 10, 32,115,101,108,102, 46,101,110,117,109,115, 32, + 61, 32,123,116,111,108,117, 97, 95,110, 61, 48,125, 10, 32, + 115,101,108,102, 46,108,110, 97,109,101,115, 32, 61, 32,123, + 125, 10, 32,114,101,116,117,114,110, 32,115,101,108,102, 10, + 101,110,100, 10, 10, 45, 45, 32,112,117,115,104, 32, 99,111, + 110,116, 97,105,110,101,114, 10,102,117,110, 99,116,105,111, + 110, 32,112,117,115,104, 32, 40,116, 41, 10, 9,116, 46,112, + 114,111,120, 32, 61, 32, 99,108, 97,115,115, 67,111,110,116, + 97,105,110,101,114, 46, 99,117,114,114, 10, 32, 99,108, 97, + 115,115, 67,111,110,116, 97,105,110,101,114, 46, 99,117,114, + 114, 32, 61, 32,116, 10,101,110,100, 10, 10, 45, 45, 32,112, + 111,112, 32, 99,111,110,116, 97,105,110,101,114, 10,102,117, + 110, 99,116,105,111,110, 32,112,111,112, 32, 40, 41, 10, 45, + 45,112,114,105,110,116, 40, 34,110, 97,109,101, 34, 44, 99, + 108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 46, 99, + 117,114,114, 46,110, 97,109,101, 41, 10, 45, 45,102,111,114, + 101, 97, 99,104, 40, 99,108, 97,115,115, 67,111,110,116, 97, + 105,110,101,114, 46, 99,117,114,114, 46,117,115,101,114,116, + 121,112,101,115, 44,112,114,105,110,116, 41, 10, 45, 45,112, + 114,105,110,116, 40, 34, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 34, 41, 10, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 32, 61, + 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, + 46, 99,117,114,114, 46,112,114,111,120, 10,101,110,100, 10, + 10, 45, 45, 32,103,101,116, 32, 99,117,114,114,101,110,116, + 32,110, 97,109,101,115,112, 97, 99,101, 10,102,117,110, 99, + 116,105,111,110, 32,103,101,116, 99,117,114,114,110, 97,109, + 101,115,112, 97, 99,101, 32, 40, 41, 10, 9,114,101,116,117, + 114,110, 32,103,101,116,110, 97,109,101,115,112, 97, 99,101, + 40, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, + 46, 99,117,114,114, 41, 10,101,110,100, 10, 10, 45, 45, 32, + 97,112,112,101,110,100, 32,116,111, 32, 99,117,114,114,101, + 110,116, 32, 99,111,110,116, 97,105,110,101,114, 10,102,117, + 110, 99,116,105,111,110, 32, 97,112,112,101,110,100, 32, 40, + 116, 41, 10, 32,114,101,116,117,114,110, 32, 99,108, 97,115, + 115, 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, + 58, 97,112,112,101,110,100, 40,116, 41, 10,101,110,100, 10, + 10, 45, 45, 32, 97,112,112,101,110,100, 32,116,121,112,101, + 100,101,102, 32,116,111, 32, 99,117,114,114,101,110,116, 32, + 99,111,110,116, 97,105,110,101,114, 10,102,117,110, 99,116, + 105,111,110, 32, 97,112,112,101,110,100,116,121,112,101,100, + 101,102, 32, 40,116, 41, 10, 32,114,101,116,117,114,110, 32, + 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 46, + 99,117,114,114, 58, 97,112,112,101,110,100,116,121,112,101, + 100,101,102, 40,116, 41, 10,101,110,100, 10, 10, 45, 45, 32, + 97,112,112,101,110,100, 32,117,115,101,114,116,121,112,101, + 32,116,111, 32, 99,117,114,114,101,110,116, 32, 99,111,110, + 116, 97,105,110,101,114, 10,102,117,110, 99,116,105,111,110, + 32, 97,112,112,101,110,100,117,115,101,114,116,121,112,101, + 32, 40,116, 41, 10, 32,114,101,116,117,114,110, 32, 99,108, + 97,115,115, 67,111,110,116, 97,105,110,101,114, 46, 99,117, + 114,114, 58, 97,112,112,101,110,100,117,115,101,114,116,121, + 112,101, 40,116, 41, 10,101,110,100, 10, 10, 45, 45, 32, 97, + 112,112,101,110,100, 32,101,110,117,109, 32,116,111, 32, 99, + 117,114,114,101,110,116, 32, 99,111,110,116, 97,105,110,101, + 114, 10,102,117,110, 99,116,105,111,110, 32, 97,112,112,101, + 110,100,101,110,117,109, 32, 40,116, 41, 10, 32,114,101,116, + 117,114,110, 32, 99,108, 97,115,115, 67,111,110,116, 97,105, + 110,101,114, 46, 99,117,114,114, 58, 97,112,112,101,110,100, + 101,110,117,109, 40,116, 41, 10,101,110,100, 10, 10, 45, 45, + 32,115,117, 98,115,116,105,116,117,116,101, 32,116,121,112, + 101,100,101,102, 10,102,117,110, 99,116,105,111,110, 32, 97, + 112,112,108,121,116,121,112,101,100,101,102, 32, 40,109,111, + 100, 44,116,121,112,101, 41, 10, 32,114,101,116,117,114,110, + 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, + 46, 99,117,114,114, 58, 97,112,112,108,121,116,121,112,101, + 100,101,102, 40,109,111,100, 44,116,121,112,101, 41, 10,101, + 110,100, 10, 10, 45, 45, 32, 99,104,101, 99,107, 32,105,102, + 32,105,115, 32,116,121,112,101, 10,102,117,110, 99,116,105, + 111,110, 32,102,105,110,100,116,121,112,101, 32, 40,116,121, + 112,101, 41, 10, 32,108,111, 99, 97,108, 32,116, 32, 61, 32, + 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 46, + 99,117,114,114, 58,102,105,110,100,116,121,112,101, 40,116, + 121,112,101, 41, 10, 9,114,101,116,117,114,110, 32,116, 10, + 101,110,100, 10, 10, 45, 45, 32, 99,104,101, 99,107, 32,105, + 102, 32,105,115, 32,116,121,112,101,100,101,102, 10,102,117, + 110, 99,116,105,111,110, 32,105,115,116,121,112,101,100,101, + 102, 32, 40,116,121,112,101, 41, 10, 32,114,101,116,117,114, + 110, 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101, + 114, 46, 99,117,114,114, 58,105,115,116,121,112,101,100,101, + 102, 40,116,121,112,101, 41, 10,101,110,100, 10, 10, 45, 45, + 32,103,101,116, 32,102,117,108,108,116,121,112,101, 32, 40, + 119,105,116,104, 32,110, 97,109,101,115,112, 97, 99,101, 41, + 10,102,117,110, 99,116,105,111,110, 32,102,117,108,108,116, + 121,112,101, 32, 40,116, 41, 10, 32,108,111, 99, 97,108, 32, + 99,117,114,114, 32, 61, 32, 32, 99,108, 97,115,115, 67,111, + 110,116, 97,105,110,101,114, 46, 99,117,114,114, 10, 9,119, + 104,105,108,101, 32, 99,117,114,114, 32,100,111, 10, 9, 32, + 105,102, 32, 99,117,114,114, 32,116,104,101,110, 10, 9, 9, + 32,105,102, 32, 99,117,114,114, 46,116,121,112,101,100,101, + 102,115, 32, 97,110,100, 32, 99,117,114,114, 46,116,121,112, + 101,100,101,102,115, 91,116, 93, 32,116,104,101,110, 10, 9, + 9, 32, 32,114,101,116,117,114,110, 32, 99,117,114,114, 46, + 116,121,112,101,100,101,102,115, 91,116, 93, 10, 9, 9, 32, + 101,108,115,101,105,102, 32, 99,117,114,114, 46,117,115,101, + 114,116,121,112,101,115, 32, 97,110,100, 32, 99,117,114,114, + 46,117,115,101,114,116,121,112,101,115, 91,116, 93, 32,116, + 104,101,110, 10, 9, 9, 32, 32,114,101,116,117,114,110, 32, + 99,117,114,114, 46,117,115,101,114,116,121,112,101,115, 91, + 116, 93, 10, 9, 9, 9,101,110,100, 10, 9, 9,101,110,100, + 10, 9, 32, 99,117,114,114, 32, 61, 32, 99,117,114,114, 46, + 112,114,111,120, 10, 9,101,110,100, 10, 9,114,101,116,117, + 114,110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, 99,104, + 101, 99,107,115, 32,105,102, 32,105,116, 32,114,101,113,117, + 105,114,101,115, 32, 99,111,108,108,101, 99,116,105,111,110, + 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, + 67,111,110,116, 97,105,110,101,114, 58,114,101,113,117,105, + 114,101, 99,111,108,108,101, 99,116,105,111,110, 32, 40,116, + 41, 10, 32,112,117,115,104, 40,115,101,108,102, 41, 10, 32, + 108,111, 99, 97,108, 32,105, 61, 49, 10, 9,108,111, 99, 97, + 108, 32,114, 32, 61, 32,102, 97,108,115,101, 10, 32,119,104, + 105,108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10, + 32, 32,114, 32, 61, 32,115,101,108,102, 91,105, 93, 58,114, + 101,113,117,105,114,101, 99,111,108,108,101, 99,116,105,111, + 110, 40,116, 41, 32,111,114, 32,114, 10, 32, 32,105, 32, 61, + 32,105, 43, 49, 10, 32,101,110,100, 10, 9,112,111,112, 40, + 41, 10, 9,114,101,116,117,114,110, 32,114, 10,101,110,100, + 10, 10, 10, 45, 45, 32,103,101,116, 32,110, 97,109,101,115, + 97,112, 99,101, 10,102,117,110, 99,116,105,111,110, 32,103, + 101,116,110, 97,109,101,115,112, 97, 99,101, 32, 40, 99,117, + 114,114, 41, 10, 9,108,111, 99, 97,108, 32,110, 97,109,101, + 115,112, 97, 99,101, 32, 61, 32, 39, 39, 10, 9,119,104,105, + 108,101, 32, 99,117,114,114, 32,100,111, 10, 9, 32,105,102, + 32, 99,117,114,114, 32, 97,110,100, 10, 9, 9, 32, 32, 32, + 40, 32, 99,117,114,114, 46, 99,108, 97,115,115,116,121,112, + 101, 32, 61, 61, 32, 39, 99,108, 97,115,115, 39, 32,111,114, + 32, 99,117,114,114, 46, 99,108, 97,115,115,116,121,112,101, + 32, 61, 61, 32, 39,110, 97,109,101,115,112, 97, 99,101, 39, + 41, 10, 9, 9,116,104,101,110, 10, 9, 9, 32,110, 97,109, + 101,115,112, 97, 99,101, 32, 61, 32, 40, 99,117,114,114, 46, + 111,114,105,103,105,110, 97,108, 95,110, 97,109,101, 32,111, + 114, 32, 99,117,114,114, 46,110, 97,109,101, 41, 32, 46, 46, + 32, 39, 58, 58, 39, 32, 46, 46, 32,110, 97,109,101,115,112, + 97, 99,101, 10, 9, 9, 32, 45, 45,110, 97,109,101,115,112, + 97, 99,101, 32, 61, 32, 99,117,114,114, 46,110, 97,109,101, + 32, 46, 46, 32, 39, 58, 58, 39, 32, 46, 46, 32,110, 97,109, + 101,115,112, 97, 99,101, 10, 9, 9,101,110,100, 10, 9, 32, + 99,117,114,114, 32, 61, 32, 99,117,114,114, 46,112,114,111, + 120, 10, 9,101,110,100, 10, 9,114,101,116,117,114,110, 32, + 110, 97,109,101,115,112, 97, 99,101, 10,101,110,100, 10, 10, + 45, 45, 32,103,101,116, 32,110, 97,109,101,115,112, 97, 99, + 101, 32, 40,111,110,108,121, 32,110, 97,109,101,115,112, 97, + 99,101, 41, 10,102,117,110, 99,116,105,111,110, 32,103,101, + 116,111,110,108,121,110, 97,109,101,115,112, 97, 99,101, 32, + 40, 41, 10, 32,108,111, 99, 97,108, 32, 99,117,114,114, 32, + 61, 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101, + 114, 46, 99,117,114,114, 10, 9,108,111, 99, 97,108, 32,110, + 97,109,101,115,112, 97, 99,101, 32, 61, 32, 39, 39, 10, 9, + 119,104,105,108,101, 32, 99,117,114,114, 32,100,111, 10, 9, + 9,105,102, 32, 99,117,114,114, 46, 99,108, 97,115,115,116, + 121,112,101, 32, 61, 61, 32, 39, 99,108, 97,115,115, 39, 32, + 116,104,101,110, 10, 9, 9, 32,114,101,116,117,114,110, 32, + 110, 97,109,101,115,112, 97, 99,101, 10, 9, 9,101,108,115, + 101,105,102, 32, 99,117,114,114, 46, 99,108, 97,115,115,116, + 121,112,101, 32, 61, 61, 32, 39,110, 97,109,101,115,112, 97, + 99,101, 39, 32,116,104,101,110, 10, 9, 9, 32,110, 97,109, + 101,115,112, 97, 99,101, 32, 61, 32, 99,117,114,114, 46,110, + 97,109,101, 32, 46, 46, 32, 39, 58, 58, 39, 32, 46, 46, 32, + 110, 97,109,101,115,112, 97, 99,101, 10, 9, 9,101,110,100, + 10, 9, 32, 99,117,114,114, 32, 61, 32, 99,117,114,114, 46, + 112,114,111,120, 10, 9,101,110,100, 10, 9,114,101,116,117, + 114,110, 32,110, 97,109,101,115,112, 97, 99,101, 10,101,110, + 100, 10, 10, 45, 45, 32, 99,104,101, 99,107, 32,105,102, 32, + 105,115, 32,101,110,117,109, 10,102,117,110, 99,116,105,111, + 110, 32,105,115,101,110,117,109, 32, 40,116,121,112,101, 41, + 10, 32,114,101,116,117,114,110, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 58,105, + 115,101,110,117,109, 40,116,121,112,101, 41, 10,101,110,100, + 10, 10, 45, 45, 32, 97,112,112,101,110,100, 32,102,101, 97, + 116,117,114,101, 32,116,111, 32, 99,111,110,116, 97,105,110, + 101,114, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 67,111,110,116, 97,105,110,101,114, 58, 97,112,112, + 101,110,100, 32, 40,116, 41, 10, 32,115,101,108,102, 46,110, + 32, 61, 32,115,101,108,102, 46,110, 32, 43, 32, 49, 10, 32, + 115,101,108,102, 91,115,101,108,102, 46,110, 93, 32, 61, 32, + 116, 10, 32,116, 46,112, 97,114,101,110,116, 32, 61, 32,115, + 101,108,102, 10,101,110,100, 10, 10, 45, 45, 32, 97,112,112, + 101,110,100, 32,116,121,112,101,100,101,102, 10,102,117,110, + 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111,110,116, + 97,105,110,101,114, 58, 97,112,112,101,110,100,116,121,112, + 101,100,101,102, 32, 40,116, 41, 10, 32,108,111, 99, 97,108, + 32,110, 97,109,101,115,112, 97, 99,101, 32, 61, 32,103,101, + 116,110, 97,109,101,115,112, 97, 99,101, 40, 99,108, 97,115, + 115, 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, + 41, 10, 32,115,101,108,102, 46,116,121,112,101,100,101,102, + 115, 46,116,111,108,117, 97, 95,110, 32, 61, 32,115,101,108, + 102, 46,116,121,112,101,100,101,102,115, 46,116,111,108,117, + 97, 95,110, 32, 43, 32, 49, 10, 32,115,101,108,102, 46,116, + 121,112,101,100,101,102,115, 91,115,101,108,102, 46,116,121, + 112,101,100,101,102,115, 46,116,111,108,117, 97, 95,110, 93, + 32, 61, 32,116, 10, 9,115,101,108,102, 46,116,121,112,101, + 100,101,102,115, 91,116, 46,117,116,121,112,101, 93, 32, 61, + 32,110, 97,109,101,115,112, 97, 99,101, 32, 46, 46, 32,116, + 46,117,116,121,112,101, 10, 9,103,108,111, 98, 97,108, 95, + 116,121,112,101,100,101,102,115, 91,110, 97,109,101,115,112, + 97, 99,101, 46, 46,116, 46,117,116,121,112,101, 93, 32, 61, + 32,116, 10, 9,116, 46,102,116,121,112,101, 32, 61, 32,102, + 105,110,100,116,121,112,101, 40,116, 46,116,121,112,101, 41, + 32,111,114, 32,116, 46,116,121,112,101, 10, 9, 45, 45,112, + 114,105,110,116, 40, 34, 97,112,112,101,110,100,105,110,103, + 32,116,121,112,101,100,101,102, 32, 34, 46, 46,116, 46,117, + 116,121,112,101, 46, 46, 34, 32, 97,115, 32, 34, 46, 46,110, + 97,109,101,115,112, 97, 99,101, 46, 46,116, 46,117,116,121, + 112,101, 46, 46, 34, 32,119,105,116,104, 32,102,116,121,112, + 101, 32, 34, 46, 46,116, 46,102,116,121,112,101, 41, 10, 9, + 97,112,112,101,110,100, 95,103,108,111, 98, 97,108, 95,116, + 121,112,101, 40,110, 97,109,101,115,112, 97, 99,101, 46, 46, + 116, 46,117,116,121,112,101, 41, 10, 9,105,102, 32,116, 46, + 102,116,121,112,101, 32, 97,110,100, 32,105,115,101,110,117, + 109, 40,116, 46,102,116,121,112,101, 41, 32,116,104,101,110, + 10, 10, 9, 9,103,108,111, 98, 97,108, 95,101,110,117,109, + 115, 91,110, 97,109,101,115,112, 97, 99,101, 46, 46,116, 46, + 117,116,121,112,101, 93, 32, 61, 32,116,114,117,101, 10, 9, + 101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, 97,112,112, + 101,110,100, 32,117,115,101,114,116,121,112,101, 58, 32,114, + 101,116,117,114,110, 32,102,117,108,108, 32,116,121,112,101, + 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, + 67,111,110,116, 97,105,110,101,114, 58, 97,112,112,101,110, + 100,117,115,101,114,116,121,112,101, 32, 40,116, 41, 10, 9, + 108,111, 99, 97,108, 32, 99,111,110,116, 97,105,110,101,114, + 10, 9,105,102, 32,116, 32, 61, 61, 32, 40,115,101,108,102, + 46,111,114,105,103,105,110, 97,108, 95,110, 97,109,101, 32, + 111,114, 32,115,101,108,102, 46,110, 97,109,101, 41, 32,116, + 104,101,110, 10, 9, 9, 99,111,110,116, 97,105,110,101,114, + 32, 61, 32,115,101,108,102, 46,112,114,111,120, 10, 9,101, + 108,115,101, 10, 9, 9, 99,111,110,116, 97,105,110,101,114, + 32, 61, 32,115,101,108,102, 10, 9,101,110,100, 10, 9,108, + 111, 99, 97,108, 32,102,116, 32, 61, 32,103,101,116,110, 97, + 109,101,115,112, 97, 99,101, 40, 99,111,110,116, 97,105,110, + 101,114, 41, 32, 46, 46, 32,116, 10, 9, 99,111,110,116, 97, + 105,110,101,114, 46,117,115,101,114,116,121,112,101,115, 91, + 116, 93, 32, 61, 32,102,116, 10, 9, 95,117,115,101,114,116, + 121,112,101, 91,102,116, 93, 32, 61, 32,102,116, 10, 9,114, + 101,116,117,114,110, 32,102,116, 10,101,110,100, 10, 10, 45, + 45, 32, 97,112,112,101,110,100, 32,101,110,117,109, 10,102, + 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111, + 110,116, 97,105,110,101,114, 58, 97,112,112,101,110,100,101, + 110,117,109, 32, 40,116, 41, 10, 32,108,111, 99, 97,108, 32, + 110, 97,109,101,115,112, 97, 99,101, 32, 61, 32,103,101,116, + 110, 97,109,101,115,112, 97, 99,101, 40, 99,108, 97,115,115, + 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 41, + 10, 32,115,101,108,102, 46,101,110,117,109,115, 46,116,111, + 108,117, 97, 95,110, 32, 61, 32,115,101,108,102, 46,101,110, + 117,109,115, 46,116,111,108,117, 97, 95,110, 32, 43, 32, 49, + 10, 32,115,101,108,102, 46,101,110,117,109,115, 91,115,101, + 108,102, 46,101,110,117,109,115, 46,116,111,108,117, 97, 95, + 110, 93, 32, 61, 32,116, 10, 9,103,108,111, 98, 97,108, 95, + 101,110,117,109,115, 91,110, 97,109,101,115,112, 97, 99,101, + 46, 46,116, 46,110, 97,109,101, 93, 32, 61, 32,116, 10,101, + 110,100, 10, 10, 45, 45, 32,100,101,116,101,114,109,105,110, + 101, 32,108,117, 97, 32,102,117,110, 99,116,105,111,110, 32, + 110, 97,109,101, 32,111,118,101,114,108,111, 97,100, 10,102, + 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111, + 110,116, 97,105,110,101,114, 58,111,118,101,114,108,111, 97, + 100, 32, 40,108,110, 97,109,101, 41, 10, 32,105,102, 32,110, + 111,116, 32,115,101,108,102, 46,108,110, 97,109,101,115, 91, + 108,110, 97,109,101, 93, 32,116,104,101,110, 10, 32, 32,115, + 101,108,102, 46,108,110, 97,109,101,115, 91,108,110, 97,109, + 101, 93, 32, 61, 32, 48, 10, 32,101,108,115,101, 10, 32, 32, + 115,101,108,102, 46,108,110, 97,109,101,115, 91,108,110, 97, + 109,101, 93, 32, 61, 32,115,101,108,102, 46,108,110, 97,109, + 101,115, 91,108,110, 97,109,101, 93, 32, 43, 32, 49, 10, 32, + 101,110,100, 10, 32,114,101,116,117,114,110, 32,102,111,114, + 109, 97,116, 40, 34, 37, 48, 50,100, 34, 44,115,101,108,102, + 46,108,110, 97,109,101,115, 91,108,110, 97,109,101, 93, 41, + 10,101,110,100, 10, 10, 45, 45, 32, 97,112,112,108,105,101, + 115, 32,116,121,112,101,100,101,102, 58, 32,114,101,116,117, + 114,110,115, 32,116,104,101, 32, 39,116,104,101, 32,102, 97, + 99,116,111, 39, 32,109,111,100,105,102,105,101,114, 32, 97, + 110,100, 32,116,121,112,101, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101, + 114, 58, 97,112,112,108,121,116,121,112,101,100,101,102, 32, + 40,109,111,100, 44,116,121,112,101, 41, 10, 9,105,102, 32, + 103,108,111, 98, 97,108, 95,116,121,112,101,100,101,102,115, + 91,116,121,112,101, 93, 32,116,104,101,110, 10, 9, 9, 45, + 45,112,114,105,110,116, 40, 34,102,111,117,110,100, 32,116, + 121,112,101,100,101,102, 32, 34, 46, 46,103,108,111, 98, 97, + 108, 95,116,121,112,101,100,101,102,115, 91,116,121,112,101, + 93, 46,116,121,112,101, 41, 10, 9, 9,108,111, 99, 97,108, + 32,109,111,100, 49, 44, 32,116,121,112,101, 49, 32, 61, 32, + 103,108,111, 98, 97,108, 95,116,121,112,101,100,101,102,115, + 91,116,121,112,101, 93, 46,109,111,100, 44, 32,103,108,111, + 98, 97,108, 95,116,121,112,101,100,101,102,115, 91,116,121, + 112,101, 93, 46,102,116,121,112,101, 10, 9, 9,108,111, 99, + 97,108, 32,109,111,100, 50, 44, 32,116,121,112,101, 50, 32, + 61, 32, 97,112,112,108,121,116,121,112,101,100,101,102, 40, + 109,111,100, 46, 46, 34, 32, 34, 46, 46,109,111,100, 49, 44, + 32,116,121,112,101, 49, 41, 10, 9, 9, 45, 45,114,101,116, + 117,114,110, 32,109,111,100, 50, 32, 46, 46, 32, 39, 32, 39, + 32, 46, 46, 32,109,111,100, 49, 44, 32,116,121,112,101, 50, + 10, 9, 9,114,101,116,117,114,110, 32,109,111,100, 50, 44, + 32,116,121,112,101, 50, 10, 9,101,110,100, 10, 9,100,111, + 32,114,101,116,117,114,110, 32,109,111,100, 44,116,121,112, + 101, 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, 99, + 104,101, 99,107, 32,105,102, 32,105,116, 32,105,115, 32, 97, + 32,116,121,112,101,100,101,102, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110, + 101,114, 58,105,115,116,121,112,101,100,101,102, 32, 40,116, + 121,112,101, 41, 10, 32,108,111, 99, 97,108, 32,101,110,118, + 32, 61, 32,115,101,108,102, 10, 32,119,104,105,108,101, 32, + 101,110,118, 32,100,111, 10, 32, 32,105,102, 32,101,110,118, + 46,116,121,112,101,100,101,102,115, 32,116,104,101,110, 10, + 32, 32, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32, 32, + 32,119,104,105,108,101, 32,101,110,118, 46,116,121,112,101, + 100,101,102,115, 91,105, 93, 32,100,111, 10, 32, 32, 32, 32, + 105,102, 32,101,110,118, 46,116,121,112,101,100,101,102,115, + 91,105, 93, 46,117,116,121,112,101, 32, 61, 61, 32,116,121, + 112,101, 32,116,104,101,110, 10, 32, 32, 32, 32, 32, 32, 32, + 32, 32,114,101,116,117,114,110, 32,116,121,112,101, 10, 32, + 32, 32, 32, 32, 32, 32, 32,101,110,100, 10, 32, 32, 32, 32, + 32, 32, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32, 32, 32, + 101,110,100, 10, 32, 32,101,110,100, 10, 32, 32,101,110,118, + 32, 61, 32,101,110,118, 46,112, 97,114,101,110,116, 10, 32, + 101,110,100, 10, 32,114,101,116,117,114,110, 32,110,105,108, + 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, + 102,105,110,100, 95,101,110,117,109, 95,118, 97,114, 40,118, + 97,114, 41, 10, 10, 9,105,102, 32,116,111,110,117,109, 98, + 101,114, 40,118, 97,114, 41, 32,116,104,101,110, 32,114,101, + 116,117,114,110, 32,118, 97,114, 32,101,110,100, 10, 10, 9, + 108,111, 99, 97,108, 32, 99, 32, 61, 32, 99,108, 97,115,115, + 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 10, + 9,119,104,105,108,101, 32, 99, 32,100,111, 10, 9, 9,108, + 111, 99, 97,108, 32,110,115, 32, 61, 32,103,101,116,110, 97, + 109,101,115,112, 97, 99,101, 40, 99, 41, 10, 9, 9,102,111, + 114, 32,107, 44,118, 32,105,110, 32,112, 97,105,114,115, 40, + 95,103,108,111, 98, 97,108, 95,101,110,117,109,115, 41, 32, + 100,111, 10, 9, 9, 9,105,102, 32,109, 97,116, 99,104, 95, + 116,121,112,101, 40,118, 97,114, 44, 32,118, 44, 32,110,115, + 41, 32,116,104,101,110, 10, 9, 9, 9, 9,114,101,116,117, + 114,110, 32,118, 10, 9, 9, 9,101,110,100, 10, 9, 9,101, + 110,100, 10, 9, 9,105,102, 32, 99, 46, 98, 97,115,101, 32, + 97,110,100, 32, 99, 46, 98, 97,115,101, 32,126, 61, 32, 39, + 39, 32,116,104,101,110, 10, 9, 9, 9, 99, 32, 61, 32, 95, + 103,108,111, 98, 97,108, 95, 99,108, 97,115,115,101,115, 91, + 99, 58,102,105,110,100,116,121,112,101, 40, 99, 46, 98, 97, + 115,101, 41, 93, 10, 9, 9,101,108,115,101, 10, 9, 9, 9, + 99, 32, 61, 32,110,105,108, 10, 9, 9,101,110,100, 10, 9, + 101,110,100, 10, 10, 9,114,101,116,117,114,110, 32,118, 97, + 114, 10,101,110,100, 10, 10, 45, 45, 32, 99,104,101, 99,107, + 32,105,102, 32,105,115, 32, 97, 32,114,101,103,105,115,116, + 101,114,101,100, 32,116,121,112,101, 58, 32,114,101,116,117, + 114,110, 32,102,117,108,108, 32,116,121,112,101, 32,111,114, + 32,110,105,108, 10,102,117,110, 99,116,105,111,110, 32, 99, + 108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 58,102, + 105,110,100,116,121,112,101, 32, 40,116, 41, 10, 10, 9,116, + 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40, + 116, 44, 32, 34, 61, 46, 42, 34, 44, 32, 34, 34, 41, 10, 9, + 105,102, 32, 95, 98, 97,115,105, 99, 91,116, 93, 32,116,104, + 101,110, 10, 9, 32,114,101,116,117,114,110, 32,116, 10, 9, + 101,110,100, 10, 10, 9,108,111, 99, 97,108, 32, 95, 44, 95, + 44,101,109, 32, 61, 32,115,116,114,105,110,103, 46,102,105, + 110,100, 40,116, 44, 32, 34, 40, 91, 38, 37, 42, 93, 41, 37, + 115, 42, 36, 34, 41, 10, 9,116, 32, 61, 32,115,116,114,105, + 110,103, 46,103,115,117, 98, 40,116, 44, 32, 34, 37,115, 42, + 40, 91, 38, 37, 42, 93, 41, 37,115, 42, 36, 34, 44, 32, 34, + 34, 41, 10, 9,112, 32, 61, 32,115,101,108,102, 10, 9,119, + 104,105,108,101, 32,112, 32, 97,110,100, 32,116,121,112,101, + 40,112, 41, 61, 61, 39,116, 97, 98,108,101, 39, 32,100,111, + 10, 9, 9,108,111, 99, 97,108, 32,115,116, 32, 61, 32,103, + 101,116,110, 97,109,101,115,112, 97, 99,101, 40,112, 41, 10, + 10, 9, 9,102,111,114, 32,105, 61, 95,103,108,111, 98, 97, + 108, 95,116,121,112,101,115, 46,110, 44, 49, 44, 45, 49, 32, + 100,111, 32, 45, 45, 32,105,110, 32,114,101,118,101,114,115, + 101, 32,111,114,100,101,114, 10, 10, 9, 9, 9,105,102, 32, + 109, 97,116, 99,104, 95,116,121,112,101, 40,116, 44, 32, 95, + 103,108,111, 98, 97,108, 95,116,121,112,101,115, 91,105, 93, + 44, 32,115,116, 41, 32,116,104,101,110, 10, 9, 9, 9, 9, + 114,101,116,117,114,110, 32, 95,103,108,111, 98, 97,108, 95, + 116,121,112,101,115, 91,105, 93, 46, 46, 40,101,109, 32,111, + 114, 32, 34, 34, 41, 10, 9, 9, 9,101,110,100, 10, 9, 9, + 101,110,100, 10, 9, 9,105,102, 32,112, 46, 98, 97,115,101, + 32, 97,110,100, 32,112, 46, 98, 97,115,101, 32,126, 61, 32, + 39, 39, 32, 97,110,100, 32,112, 46, 98, 97,115,101, 32,126, + 61, 32,116, 32,116,104,101,110, 10, 9, 9, 9, 45, 45,112, + 114,105,110,116, 40, 34,116,121,112,101, 32,105,115, 32, 34, + 46, 46,116, 46, 46, 34, 44, 32,112, 32,105,115, 32, 34, 46, + 46,112, 46, 98, 97,115,101, 46, 46, 34, 32,115,101,108,102, + 46,116,121,112,101, 32,105,115, 32, 34, 46, 46,115,101,108, + 102, 46,116,121,112,101, 46, 46, 34, 32,115,101,108,102, 46, + 110, 97,109,101, 32,105,115, 32, 34, 46, 46,115,101,108,102, + 46,110, 97,109,101, 41, 10, 9, 9, 9,112, 32, 61, 32, 95, + 103,108,111, 98, 97,108, 95, 99,108, 97,115,115,101,115, 91, + 112, 58,102,105,110,100,116,121,112,101, 40,112, 46, 98, 97, + 115,101, 41, 93, 10, 9, 9,101,108,115,101, 10, 9, 9, 9, + 112, 32, 61, 32,110,105,108, 10, 9, 9,101,110,100, 10, 9, + 101,110,100, 10, 10, 9,114,101,116,117,114,110, 32,110,105, + 108, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, + 32, 97,112,112,101,110,100, 95,103,108,111, 98, 97,108, 95, + 116,121,112,101, 40,116, 44, 32, 99,108, 97,115,115, 41, 10, + 9, 95,103,108,111, 98, 97,108, 95,116,121,112,101,115, 46, + 110, 32, 61, 32, 95,103,108,111, 98, 97,108, 95,116,121,112, + 101,115, 46,110, 32, 43, 49, 10, 9, 95,103,108,111, 98, 97, + 108, 95,116,121,112,101,115, 91, 95,103,108,111, 98, 97,108, + 95,116,121,112,101,115, 46,110, 93, 32, 61, 32,116, 10, 9, + 95,103,108,111, 98, 97,108, 95,116,121,112,101,115, 95,104, + 97,115,104, 91,116, 93, 32, 61, 32, 49, 10, 9,105,102, 32, + 99,108, 97,115,115, 32,116,104,101,110, 32, 97,112,112,101, + 110,100, 95, 99,108, 97,115,115, 95,116,121,112,101, 40,116, + 44, 32, 99,108, 97,115,115, 41, 32,101,110,100, 10,101,110, + 100, 10, 10,102,117,110, 99,116,105,111,110, 32, 97,112,112, + 101,110,100, 95, 99,108, 97,115,115, 95,116,121,112,101, 40, + 116, 44, 99,108, 97,115,115, 41, 10, 9,105,102, 32, 95,103, + 108,111, 98, 97,108, 95, 99,108, 97,115,115,101,115, 91,116, + 93, 32,116,104,101,110, 10, 9, 9, 99,108, 97,115,115, 46, + 102,108, 97,103,115, 32, 61, 32, 95,103,108,111, 98, 97,108, + 95, 99,108, 97,115,115,101,115, 91,116, 93, 46,102,108, 97, + 103,115, 10, 9, 9, 99,108, 97,115,115, 46,108,110, 97,109, + 101,115, 32, 61, 32, 95,103,108,111, 98, 97,108, 95, 99,108, + 97,115,115,101,115, 91,116, 93, 46,108,110, 97,109,101,115, + 10, 9, 9,105,102, 32, 95,103,108,111, 98, 97,108, 95, 99, + 108, 97,115,115,101,115, 91,116, 93, 46, 98, 97,115,101, 32, + 97,110,100, 32, 40, 95,103,108,111, 98, 97,108, 95, 99,108, + 97,115,115,101,115, 91,116, 93, 46, 98, 97,115,101, 32,126, + 61, 32, 39, 39, 41, 32,116,104,101,110, 10, 9, 9, 9, 99, + 108, 97,115,115, 46, 98, 97,115,101, 32, 61, 32, 95,103,108, + 111, 98, 97,108, 95, 99,108, 97,115,115,101,115, 91,116, 93, + 46, 98, 97,115,101, 32,111,114, 32, 99,108, 97,115,115, 46, + 98, 97,115,101, 10, 9, 9,101,110,100, 10, 9,101,110,100, + 10, 9, 95,103,108,111, 98, 97,108, 95, 99,108, 97,115,115, + 101,115, 91,116, 93, 32, 61, 32, 99,108, 97,115,115, 10, 9, + 99,108, 97,115,115, 46,102,108, 97,103,115, 32, 61, 32, 99, + 108, 97,115,115, 46,102,108, 97,103,115, 32,111,114, 32,123, + 125, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, + 32,109, 97,116, 99,104, 95,116,121,112,101, 40, 99,104,105, + 108,100,116,121,112,101, 44, 32,114,101,103,116,121,112,101, + 44, 32,115,116, 41, 10, 45, 45,112,114,105,110,116, 40, 34, + 102,105,110,100,116,121,112,101, 32, 34, 46, 46, 99,104,105, + 108,100,116,121,112,101, 46, 46, 34, 44, 32, 34, 46, 46,114, + 101,103,116,121,112,101, 46, 46, 34, 44, 32, 34, 46, 46,115, + 116, 41, 10, 9,108,111, 99, 97,108, 32, 98, 44,101, 32, 61, + 32,115,116,114,105,110,103, 46,102,105,110,100, 40,114,101, + 103,116,121,112,101, 44, 32, 99,104,105,108,100,116,121,112, + 101, 44, 32, 45,115,116,114,105,110,103, 46,108,101,110, 40, + 99,104,105,108,100,116,121,112,101, 41, 44, 32,116,114,117, + 101, 41, 10, 9,105,102, 32, 98, 32,116,104,101,110, 10, 10, + 9, 9,105,102, 32,101, 32, 61, 61, 32,115,116,114,105,110, + 103, 46,108,101,110, 40,114,101,103,116,121,112,101, 41, 32, + 97,110,100, 10, 9, 9, 9, 9, 40, 98, 32, 61, 61, 32, 49, + 32,111,114, 32, 40,115,116,114,105,110,103, 46,115,117, 98, + 40,114,101,103,116,121,112,101, 44, 32, 98, 45, 49, 44, 32, + 98, 45, 49, 41, 32, 61, 61, 32, 39, 58, 39, 32, 97,110,100, + 10, 9, 9, 9, 9,115,116,114,105,110,103, 46,115,117, 98, + 40,114,101,103,116,121,112,101, 44, 32, 49, 44, 32, 98, 45, + 49, 41, 32, 61, 61, 32,115,116,114,105,110,103, 46,115,117, + 98, 40,115,116, 44, 32, 49, 44, 32, 98, 45, 49, 41, 41, 41, + 32,116,104,101,110, 10, 9, 9, 9,114,101,116,117,114,110, + 32,116,114,117,101, 10, 9, 9,101,110,100, 10, 9,101,110, + 100, 10, 10, 9,114,101,116,117,114,110, 32,102, 97,108,115, + 101, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, + 32,102,105,110,100,116,121,112,101, 95,111,110, 95, 99,104, + 105,108,100,115, 40,115,101,108,102, 44, 32,116, 41, 10, 10, + 9,108,111, 99, 97,108, 32,116, 99,104,105,108,100, 10, 9, + 105,102, 32,115,101,108,102, 46, 99,108, 97,115,115,116,121, + 112,101, 32, 61, 61, 32, 39, 99,108, 97,115,115, 39, 32,111, + 114, 32,115,101,108,102, 46, 99,108, 97,115,115,116,121,112, + 101, 32, 61, 61, 32, 39,110, 97,109,101,115,112, 97, 99,101, + 39, 32,116,104,101,110, 10, 9, 9,102,111,114, 32,107, 44, + 118, 32,105,110, 32,105,112, 97,105,114,115, 40,115,101,108, + 102, 41, 32,100,111, 10, 9, 9, 9,105,102, 32,118, 46, 99, + 108, 97,115,115,116,121,112,101, 32, 61, 61, 32, 39, 99,108, + 97,115,115, 39, 32,111,114, 32,118, 46, 99,108, 97,115,115, + 116,121,112,101, 32, 61, 61, 32, 39,110, 97,109,101,115,112, + 97, 99,101, 39, 32,116,104,101,110, 10, 9, 9, 9, 9,105, + 102, 32,118, 46,116,121,112,101,100,101,102,115, 32, 97,110, + 100, 32,118, 46,116,121,112,101,100,101,102,115, 91,116, 93, + 32,116,104,101,110, 10, 9, 9, 9, 9, 32,114,101,116,117, + 114,110, 32,118, 46,116,121,112,101,100,101,102,115, 91,116, + 93, 10, 9, 9, 9, 9,101,108,115,101,105,102, 32,118, 46, + 117,115,101,114,116,121,112,101,115, 32, 97,110,100, 32,118, + 46,117,115,101,114,116,121,112,101,115, 91,116, 93, 32,116, + 104,101,110, 10, 9, 9, 9, 9, 32,114,101,116,117,114,110, + 32,118, 46,117,115,101,114,116,121,112,101,115, 91,116, 93, + 10, 9, 9, 9, 9,101,110,100, 10, 9, 9, 9, 9,116, 99, + 104,105,108,100, 32, 61, 32,102,105,110,100,116,121,112,101, + 95,111,110, 95, 99,104,105,108,100,115, 40,118, 44, 32,116, + 41, 10, 9, 9, 9, 9,105,102, 32,116, 99,104,105,108,100, + 32,116,104,101,110, 32,114,101,116,117,114,110, 32,116, 99, + 104,105,108,100, 32,101,110,100, 10, 9, 9, 9,101,110,100, + 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, 9,114,101, + 116,117,114,110, 32,110,105,108, 10, 10,101,110,100, 10, 10, + 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 58,105,115,101,110,117,109, + 32, 40,116,121,112,101, 41, 10, 32,105,102, 32,103,108,111, + 98, 97,108, 95,101,110,117,109,115, 91,116,121,112,101, 93, + 32,116,104,101,110, 10, 9,114,101,116,117,114,110, 32,116, + 121,112,101, 10, 32,101,108,115,101, 10, 32, 9,114,101,116, + 117,114,110, 32,102, 97,108,115,101, 10, 32,101,110,100, 10, + 10, 32,108,111, 99, 97,108, 32, 98, 97,115,101,116,121,112, + 101, 32, 61, 32,103,115,117, 98, 40,116,121,112,101, 44, 34, + 94, 46, 42, 58, 58, 34, 44, 34, 34, 41, 10, 32,108,111, 99, + 97,108, 32,101,110,118, 32, 61, 32,115,101,108,102, 10, 32, + 119,104,105,108,101, 32,101,110,118, 32,100,111, 10, 32, 32, + 105,102, 32,101,110,118, 46,101,110,117,109,115, 32,116,104, + 101,110, 10, 32, 32, 32,108,111, 99, 97,108, 32,105, 61, 49, + 10, 32, 32, 32,119,104,105,108,101, 32,101,110,118, 46,101, + 110,117,109,115, 91,105, 93, 32,100,111, 10, 32, 32, 32, 32, + 105,102, 32,101,110,118, 46,101,110,117,109,115, 91,105, 93, + 46,110, 97,109,101, 32, 61, 61, 32, 98, 97,115,101,116,121, + 112,101, 32,116,104,101,110, 10, 32, 32, 32, 32, 32, 32, 32, + 32, 32,114,101,116,117,114,110, 32,116,114,117,101, 10, 32, + 32, 32, 32, 32, 32, 32, 32,101,110,100, 10, 32, 32, 32, 32, + 32, 32, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32, 32, 32, + 101,110,100, 10, 32, 32,101,110,100, 10, 32, 32,101,110,118, + 32, 61, 32,101,110,118, 46,112, 97,114,101,110,116, 10, 32, + 101,110,100, 10, 32,114,101,116,117,114,110, 32,102, 97,108, + 115,101, 10,101,110,100, 10, 10,109,101,116,104,111,100,105, + 115,118,105,114,116,117, 97,108, 32, 61, 32,102, 97,108,115, + 101, 32, 45, 45, 32, 97, 32,103,108,111, 98, 97,108, 10, 10, + 45, 45, 32,112, 97,114,115,101, 32, 99,104,117,110,107, 10, + 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 58,100,111,112, 97,114,115, + 101, 32, 40,115, 41, 10, 45, 45,112,114,105,110,116, 32, 40, + 34,112, 97,114,115,101, 32, 34, 46, 46,115, 41, 10, 10, 32, + 45, 45, 32,116,114,121, 32,116,104,101, 32,112, 97,114,115, + 101,114, 32,104,111,111,107, 10, 32,100,111, 10, 32, 9,108, + 111, 99, 97,108, 32,115,117, 98, 32, 61, 32,112, 97,114,115, + 101,114, 95,104,111,111,107, 40,115, 41, 10, 32, 9,105,102, + 32,115,117, 98, 32,116,104,101,110, 10, 32, 9, 9,114,101, + 116,117,114,110, 32,115,117, 98, 10, 32, 9,101,110,100, 10, + 32,101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, 32,116, + 104,101, 32,110,117,108,108, 32,115,116, 97,116,101,109,101, + 110,116, 10, 32,100,111, 10, 32, 9,108,111, 99, 97,108, 32, + 98, 44,101, 44, 99,111,100,101, 32, 61, 32,115,116,114,105, + 110,103, 46,102,105,110,100, 40,115, 44, 32, 34, 94, 37,115, + 42, 59, 34, 41, 10, 32, 9,105,102, 32, 98, 32,116,104,101, + 110, 10, 32, 9, 9,114,101,116,117,114,110, 32,115,116,114, + 115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, 9,101,110, + 100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, + 32,101,109,112,116,121, 32,118,101,114, 98, 97,116,105,109, + 32,108,105,110,101, 10, 32,100,111, 10, 32, 9,108,111, 99, + 97,108, 32, 98, 44,101, 44, 99,111,100,101, 32, 61, 32,115, + 116,114,105,110,103, 46,102,105,110,100, 40,115, 44, 32, 34, + 94, 37,115, 42, 36, 92,110, 34, 41, 10, 32, 9,105,102, 32, + 98, 32,116,104,101,110, 10, 32, 9, 9,114,101,116,117,114, + 110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, + 10, 32, 9,101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, + 45, 32,116,114,121, 32, 76,117, 97, 32, 99,111,100,101, 10, + 32,100,111, 10, 32, 32,108,111, 99, 97,108, 32, 98, 44,101, + 44, 99,111,100,101, 32, 61, 32,115,116,114,102,105,110,100, + 40,115, 44, 34, 94, 37,115, 42, 40, 37, 98, 92, 49, 92, 50, + 41, 34, 41, 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, + 10, 32, 32, 32, 67,111,100,101, 40,115,116,114,115,117, 98, + 40, 99,111,100,101, 44, 50, 44, 45, 50, 41, 41, 10, 32, 32, + 32,114,101,116,117,114,110, 32,115,116,114,115,117, 98, 40, + 115, 44,101, 43, 49, 41, 10, 32, 32,101,110,100, 10, 32,101, + 110,100, 10, 10, 32, 45, 45, 32,116,114,121, 32, 67, 32, 99, + 111,100,101, 10, 32,100,111, 10, 32, 32,108,111, 99, 97,108, + 32, 98, 44,101, 44, 99,111,100,101, 32, 61, 32,115,116,114, + 102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, 40, 37, 98, + 92, 51, 92, 52, 41, 34, 41, 10, 32, 32,105,102, 32, 98, 32, + 116,104,101,110, 10, 9, 99,111,100,101, 32, 61, 32, 39,123, + 39, 46, 46,115,116,114,115,117, 98, 40, 99,111,100,101, 44, + 50, 44, 45, 50, 41, 46, 46, 39, 92,110,125, 92,110, 39, 10, + 9, 86,101,114, 98, 97,116,105,109, 40, 99,111,100,101, 44, + 39,114, 39, 41, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 32, + 118,101,114, 98, 97,116,105,109, 32, 99,111,100,101, 32,102, + 111,114, 32, 39,114, 39,101,103,105,115,116,101,114, 32,102, + 114, 97,103,109,101,110,116, 10, 9,114,101,116,117,114,110, + 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, + 32, 32,101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, + 32,116,114,121, 32, 67, 32, 99,111,100,101, 32,102,111,114, + 32,112,114,101, 97,109, 98,108,101, 32,115,101, 99,116,105, + 111,110, 10, 32,100,111, 10, 32, 9,108,111, 99, 97,108, 32, + 98, 44,101, 44, 99,111,100,101, 32, 61, 32,115,116,114,105, + 110,103, 46,102,105,110,100, 40,115, 44, 32, 34, 94, 37,115, + 42, 40, 37, 98, 92, 53, 92, 54, 41, 34, 41, 10, 32, 9,105, + 102, 32, 98, 32,116,104,101,110, 10, 32, 9, 9, 99,111,100, + 101, 32, 61, 32,115,116,114,105,110,103, 46,115,117, 98, 40, + 99,111,100,101, 44, 32, 50, 44, 32, 45, 50, 41, 46, 46, 34, + 92,110, 34, 10, 9, 9, 86,101,114, 98, 97,116,105,109, 40, + 99,111,100,101, 44, 32, 39, 39, 41, 10, 9, 9,114,101,116, + 117,114,110, 32,115,116,114,105,110,103, 46,115,117, 98, 40, + 115, 44, 32,101, 43, 49, 41, 10, 32, 9,101,110,100, 10, 32, + 101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, 32,100,101, + 102, 97,117,108,116, 95,112,114,111,112,101,114,116,121, 32, + 100,105,114,101, 99,116,105,118,101, 10, 32,100,111, 10, 32, + 9,108,111, 99, 97,108, 32, 98, 44,101, 44,112,116,121,112, + 101, 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 32, + 34, 94, 37,115, 42, 84, 79, 76, 85, 65, 95, 80, 82, 79, 80, + 69, 82, 84, 89, 95, 84, 89, 80, 69, 37,115, 42, 37, 40, 43, + 37,115, 42, 40, 91, 94, 37, 41, 37,115, 93, 42, 41, 37,115, + 42, 37, 41, 43, 37,115, 42, 59, 63, 34, 41, 10, 32, 9,105, + 102, 32, 98, 32,116,104,101,110, 10, 32, 9, 9,105,102, 32, + 110,111,116, 32,112,116,121,112,101, 32,111,114, 32,112,116, + 121,112,101, 32, 61, 61, 32, 34, 34, 32,116,104,101,110, 10, + 32, 9, 9, 9,112,116,121,112,101, 32, 61, 32, 34,100,101, + 102, 97,117,108,116, 34, 10, 32, 9, 9,101,110,100, 10, 32, + 9, 9,115,101,108,102, 58,115,101,116, 95,112,114,111,112, + 101,114,116,121, 95,116,121,112,101, 40,112,116,121,112,101, + 41, 10, 9, 32, 9,114,101,116,117,114,110, 32,115,116,114, + 115,117, 98, 40,115, 44, 32,101, 43, 49, 41, 10, 32, 9,101, + 110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32,116,114, + 121, 32,112,114,111,116,101, 99,116,101,100, 95,100,101,115, + 116,114,117, 99,116,111,114, 32,100,105,114,101, 99,116,105, + 118,101, 10, 32,100,111, 10, 32, 9,108,111, 99, 97,108, 32, + 98, 44,101, 32, 61, 32,115,116,114,105,110,103, 46,102,105, + 110,100, 40,115, 44, 32, 34, 94, 37,115, 42, 84, 79, 76, 85, + 65, 95, 80, 82, 79, 84, 69, 67, 84, 69, 68, 95, 68, 69, 83, + 84, 82, 85, 67, 84, 79, 82, 37,115, 42, 59, 63, 34, 41, 10, + 9,105,102, 32, 98, 32,116,104,101,110, 10, 9, 9,105,102, + 32,115,101,108,102, 46,115,101,116, 95,112,114,111,116,101, + 99,116,101,100, 95,100,101,115,116,114,117, 99,116,111,114, + 32,116,104,101,110, 10, 9, 32, 9, 9,115,101,108,102, 58, + 115,101,116, 95,112,114,111,116,101, 99,116,101,100, 95,100, + 101,115,116,114,117, 99,116,111,114, 40,116,114,117,101, 41, + 10, 9, 32, 9,101,110,100, 10, 32, 9, 9,114,101,116,117, + 114,110, 32,115,116,114,115,117, 98, 40,115, 44, 32,101, 43, + 49, 41, 10, 32, 9,101,110,100, 10, 32,101,110,100, 10, 10, + 32, 45, 45, 32,116,114,121, 32, 39,101,120,116,101,114,110, + 39, 32,107,101,121,119,111,114,100, 10, 32,100,111, 10, 32, + 9,108,111, 99, 97,108, 32, 98, 44,101, 32, 61, 32,115,116, + 114,105,110,103, 46,102,105,110,100, 40,115, 44, 32, 34, 94, + 37,115, 42,101,120,116,101,114,110, 37,115, 43, 34, 41, 10, + 32, 9,105,102, 32, 98, 32,116,104,101,110, 10, 9, 9, 45, + 45, 32,100,111, 32,110,111,116,104,105,110,103, 10, 32, 9, + 9,114,101,116,117,114,110, 32,115,116,114,115,117, 98, 40, + 115, 44, 32,101, 43, 49, 41, 10, 32, 9,101,110,100, 10, 32, + 101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, 32, 39,118, + 105,114,116,117, 97,108, 39, 32,107,101,121,119,111,114,107, + 100, 10, 32,100,111, 10, 32, 9,108,111, 99, 97,108, 32, 98, + 44,101, 32, 61, 32,115,116,114,105,110,103, 46,102,105,110, + 100, 40,115, 44, 32, 34, 94, 37,115, 42,118,105,114,116,117, + 97,108, 37,115, 43, 34, 41, 10, 32, 9,105,102, 32, 98, 32, + 116,104,101,110, 10, 32, 9, 9,109,101,116,104,111,100,105, + 115,118,105,114,116,117, 97,108, 32, 61, 32,116,114,117,101, + 10, 32, 9, 9,114,101,116,117,114,110, 32,115,116,114,115, + 117, 98, 40,115, 44, 32,101, 43, 49, 41, 10, 32, 9,101,110, + 100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, + 32,108, 97, 98,101,108,115, 32, 40,112,117, 98,108,105, 99, + 44, 32,112,114,105,118, 97,116,101, 44, 32,101,116, 99, 41, + 10, 32,100,111, 10, 32, 9,108,111, 99, 97,108, 32, 98, 44, + 101, 32, 61, 32,115,116,114,105,110,103, 46,102,105,110,100, + 40,115, 44, 32, 34, 94, 37,115, 42, 37,119, 42, 37,115, 42, + 58, 91, 94, 58, 93, 34, 41, 10, 32, 9,105,102, 32, 98, 32, + 116,104,101,110, 10, 32, 9, 9,114,101,116,117,114,110, 32, + 115,116,114,115,117, 98, 40,115, 44, 32,101, 41, 32, 45, 45, + 32,112,114,101,115,101,114,118,101, 32,116,104,101, 32, 91, + 94, 58, 93, 10, 32, 9,101,110,100, 10, 32,101,110,100, 10, + 10, 32, 45, 45, 32,116,114,121, 32,109,111,100,117,108,101, + 10, 32,100,111, 10, 32, 32,108,111, 99, 97,108, 32, 98, 44, + 101, 44,110, 97,109,101, 44, 98,111,100,121, 32, 61, 32,115, + 116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42,109, + 111,100,117,108,101, 37,115, 37,115, 42, 40, 91, 95, 37,119, + 93, 91, 95, 37,119, 93, 42, 41, 37,115, 42, 40, 37, 98,123, + 125, 41, 37,115, 42, 34, 41, 10, 32, 32,105,102, 32, 98, 32, + 116,104,101,110, 10, 32, 32, 32, 95, 99,117,114,114, 95, 99, + 111,100,101, 32, 61, 32,115,116,114,115,117, 98, 40,115, 44, + 98, 44,101, 41, 10, 32, 32, 32, 77,111,100,117,108,101, 40, + 110, 97,109,101, 44, 98,111,100,121, 41, 10, 32, 32, 32,114, + 101,116,117,114,110, 32,115,116,114,115,117, 98, 40,115, 44, + 101, 43, 49, 41, 10, 32, 32,101,110,100, 10, 32,101,110,100, + 10, 10, 32, 45, 45, 32,116,114,121, 32,110, 97,109,101,115, + 97,112, 99,101, 10, 32,100,111, 10, 32, 32,108,111, 99, 97, + 108, 32, 98, 44,101, 44,110, 97,109,101, 44, 98,111,100,121, + 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, + 37,115, 42,110, 97,109,101,115,112, 97, 99,101, 37,115, 37, + 115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 93, 42, 41, + 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, 59, 63, 34, + 41, 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, 10, 32, + 32, 32, 95, 99,117,114,114, 95, 99,111,100,101, 32, 61, 32, + 115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, 10, 32, + 32, 32, 78, 97,109,101,115,112, 97, 99,101, 40,110, 97,109, + 101, 44, 98,111,100,121, 41, 10, 32, 32, 32,114,101,116,117, + 114,110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, + 41, 10, 32, 32,101,110,100, 10, 32,101,110,100, 10, 10, 32, + 45, 45, 32,116,114,121, 32,100,101,102,105,110,101, 10, 32, + 100,111, 10, 32, 32,108,111, 99, 97,108, 32, 98, 44,101, 44, + 110, 97,109,101, 32, 61, 32,115,116,114,102,105,110,100, 40, + 115, 44, 34, 94, 37,115, 42, 35,100,101,102,105,110,101, 37, + 115, 37,115, 42, 40, 91, 94, 37,115, 93, 42, 41, 91, 94, 92, + 110, 93, 42, 92,110, 37,115, 42, 34, 41, 10, 32, 32,105,102, + 32, 98, 32,116,104,101,110, 10, 32, 32, 32, 95, 99,117,114, + 114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, 98, + 40,115, 44, 98, 44,101, 41, 10, 32, 32, 32, 68,101,102,105, + 110,101, 40,110, 97,109,101, 41, 10, 32, 32, 32,114,101,116, + 117,114,110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, + 49, 41, 10, 32, 32,101,110,100, 10, 32,101,110,100, 10, 10, + 32, 45, 45, 32,116,114,121, 32,101,110,117,109,101,114, 97, + 116,101,115, 10, 10, 32,100,111, 10, 32, 32,108,111, 99, 97, + 108, 32, 98, 44,101, 44,110, 97,109,101, 44, 98,111,100,121, + 44,118, 97,114,110, 97,109,101, 32, 61, 32,115,116,114,102, + 105,110,100, 40,115, 44, 34, 94, 37,115, 42,101,110,117,109, + 37,115, 43, 40, 37, 83, 42, 41, 37,115, 42, 40, 37, 98,123, + 125, 41, 37,115, 42, 40, 91, 94, 37,115, 59, 93, 42, 41, 37, + 115, 42, 59, 63, 37,115, 42, 34, 41, 10, 32, 32,105,102, 32, + 98, 32,116,104,101,110, 10, 32, 32, 32, 45, 45,101,114,114, + 111,114, 40, 34, 35, 83,111,114,114,121, 44, 32,100,101, 99, + 108, 97,114, 97,116,105,111,110, 32,111,102, 32,101,110,117, + 109,115, 32, 97,110,100, 32,118, 97,114,105, 97, 98,108,101, + 115, 32,111,110, 32,116,104,101, 32,115, 97,109,101, 32,115, + 116, 97,116,101,109,101,110,116, 32,105,115, 32,110,111,116, + 32,115,117,112,112,111,114,116,101,100, 46, 92,110, 68,101, + 99,108, 97,114,101, 32,121,111,117,114, 32,118, 97,114,105, + 97, 98,108,101, 32,115,101,112, 97,114, 97,116,101,108,121, + 32, 40,101,120, 97,109,112,108,101, 58, 32, 39, 34, 46, 46, + 110, 97,109,101, 46, 46, 34, 32, 34, 46, 46,118, 97,114,110, + 97,109,101, 46, 46, 34, 59, 39, 41, 34, 41, 10, 32, 32, 32, + 95, 99,117,114,114, 95, 99,111,100,101, 32, 61, 32,115,116, + 114,115,117, 98, 40,115, 44, 98, 44,101, 41, 10, 32, 32, 32, + 69,110,117,109,101,114, 97,116,101, 40,110, 97,109,101, 44, + 98,111,100,121, 44,118, 97,114,110, 97,109,101, 41, 10, 32, + 32, 32,114,101,116,117,114,110, 32,115,116,114,115,117, 98, + 40,115, 44,101, 43, 49, 41, 10, 32, 32,101,110,100, 10, 32, + 101,110,100, 10, 10, 45, 45, 32,100,111, 10, 45, 45, 32, 32, + 108,111, 99, 97,108, 32, 98, 44,101, 44,110, 97,109,101, 44, + 98,111,100,121, 32, 61, 32,115,116,114,102,105,110,100, 40, + 115, 44, 34, 94, 37,115, 42,101,110,117,109, 37,115, 43, 40, + 37, 83, 42, 41, 37,115, 42, 40, 37, 98,123,125, 41, 37,115, + 42, 59, 63, 37,115, 42, 34, 41, 10, 45, 45, 32, 32,105,102, + 32, 98, 32,116,104,101,110, 10, 45, 45, 32, 32, 32, 95, 99, + 117,114,114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115, + 117, 98, 40,115, 44, 98, 44,101, 41, 10, 45, 45, 32, 32, 32, + 69,110,117,109,101,114, 97,116,101, 40,110, 97,109,101, 44, + 98,111,100,121, 41, 10, 45, 45, 32, 32,114,101,116,117,114, + 110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, + 10, 45, 45, 32, 32,101,110,100, 10, 45, 45, 32,101,110,100, + 10, 10, 32,100,111, 10, 32, 32,108,111, 99, 97,108, 32, 98, + 44,101, 44, 98,111,100,121, 44,110, 97,109,101, 32, 61, 32, + 115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, + 116,121,112,101,100,101,102, 37,115, 43,101,110,117,109, 91, + 94,123, 93, 42, 40, 37, 98,123,125, 41, 37,115, 42, 40, 91, + 37,119, 95, 93, 91, 94, 37,115, 93, 42, 41, 37,115, 42, 59, + 37,115, 42, 34, 41, 10, 32, 32,105,102, 32, 98, 32,116,104, + 101,110, 10, 32, 32, 32, 95, 99,117,114,114, 95, 99,111,100, + 101, 32, 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44, + 101, 41, 10, 32, 32, 32, 69,110,117,109,101,114, 97,116,101, + 40,110, 97,109,101, 44, 98,111,100,121, 41, 10, 32, 32, 32, + 114,101,116,117,114,110, 32,115,116,114,115,117, 98, 40,115, + 44,101, 43, 49, 41, 10, 32, 32,101,110,100, 10, 32,101,110, + 100, 10, 10, 32, 45, 45, 32,116,114,121, 32,111,112,101,114, + 97,116,111,114, 10, 32,100,111, 10, 32, 32,108,111, 99, 97, + 108, 32, 98, 44,101, 44,100,101, 99,108, 44,107,105,110,100, + 44, 97,114,103, 44, 99,111,110,115,116, 32, 61, 32,115,116, + 114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, 40, 91, + 95, 37,119, 93, 91, 95, 37,119, 37,115, 37, 42, 38, 58, 60, + 62, 44, 93, 45, 37,115, 43,111,112,101,114, 97,116,111,114, + 41, 37,115, 42, 40, 91, 94, 37,115, 93, 91, 94, 37,115, 93, + 42, 41, 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, + 99, 63,111, 63,110, 63,115, 63,116, 63, 41, 37,115, 42, 59, + 37,115, 42, 34, 41, 10, 32, 32,105,102, 32,110,111,116, 32, + 98, 32,116,104,101,110, 10, 9, 9, 32, 45, 45, 32,116,114, + 121, 32,105,110,108,105,110,101, 10, 32, 32, 32, 98, 44,101, + 44,100,101, 99,108, 44,107,105,110,100, 44, 97,114,103, 44, + 99,111,110,115,116, 32, 61, 32,115,116,114,102,105,110,100, + 40,115, 44, 34, 94, 37,115, 42, 40, 91, 95, 37,119, 93, 91, + 95, 37,119, 37,115, 37, 42, 38, 58, 60, 62, 44, 93, 45, 37, + 115, 43,111,112,101,114, 97,116,111,114, 41, 37,115, 42, 40, + 91, 94, 37,115, 93, 91, 94, 37,115, 93, 42, 41, 37,115, 42, + 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, + 63,115, 63,116, 63, 41, 91, 37,115, 92,110, 93, 42, 37, 98, + 123,125, 37,115, 42, 59, 63, 37,115, 42, 34, 41, 10, 32, 32, + 101,110,100, 10, 32, 32,105,102, 32,110,111,116, 32, 98, 32, + 116,104,101,110, 10, 32, 32, 9, 45, 45, 32,116,114,121, 32, + 99, 97,115,116, 32,111,112,101,114, 97,116,111,114, 10, 32, + 32, 9, 98, 44,101, 44,100,101, 99,108, 44,107,105,110,100, + 44, 97,114,103, 44, 99,111,110,115,116, 32, 61, 32,115,116, + 114,102,105,110,100, 40,115, 44, 32, 34, 94, 37,115, 42, 40, + 111,112,101,114, 97,116,111,114, 41, 37,115, 43, 40, 91, 37, + 119, 95, 58, 37,100, 60, 62, 37, 42, 37, 38, 37,115, 93, 43, + 41, 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, + 63,111, 63,110, 63,115, 63,116, 63, 41, 34, 41, 59, 10, 32, + 32, 9,105,102, 32, 98, 32,116,104,101,110, 10, 32, 32, 9, + 9,108,111, 99, 97,108, 32, 95, 44,105,101, 32, 61, 32,115, + 116,114,105,110,103, 46,102,105,110,100, 40,115, 44, 32, 34, + 94, 37,115, 42, 37, 98,123,125, 34, 44, 32,101, 43, 49, 41, + 10, 32, 32, 9, 9,105,102, 32,105,101, 32,116,104,101,110, + 10, 32, 32, 9, 9, 9,101, 32, 61, 32,105,101, 10, 32, 32, + 9, 9,101,110,100, 10, 32, 32, 9,101,110,100, 10, 32, 32, + 101,110,100, 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, + 10, 32, 32, 32, 95, 99,117,114,114, 95, 99,111,100,101, 32, + 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, + 10, 32, 32, 32, 79,112,101,114, 97,116,111,114, 40,100,101, + 99,108, 44,107,105,110,100, 44, 97,114,103, 44, 99,111,110, + 115,116, 41, 10, 32, 32, 32,114,101,116,117,114,110, 32,115, + 116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, 32, + 101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32,116, + 114,121, 32,102,117,110, 99,116,105,111,110, 10, 32,100,111, + 10, 32, 32, 45, 45,108,111, 99, 97,108, 32, 98, 44,101, 44, + 100,101, 99,108, 44, 97,114,103, 44, 99,111,110,115,116, 32, + 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37, + 115, 42, 40, 91,126, 95, 37,119, 93, 91, 95, 64, 37,119, 37, + 115, 37, 42, 38, 58, 60, 62, 93, 42, 91, 95, 37,119, 93, 41, + 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63, + 111, 63,110, 63,115, 63,116, 63, 41, 37,115, 42, 61, 63, 37, + 115, 42, 48, 63, 37,115, 42, 59, 37,115, 42, 34, 41, 10, 32, + 32,108,111, 99, 97,108, 32, 98, 44,101, 44,100,101, 99,108, + 44, 97,114,103, 44, 99,111,110,115,116, 44,118,105,114,116, + 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, + 37,115, 42, 40, 91, 94, 37, 40, 92,110, 93, 43, 41, 37,115, + 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63, + 110, 63,115, 63,116, 63, 41, 37,115, 42, 40, 61, 63, 37,115, + 42, 48, 63, 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10, 32, + 32,105,102, 32,110,111,116, 32, 98, 32,116,104,101,110, 10, + 32, 32, 9, 45, 45, 32,116,114,121, 32,102,117,110, 99,116, + 105,111,110, 32,119,105,116,104, 32,116,101,109,112,108, 97, + 116,101, 10, 32, 32, 9, 98, 44,101, 44,100,101, 99,108, 44, + 97,114,103, 44, 99,111,110,115,116, 32, 61, 32,115,116,114, + 102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, 40, 91,126, + 95, 37,119, 93, 91, 95, 64, 37,119, 37,115, 37, 42, 38, 58, + 60, 62, 93, 42, 91, 95, 37,119, 93, 37, 98, 60, 62, 41, 37, + 115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, + 63,110, 63,115, 63,116, 63, 41, 37,115, 42, 61, 63, 37,115, + 42, 48, 63, 37,115, 42, 59, 37,115, 42, 34, 41, 10, 32, 32, + 101,110,100, 10, 32, 32,105,102, 32,110,111,116, 32, 98, 32, + 116,104,101,110, 10, 32, 32, 32, 45, 45, 32,116,114,121, 32, + 97, 32,115,105,110,103,108,101, 32,108,101,116,116,101,114, + 32,102,117,110, 99,116,105,111,110, 32,110, 97,109,101, 10, + 32, 32, 32, 98, 44,101, 44,100,101, 99,108, 44, 97,114,103, + 44, 99,111,110,115,116, 32, 61, 32,115,116,114,102,105,110, + 100, 40,115, 44, 34, 94, 37,115, 42, 40, 91, 95, 37,119, 93, + 41, 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, + 63,111, 63,110, 63,115, 63,116, 63, 41, 37,115, 42, 59, 37, + 115, 42, 34, 41, 10, 32, 32,101,110,100, 10, 32, 32,105,102, + 32,110,111,116, 32, 98, 32,116,104,101,110, 10, 32, 32, 32, + 45, 45, 32,116,114,121, 32,102,117,110, 99,116,105,111,110, + 32,112,111,105,110,116,101,114, 10, 32, 32, 32, 98, 44,101, + 44,100,101, 99,108, 44, 97,114,103, 44, 99,111,110,115,116, + 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, + 37,115, 42, 40, 91, 94, 37, 40, 59, 92,110, 93, 43, 37, 98, + 40, 41, 41, 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, + 59, 37,115, 42, 34, 41, 10, 32, 32, 32,105,102, 32, 98, 32, + 116,104,101,110, 10, 32, 32, 32, 32,100,101, 99,108, 32, 61, + 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,100,101, + 99,108, 44, 32, 34, 37, 40, 37,115, 42, 37, 42, 40, 91, 94, + 37, 41, 93, 42, 41, 37,115, 42, 37, 41, 34, 44, 32, 34, 32, + 37, 49, 32, 34, 41, 10, 32, 32, 32,101,110,100, 10, 32, 32, + 101,110,100, 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, + 10, 32, 32, 9,105,102, 32,118,105,114,116, 32, 97,110,100, + 32,115,116,114,105,110,103, 46,102,105,110,100, 40,118,105, + 114,116, 44, 32, 34, 91, 61, 48, 93, 34, 41, 32,116,104,101, + 110, 10, 32, 32, 9, 9,105,102, 32,115,101,108,102, 46,102, + 108, 97,103,115, 32,116,104,101,110, 10, 32, 32, 9, 9, 9, + 115,101,108,102, 46,102,108, 97,103,115, 46,112,117,114,101, + 95,118,105,114,116,117, 97,108, 32, 61, 32,116,114,117,101, + 10, 32, 32, 9, 9,101,110,100, 10, 32, 32, 9,101,110,100, + 10, 32, 32, 32, 95, 99,117,114,114, 95, 99,111,100,101, 32, + 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, + 10, 32, 32, 32, 70,117,110, 99,116,105,111,110, 40,100,101, + 99,108, 44, 97,114,103, 44, 99,111,110,115,116, 41, 10, 32, + 32, 32,114,101,116,117,114,110, 32,115,116,114,115,117, 98, + 40,115, 44,101, 43, 49, 41, 10, 32, 32,101,110,100, 10, 32, + 101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, 32,105,110, + 108,105,110,101, 32,102,117,110, 99,116,105,111,110, 10, 32, + 100,111, 10, 32, 32,108,111, 99, 97,108, 32, 98, 44,101, 44, + 100,101, 99,108, 44, 97,114,103, 44, 99,111,110,115,116, 32, + 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37, + 115, 42, 40, 91, 94, 37, 40, 92,110, 93, 43, 41, 37,115, 42, + 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, + 63,115, 63,116, 63, 41, 91, 94, 59,123, 93, 42, 37, 98,123, + 125, 37,115, 42, 59, 63, 37,115, 42, 34, 41, 10, 32, 32, 45, + 45,108,111, 99, 97,108, 32, 98, 44,101, 44,100,101, 99,108, + 44, 97,114,103, 44, 99,111,110,115,116, 32, 61, 32,115,116, + 114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, 40, 91, + 126, 95, 37,119, 93, 91, 95, 64, 37,119, 37,115, 37, 42, 38, + 58, 60, 62, 93, 42, 91, 95, 37,119, 62, 93, 41, 37,115, 42, + 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, + 63,115, 63,116, 63, 41, 91, 94, 59, 93, 42, 37, 98,123,125, + 37,115, 42, 59, 63, 37,115, 42, 34, 41, 10, 32, 32,105,102, + 32,110,111,116, 32, 98, 32,116,104,101,110, 10, 32, 32, 32, + 45, 45, 32,116,114,121, 32, 97, 32,115,105,110,103,108,101, + 32,108,101,116,116,101,114, 32,102,117,110, 99,116,105,111, + 110, 32,110, 97,109,101, 10, 32, 32, 32, 98, 44,101, 44,100, + 101, 99,108, 44, 97,114,103, 44, 99,111,110,115,116, 32, 61, + 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, + 42, 40, 91, 95, 37,119, 93, 41, 37,115, 42, 40, 37, 98, 40, + 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, + 63, 41, 46, 45, 37, 98,123,125, 37,115, 42, 59, 63, 37,115, + 42, 34, 41, 10, 32, 32,101,110,100, 10, 32, 32,105,102, 32, + 98, 32,116,104,101,110, 10, 32, 32, 32, 95, 99,117,114,114, + 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, 98, 40, + 115, 44, 98, 44,101, 41, 10, 32, 32, 32, 70,117,110, 99,116, + 105,111,110, 40,100,101, 99,108, 44, 97,114,103, 44, 99,111, + 110,115,116, 41, 10, 32, 32, 32,114,101,116,117,114,110, 32, + 115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, + 32,101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, + 116,114,121, 32, 99,108, 97,115,115, 10, 32,100,111, 10, 9, + 32,108,111, 99, 97,108, 32, 98, 44,101, 44,110, 97,109,101, + 44, 98, 97,115,101, 44, 98,111,100,121, 10, 9, 9, 98, 97, + 115,101, 32, 61, 32, 39, 39, 32, 98,111,100,121, 32, 61, 32, + 39, 39, 10, 9, 9, 98, 44,101, 44,110, 97,109,101, 32, 61, + 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, + 42, 99,108, 97,115,115, 37,115, 42, 40, 91, 95, 37,119, 93, + 91, 95, 37,119, 64, 93, 42, 41, 37,115, 42, 59, 34, 41, 32, + 32, 45, 45, 32,100,117,109,109,121, 32, 99,108, 97,115,115, + 10, 9, 9,108,111, 99, 97,108, 32,100,117,109,109,121, 32, + 61, 32,102, 97,108,115,101, 10, 9, 9,105,102, 32,110,111, + 116, 32, 98, 32,116,104,101,110, 10, 9, 9, 9, 98, 44,101, + 44,110, 97,109,101, 32, 61, 32,115,116,114,102,105,110,100, + 40,115, 44, 34, 94, 37,115, 42,115,116,114,117, 99,116, 37, + 115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 64, 93, 42, + 41, 37,115, 42, 59, 34, 41, 32, 32, 32, 32, 45, 45, 32,100, + 117,109,109,121, 32,115,116,114,117, 99,116, 10, 9, 9, 9, + 105,102, 32,110,111,116, 32, 98, 32,116,104,101,110, 10, 9, + 9, 9, 9, 98, 44,101, 44,110, 97,109,101, 44, 98, 97,115, + 101, 44, 98,111,100,121, 32, 61, 32,115,116,114,102,105,110, + 100, 40,115, 44, 34, 94, 37,115, 42, 99,108, 97,115,115, 37, + 115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 64, 93, 42, + 41, 37,115, 42, 40, 91, 94,123, 93, 45, 41, 37,115, 42, 40, + 37, 98,123,125, 41, 37,115, 42, 34, 41, 10, 9, 9, 9, 9, + 105,102, 32,110,111,116, 32, 98, 32,116,104,101,110, 10, 9, + 9, 9, 9, 9, 98, 44,101, 44,110, 97,109,101, 44, 98, 97, + 115,101, 44, 98,111,100,121, 32, 61, 32,115,116,114,102,105, + 110,100, 40,115, 44, 34, 94, 37,115, 42,115,116,114,117, 99, + 116, 37,115, 43, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 64, + 93, 42, 41, 37,115, 42, 40, 91, 94,123, 93, 45, 41, 37,115, + 42, 40, 37, 98,123,125, 41, 37,115, 42, 34, 41, 10, 9, 9, + 9, 9, 9,105,102, 32,110,111,116, 32, 98, 32,116,104,101, + 110, 10, 9, 9, 9, 9, 9, 9, 98, 44,101, 44,110, 97,109, + 101, 44, 98, 97,115,101, 44, 98,111,100,121, 32, 61, 32,115, + 116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42,117, + 110,105,111,110, 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, + 37,119, 64, 93, 42, 41, 37,115, 42, 40, 91, 94,123, 93, 45, + 41, 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, 34, 41, + 10, 9, 9, 9, 9, 9, 9,105,102, 32,110,111,116, 32, 98, + 32,116,104,101,110, 10, 9, 9, 9, 9, 9, 9, 9, 98, 97, + 115,101, 32, 61, 32, 39, 39, 10, 9, 9, 9, 9, 9, 9, 9, + 98, 44,101, 44, 98,111,100,121, 44,110, 97,109,101, 32, 61, + 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, + 42,116,121,112,101,100,101,102, 37,115, 37,115, 42,115,116, + 114,117, 99,116, 37,115, 37,115, 42, 91, 95, 37,119, 93, 42, + 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, 40, 91, 95, + 37,119, 93, 91, 95, 37,119, 64, 93, 42, 41, 37,115, 42, 59, + 34, 41, 10, 9, 9, 9, 9, 9, 9,101,110,100, 10, 9, 9, + 9, 9, 9,101,110,100, 10, 9, 9, 9, 9,101,110,100, 10, + 9, 9, 9,101,108,115,101, 32,100,117,109,109,121, 32, 61, + 32, 49, 32,101,110,100, 10, 9, 9,101,108,115,101, 32,100, + 117,109,109,121, 32, 61, 32, 49, 32,101,110,100, 10, 9, 9, + 105,102, 32, 98, 32,116,104,101,110, 10, 9, 9, 9,105,102, + 32, 98, 97,115,101, 32,126, 61, 32, 39, 39, 32,116,104,101, + 110, 10, 9, 9, 9, 9, 98, 97,115,101, 32, 61, 32,115,116, + 114,105,110,103, 46,103,115,117, 98, 40, 98, 97,115,101, 44, + 32, 34, 94, 37,115, 42, 58, 37,115, 42, 34, 44, 32, 34, 34, + 41, 10, 9, 9, 9, 9, 98, 97,115,101, 32, 61, 32,115,116, + 114,105,110,103, 46,103,115,117, 98, 40, 98, 97,115,101, 44, + 32, 34, 37,115, 42,112,117, 98,108,105, 99, 37,115, 42, 34, + 44, 32, 34, 34, 41, 10, 9, 9, 9, 9, 98, 97,115,101, 32, + 61, 32,115,112,108,105,116, 40, 98, 97,115,101, 44, 32, 34, + 44, 34, 41, 10, 9, 9, 9, 9, 45, 45,108,111, 99, 97,108, + 32, 98, 44,101, 10, 9, 9, 9, 9, 45, 45, 98, 44,101, 44, + 98, 97,115,101, 32, 61, 32,115,116,114,102,105,110,100, 40, + 98, 97,115,101, 44, 34, 46, 45, 40, 91, 95, 37,119, 93, 91, + 95, 37,119, 60, 62, 44, 58, 93, 42, 41, 36, 34, 41, 10, 9, + 9, 9,101,108,115,101, 10, 9, 9, 9, 9, 98, 97,115,101, + 32, 61, 32,123,125, 10, 9, 9, 9,101,110,100, 10, 9, 9, + 9, 95, 99,117,114,114, 95, 99,111,100,101, 32, 61, 32,115, + 116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, 10, 9, 9, + 9, 67,108, 97,115,115, 40,110, 97,109,101, 44, 98, 97,115, + 101, 44, 98,111,100,121, 41, 10, 9, 9, 9,105,102, 32,110, + 111,116, 32,100,117,109,109,121, 32,116,104,101,110, 10, 9, + 9, 9, 9,118, 97,114, 98, 44,118, 97,114,101, 44,118, 97, + 114,110, 97,109,101, 32, 61, 32,115,116,114,105,110,103, 46, + 102,105,110,100, 40,115, 44, 32, 34, 94, 37,115, 42, 40, 91, + 95, 37,119, 93, 43, 41, 37,115, 42, 59, 34, 44, 32,101, 43, + 49, 41, 10, 9, 9, 9, 9,105,102, 32,118, 97,114, 98, 32, + 116,104,101,110, 10, 9, 9, 9, 9, 9, 86, 97,114,105, 97, + 98,108,101, 40,110, 97,109,101, 46, 46, 34, 32, 34, 46, 46, + 118, 97,114,110, 97,109,101, 41, 10, 9, 9, 9, 9, 9,101, + 32, 61, 32,118, 97,114,101, 10, 9, 9, 9, 9,101,110,100, + 10, 9, 9, 9,101,110,100, 10, 9, 9, 9,114,101,116,117, + 114,110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, + 41, 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, 10, 32, + 45, 45, 32,116,114,121, 32,116,121,112,101,100,101,102, 10, + 32,100,111, 10, 32, 32,108,111, 99, 97,108, 32, 98, 44,101, + 44,116,121,112,101,115, 32, 61, 32,115,116,114,102,105,110, + 100, 40,115, 44, 34, 94, 37,115, 42,116,121,112,101,100,101, + 102, 37,115, 37,115, 42, 40, 46, 45, 41, 37,115, 42, 59, 37, + 115, 42, 34, 41, 10, 32, 32,105,102, 32, 98, 32,116,104,101, + 110, 10, 32, 32, 32, 95, 99,117,114,114, 95, 99,111,100,101, + 32, 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, + 41, 10, 32, 32, 32, 84,121,112,101,100,101,102, 40,116,121, + 112,101,115, 41, 10, 32, 32, 32,114,101,116,117,114,110, 32, + 115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, + 32,101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, + 116,114,121, 32,118, 97,114,105, 97, 98,108,101, 10, 32,100, + 111, 10, 32, 32,108,111, 99, 97,108, 32, 98, 44,101, 44,100, + 101, 99,108, 32, 61, 32,115,116,114,102,105,110,100, 40,115, + 44, 34, 94, 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, 64, + 37,115, 37,119, 37,100, 37, 42, 38, 58, 60, 62, 44, 93, 42, + 91, 95, 37,119, 37,100, 93, 41, 37,115, 42, 59, 37,115, 42, + 34, 41, 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, 10, + 32, 32, 32, 95, 99,117,114,114, 95, 99,111,100,101, 32, 61, + 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, 10, + 10, 9,108,111, 99, 97,108, 32,108,105,115,116, 32, 61, 32, + 115,112,108,105,116, 95, 99, 95,116,111,107,101,110,115, 40, + 100,101, 99,108, 44, 32, 34, 44, 34, 41, 10, 9, 86, 97,114, + 105, 97, 98,108,101, 40,108,105,115,116, 91, 49, 93, 41, 10, + 9,105,102, 32,108,105,115,116, 46,110, 32, 62, 32, 49, 32, + 116,104,101,110, 10, 9, 9,108,111, 99, 97,108, 32, 95, 44, + 95, 44,116,121,112,101, 32, 61, 32,115,116,114,102,105,110, + 100, 40,108,105,115,116, 91, 49, 93, 44, 32, 34, 40, 46, 45, + 41, 37,115, 43, 40, 91, 94, 37,115, 93, 42, 41, 36, 34, 41, + 59, 10, 10, 9, 9,108,111, 99, 97,108, 32,105, 32, 61, 50, + 59, 10, 9, 9,119,104,105,108,101, 32,108,105,115,116, 91, + 105, 93, 32,100,111, 10, 9, 9, 9, 86, 97,114,105, 97, 98, + 108,101, 40,116,121,112,101, 46, 46, 34, 32, 34, 46, 46,108, + 105,115,116, 91,105, 93, 41, 10, 9, 9, 9,105, 61,105, 43, + 49, 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, 32, 32, + 32, 45, 45, 86, 97,114,105, 97, 98,108,101, 40,100,101, 99, + 108, 41, 10, 32, 32, 32,114,101,116,117,114,110, 32,115,116, + 114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, 32,101, + 110,100, 10, 32,101,110,100, 10, 10, 9, 45, 45, 32,116,114, + 121, 32,115,116,114,105,110,103, 10, 32,100,111, 10, 32, 32, + 108,111, 99, 97,108, 32, 98, 44,101, 44,100,101, 99,108, 32, + 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37, + 115, 42, 40, 91, 95, 37,119, 93, 63, 91, 95, 37,115, 37,119, + 37,100, 93, 45, 99,104, 97,114, 37,115, 43, 91, 95, 64, 37, + 119, 37,100, 93, 42, 37,115, 42, 37, 91, 37,115, 42, 37, 83, + 43, 37,115, 42, 37, 93, 41, 37,115, 42, 59, 37,115, 42, 34, + 41, 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, 10, 32, + 32, 32, 95, 99,117,114,114, 95, 99,111,100,101, 32, 61, 32, + 115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, 10, 32, + 32, 32, 86, 97,114,105, 97, 98,108,101, 40,100,101, 99,108, + 41, 10, 32, 32, 32,114,101,116,117,114,110, 32,115,116,114, + 115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, 32,101,110, + 100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32,116,114,121, + 32, 97,114,114, 97,121, 10, 32,100,111, 10, 32, 32,108,111, + 99, 97,108, 32, 98, 44,101, 44,100,101, 99,108, 32, 61, 32, + 115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, + 40, 91, 95, 37,119, 93, 91, 93, 91, 95, 64, 37,115, 37,119, + 37,100, 37, 42, 38, 58, 93, 42, 91, 93, 95, 37,119, 37,100, + 93, 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10, 32, 32,105, + 102, 32, 98, 32,116,104,101,110, 10, 32, 32, 32, 95, 99,117, + 114,114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, + 98, 40,115, 44, 98, 44,101, 41, 10, 32, 32, 32, 65,114,114, + 97,121, 40,100,101, 99,108, 41, 10, 32, 32, 32,114,101,116, + 117,114,110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, + 49, 41, 10, 32, 32,101,110,100, 10, 32,101,110,100, 10, 10, + 32, 45, 45, 32,110,111, 32,109, 97,116, 99,104,105,110,103, + 10, 32,105,102, 32,103,115,117, 98, 40,115, 44, 34, 37,115, + 37,115, 42, 34, 44, 34, 34, 41, 32,126, 61, 32, 34, 34, 32, + 116,104,101,110, 10, 32, 32, 95, 99,117,114,114, 95, 99,111, + 100,101, 32, 61, 32,115, 10, 32, 32,101,114,114,111,114, 40, + 34, 35,112, 97,114,115,101, 32,101,114,114,111,114, 34, 41, + 10, 32,101,108,115,101, 10, 32, 32,114,101,116,117,114,110, + 32, 34, 34, 10, 32,101,110,100, 10, 10,101,110,100, 10, 10, + 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 58,112, 97,114,115,101, 32, + 40,115, 41, 10, 10, 9, 45, 45,115,101,108,102, 46, 99,117, + 114,114, 95,109,101,109, 98,101,114, 95, 97, 99, 99,101,115, + 115, 32, 61, 32,110,105,108, 10, 10, 32,119,104,105,108,101, + 32,115, 32,126, 61, 32, 39, 39, 32,100,111, 10, 32, 32,115, + 32, 61, 32,115,101,108,102, 58,100,111,112, 97,114,115,101, + 40,115, 41, 10, 32, 32,109,101,116,104,111,100,105,115,118, + 105,114,116,117, 97,108, 32, 61, 32,102, 97,108,115,101, 10, + 32,101,110,100, 10,101,110,100, 10, 10, 10, 45, 45, 32,112, + 114,111,112,101,114,116,121, 32,116,121,112,101,115, 10, 10, + 102,117,110, 99,116,105,111,110, 32,103,101,116, 95,112,114, + 111,112,101,114,116,121, 95,116,121,112,101, 40, 41, 10, 10, + 9,114,101,116,117,114,110, 32, 99,108, 97,115,115, 67,111, + 110,116, 97,105,110,101,114, 46, 99,117,114,114, 58,103,101, + 116, 95,112,114,111,112,101,114,116,121, 95,116,121,112,101, + 40, 41, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101, + 114, 58,115,101,116, 95,112,114,111,112,101,114,116,121, 95, + 116,121,112,101, 40,112,116,121,112,101, 41, 10, 9,112,116, + 121,112,101, 32, 61, 32,115,116,114,105,110,103, 46,103,115, + 117, 98, 40,112,116,121,112,101, 44, 32, 34, 94, 37,115, 42, + 34, 44, 32, 34, 34, 41, 10, 9,112,116,121,112,101, 32, 61, + 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,112,116, + 121,112,101, 44, 32, 34, 37,115, 42, 36, 34, 44, 32, 34, 34, + 41, 10, 10, 9,115,101,108,102, 46,112,114,111,112,101,114, + 116,121, 95,116,121,112,101, 32, 61, 32,112,116,121,112,101, + 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, + 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 58, + 103,101,116, 95,112,114,111,112,101,114,116,121, 95,116,121, + 112,101, 40, 41, 10, 9,114,101,116,117,114,110, 32,115,101, + 108,102, 46,112,114,111,112,101,114,116,121, 95,116,121,112, + 101, 32,111,114, 32, 40,115,101,108,102, 46,112, 97,114,101, + 110,116, 32, 97,110,100, 32,115,101,108,102, 46,112, 97,114, + 101,110,116, 58,103,101,116, 95,112,114,111,112,101,114,116, + 121, 95,116,121,112,101, 40, 41, 41, 32,111,114, 32, 34,100, + 101,102, 97,117,108,116, 34, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/container.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,112, 97, 99,107, 97, + 103,101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105, + 116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, 97, + 114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71, + 114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, + 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73,100, + 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111, + 100,101, 32,105,115, 32,102,114,101,101, 32,115,111,102,116, + 119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32,114, + 101,100,105,115,116,114,105, 98,117,116,101, 32,105,116, 32, + 97,110,100, 47,111,114, 32,109,111,100,105,102,121, 32,105, + 116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116,119, + 97,114,101, 32,112,114,111,118,105,100,101,100, 32,104,101, + 114,101,117,110,100,101,114, 32,105,115, 32,111,110, 32, 97, + 110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, + 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97,117, + 116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98,108, + 105,103, 97,116,105,111,110, 32,116,111, 32,112,114,111,118, + 105,100,101, 32,109, 97,105,110,116,101,110, 97,110, 99,101, + 44, 32,115,117,112,112,111,114,116, 44, 32,117,112,100, 97, + 116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101, + 109,101,110,116,115, 44, 32,111,114, 32,109,111,100,105,102, + 105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 10, 45, 45, + 32, 80, 97, 99,107, 97,103,101, 32, 99,108, 97,115,115, 10, + 45, 45, 32, 82,101,112,114,101,115,101,110,116,115, 32,116, + 104,101, 32,119,104,111,108,101, 32,112, 97, 99,107, 97,103, + 101, 32, 98,101,105,110,103, 32, 98,111,117,110,100, 46, 10, + 45, 45, 32, 84,104,101, 32,102,111,108,108,111,119,105,110, + 103, 32,102,105,101,108,100,115, 32, 97,114,101, 32,115,116, + 111,114,101,100, 58, 10, 45, 45, 32, 32, 32, 32,123,105,125, + 32, 61, 32,108,105,115,116, 32,111,102, 32,111, 98,106,101, + 99,116,115, 32,105,110, 32,116,104,101, 32,112, 97, 99,107, + 97,103,101, 46, 10, 99,108, 97,115,115, 80, 97, 99,107, 97, + 103,101, 32, 61, 32,123, 10, 32, 99,108, 97,115,115,116,121, + 112,101, 32, 61, 32, 39,112, 97, 99,107, 97,103,101, 39, 10, + 125, 10, 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 46, + 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97,115,115, + 80, 97, 99,107, 97,103,101, 10,115,101,116,109,101,116, 97, + 116, 97, 98,108,101, 40, 99,108, 97,115,115, 80, 97, 99,107, + 97,103,101, 44, 99,108, 97,115,115, 67,111,110,116, 97,105, + 110,101,114, 41, 10, 10, 45, 45, 32, 80,114,105,110,116, 32, + 109,101,116,104,111,100, 10,102,117,110, 99,116,105,111,110, + 32, 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 58,112, + 114,105,110,116, 32, 40, 41, 10, 32,112,114,105,110,116, 40, + 34, 80, 97, 99,107, 97,103,101, 58, 32, 34, 46, 46,115,101, + 108,102, 46,110, 97,109,101, 41, 10, 32,108,111, 99, 97,108, + 32,105, 61, 49, 10, 32,119,104,105,108,101, 32,115,101,108, + 102, 91,105, 93, 32,100,111, 10, 32, 32,115,101,108,102, 91, + 105, 93, 58,112,114,105,110,116, 40, 34, 34, 44, 34, 34, 41, + 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, + 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, + 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 58,112,114, + 101,112,114,111, 99,101,115,115, 32, 40, 41, 10, 10, 32, 45, + 45, 32, 97,118,111,105,100, 32,112,114,101,112,114,111, 99, + 101,115,115,105,110,103, 32,101,109, 98,101,100,100,101,100, + 32, 76,117, 97, 32, 99,111,100,101, 10, 32,108,111, 99, 97, + 108, 32, 76, 32, 61, 32,123,125, 10, 32,115,101,108,102, 46, + 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108, + 102, 46, 99,111,100,101, 44, 34, 92,110, 37,115, 42, 37, 36, + 37, 91, 34, 44, 34, 92, 49, 34, 41, 32, 45, 45, 32,100,101, + 97,108, 32,119,105,116,104, 32,101,109, 98,101,100,100,101, + 100, 32,108,117, 97, 32, 99,111,100,101, 10, 32,115,101,108, + 102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115, + 101,108,102, 46, 99,111,100,101, 44, 34, 92,110, 37,115, 42, + 37, 36, 37, 93, 34, 44, 34, 92, 50, 34, 41, 10, 32,115,101, + 108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40, + 115,101,108,102, 46, 99,111,100,101, 44, 34, 40, 37, 98, 92, + 49, 92, 50, 41, 34, 44, 32, 32, 32, 32, 32, 32, 32,102,117, + 110, 99,116,105,111,110, 32, 40, 99, 41, 10, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,116,105, + 110,115,101,114,116, 40, 76, 44, 99, 41, 10, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,114,101, + 116,117,114,110, 32, 34, 92,110, 35, 91, 34, 46, 46,103,101, + 116,110, 40, 76, 41, 46, 46, 34, 93, 35, 34, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,101,110, + 100, 41, 10, 32, 45, 45, 32, 97,118,111,105,100, 32,112,114, + 101,112,114,111, 99,101,115,115,105,110,103, 32,101,109, 98, + 101,100,100,101,100, 32, 67, 32, 99,111,100,101, 10, 32,108, + 111, 99, 97,108, 32, 67, 32, 61, 32,123,125, 10, 32,115,101, + 108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40, + 115,101,108,102, 46, 99,111,100,101, 44, 34, 92,110, 37,115, + 42, 37, 36, 37, 60, 34, 44, 34, 92, 51, 34, 41, 32, 45, 45, + 32,100,101, 97,108, 32,119,105,116,104, 32,101,109, 98,101, + 100,100,101,100, 32, 67, 32, 99,111,100,101, 10, 32,115,101, + 108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40, + 115,101,108,102, 46, 99,111,100,101, 44, 34, 92,110, 37,115, + 42, 37, 36, 37, 62, 34, 44, 34, 92, 52, 34, 41, 10, 32,115, + 101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, + 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 40, 37, 98, + 92, 51, 92, 52, 41, 34, 44, 32, 32, 32, 32, 32, 32, 32,102, + 117,110, 99,116,105,111,110, 32, 40, 99, 41, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,116, + 105,110,115,101,114,116, 40, 67, 44, 99, 41, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,114, + 101,116,117,114,110, 32, 34, 92,110, 35, 60, 34, 46, 46,103, + 101,116,110, 40, 67, 41, 46, 46, 34, 62, 35, 34, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,101, + 110,100, 41, 10, 32, 45, 45, 32, 97,118,111,105,100, 32,112, + 114,101,112,114,111, 99,101,115,115,105,110,103, 32,101,109, + 98,101,100,100,101,100, 32, 67, 32, 99,111,100,101, 10, 32, + 115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, + 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 92,110, + 37,115, 42, 37, 36, 37,123, 34, 44, 34, 92, 53, 34, 41, 32, + 45, 45, 32,100,101, 97,108, 32,119,105,116,104, 32,101,109, + 98,101,100,100,101,100, 32, 67, 32, 99,111,100,101, 10, 32, + 115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, + 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 92,110, + 37,115, 42, 37, 36, 37,125, 34, 44, 34, 92, 54, 34, 41, 10, + 32,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115, + 117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 40, + 37, 98, 92, 53, 92, 54, 41, 34, 44, 32, 32, 32, 32, 32, 32, + 32,102,117,110, 99,116,105,111,110, 32, 40, 99, 41, 10, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,116,105,110,115,101,114,116, 40, 67, 44, 99, 41, 10, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,114,101,116,117,114,110, 32, 34, 92,110, 35, 60, 34, 46, + 46,103,101,116,110, 40, 67, 41, 46, 46, 34, 62, 35, 34, 10, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,101,110,100, 41, 10, 10, 32, 45, 45,115,101,108,102, 46, + 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108, + 102, 46, 99,111,100,101, 44, 34, 92,110, 37,115, 42, 35, 91, + 94,100, 93, 91, 94, 92,110, 93, 42, 92,110, 34, 44, 32, 34, + 92,110, 92,110, 34, 41, 32, 45, 45, 32,101,108,105,109,105, + 110, 97,116,101, 32,112,114,101,112,114,111, 99,101,115,115, + 111,114, 32,100,105,114,101, 99,116,105,118,101,115, 32,116, + 104, 97,116, 32,100,111,110, 39,116, 32,115,116, 97,114,116, + 32,119,105,116,104, 32, 39,100, 39, 10, 32,115,101,108,102, + 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101, + 108,102, 46, 99,111,100,101, 44, 34, 92,110, 91, 32, 92,116, + 93, 42, 35, 91, 32, 92,116, 93, 42, 91, 94,100, 37, 60, 37, + 91, 93, 34, 44, 32, 34, 92,110, 47, 47, 34, 41, 32, 45, 45, + 32,101,108,105,109,105,110, 97,116,101, 32,112,114,101,112, + 114,111, 99,101,115,115,111,114, 32,100,105,114,101, 99,116, + 105,118,101,115, 32,116,104, 97,116, 32,100,111,110, 39,116, + 32,115,116, 97,114,116, 32,119,105,116,104, 32, 39,100, 39, + 10, 10, 32, 45, 45, 32, 97,118,111,105,100, 32,112,114,101, + 112,114,111, 99,101,115,115,105,110,103, 32,118,101,114, 98, + 97,116,105,109, 32,108,105,110,101,115, 10, 32,108,111, 99, + 97,108, 32, 86, 32, 61, 32,123,125, 10, 32,115,101,108,102, + 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101, + 108,102, 46, 99,111,100,101, 44, 34, 92,110, 40, 37,115, 42, + 37, 36, 91, 94, 37, 91, 37, 93, 93, 91, 94, 92,110, 93, 42, + 41, 34, 44,102,117,110, 99,116,105,111,110, 32, 40,118, 41, + 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32,116,105,110,115,101,114,116, 40, 86, 44,118, 41, + 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32,114,101,116,117,114,110, 32, 34, 92,110, 35, 34, + 46, 46,103,101,116,110, 40, 86, 41, 46, 46, 34, 35, 34, 10, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,101,110,100, 41, 10, 10, 32, 45, 45, 32,112,101,114,102, + 111,114,109, 32,103,108,111, 98, 97,108, 32,115,117, 98,115, + 116,105,116,117,116,105,111,110, 10, 10, 32,115,101,108,102, + 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101, + 108,102, 46, 99,111,100,101, 44, 34, 40, 47, 47, 91, 94, 92, + 110, 93, 42, 41, 34, 44, 34, 34, 41, 32, 32, 32, 32, 32, 45, + 45, 32,101,108,105,109,105,110, 97,116,101, 32, 67, 43, 43, + 32, 99,111,109,109,101,110,116,115, 10, 32,115,101,108,102, + 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101, + 108,102, 46, 99,111,100,101, 44, 34, 47, 37, 42, 34, 44, 34, + 92, 49, 34, 41, 10, 32,115,101,108,102, 46, 99,111,100,101, + 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111, + 100,101, 44, 34, 37, 42, 47, 34, 44, 34, 92, 50, 34, 41, 10, + 32,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115, + 117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 37, + 98, 92, 49, 92, 50, 34, 44, 34, 34, 41, 10, 32,115,101,108, + 102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115, + 101,108,102, 46, 99,111,100,101, 44, 34, 92, 49, 34, 44, 34, + 47, 37, 42, 34, 41, 10, 32,115,101,108,102, 46, 99,111,100, + 101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99, + 111,100,101, 44, 34, 92, 50, 34, 44, 34, 37, 42, 47, 34, 41, + 10, 32,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103, + 115,117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, + 37,115, 42, 64, 37,115, 42, 34, 44, 34, 64, 34, 41, 32, 45, + 45, 32,101,108,105,109,105,110, 97,116,101, 32,115,112, 97, + 99,101,115, 32, 98,101,115,105,100,101, 32, 64, 10, 32,115, + 101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, + 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 37,115, 63, + 105,110,108,105,110,101, 40, 37,115, 41, 34, 44, 34, 37, 49, + 34, 41, 32, 45, 45, 32,101,108,105,109,105,110, 97,116,101, + 32, 39,105,110,108,105,110,101, 39, 32,107,101,121,119,111, + 114,100, 10, 32, 45, 45,115,101,108,102, 46, 99,111,100,101, + 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111, + 100,101, 44, 34, 37,115, 63,101,120,116,101,114,110, 40, 37, + 115, 41, 34, 44, 34, 37, 49, 34, 41, 32, 45, 45, 32,101,108, + 105,109,105,110, 97,116,101, 32, 39,101,120,116,101,114,110, + 39, 32,107,101,121,119,111,114,100, 10, 32, 45, 45,115,101, + 108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40, + 115,101,108,102, 46, 99,111,100,101, 44, 34, 37,115, 63,118, + 105,114,116,117, 97,108, 40, 37,115, 41, 34, 44, 34, 37, 49, + 34, 41, 32, 45, 45, 32,101,108,105,109,105,110, 97,116,101, + 32, 39,118,105,114,116,117, 97,108, 39, 32,107,101,121,119, + 111,114,100, 10, 32, 45, 45,115,101,108,102, 46, 99,111,100, + 101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99, + 111,100,101, 44, 34,112,117, 98,108,105, 99, 58, 34, 44, 34, + 34, 41, 32, 45, 45, 32,101,108,105,109,105,110, 97,116,101, + 32, 39,112,117, 98,108,105, 99, 58, 39, 32,107,101,121,119, + 111,114,100, 10, 32,115,101,108,102, 46, 99,111,100,101, 32, + 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111,100, + 101, 44, 34, 40, 91, 94, 37,119, 95, 93, 41,118,111,105,100, + 37,115, 42, 37, 42, 34, 44, 34, 37, 49, 95,117,115,101,114, + 100, 97,116, 97, 32, 34, 41, 32, 45, 45, 32,115,117, 98,115, + 116,105,116,117,116,101, 32, 39,118,111,105,100, 42, 39, 10, + 32,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115, + 117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 40, + 91, 94, 37,119, 95, 93, 41,118,111,105,100, 37,115, 42, 37, + 42, 34, 44, 34, 37, 49, 95,117,115,101,114,100, 97,116, 97, + 32, 34, 41, 32, 45, 45, 32,115,117, 98,115,116,105,116,117, + 116,101, 32, 39,118,111,105,100, 42, 39, 10, 32,115,101,108, + 102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115, + 101,108,102, 46, 99,111,100,101, 44, 34, 40, 91, 94, 37,119, + 95, 93, 41, 99,104, 97,114, 37,115, 42, 37, 42, 34, 44, 34, + 37, 49, 95, 99,115,116,114,105,110,103, 32, 34, 41, 32, 32, + 45, 45, 32,115,117, 98,115,116,105,116,117,116,101, 32, 39, + 99,104, 97,114, 42, 39, 10, 32,115,101,108,102, 46, 99,111, + 100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, + 99,111,100,101, 44, 34, 40, 91, 94, 37,119, 95, 93, 41,108, + 117, 97, 95, 83,116, 97,116,101, 37,115, 42, 37, 42, 34, 44, + 34, 37, 49, 95,108,115,116, 97,116,101, 32, 34, 41, 32, 32, + 45, 45, 32,115,117, 98,115,116,105,116,117,116,101, 32, 39, + 108,117, 97, 95, 83,116, 97,116,101, 42, 39, 10, 10, 32, 45, + 45, 32,114,101,115,116,111,114,101, 32,101,109, 98,101,100, + 100,101,100, 32, 76,117, 97, 32, 99,111,100,101, 10, 32,115, + 101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, + 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 37, 35, 37, + 91, 40, 37,100, 43, 41, 37, 93, 37, 35, 34, 44,102,117,110, + 99,116,105,111,110, 32, 40,110, 41, 10, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,114,101,116,117, + 114,110, 32, 76, 91,116,111,110,117,109, 98,101,114, 40,110, + 41, 93, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32,101,110,100, 41, 10, 32, 45, 45, 32,114,101,115,116, + 111,114,101, 32,101,109, 98,101,100,100,101,100, 32, 67, 32, + 99,111,100,101, 10, 32,115,101,108,102, 46, 99,111,100,101, + 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111, + 100,101, 44, 34, 37, 35, 37, 60, 40, 37,100, 43, 41, 37, 62, + 37, 35, 34, 44,102,117,110, 99,116,105,111,110, 32, 40,110, + 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32,114,101,116,117,114,110, 32, 67, 91,116,111,110,117, + 109, 98,101,114, 40,110, 41, 93, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32,101,110,100, 41, 10, 32, 45, + 45, 32,114,101,115,116,111,114,101, 32,118,101,114, 98, 97, + 116,105,109, 32,108,105,110,101,115, 10, 32,115,101,108,102, + 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101, + 108,102, 46, 99,111,100,101, 44, 34, 37, 35, 40, 37,100, 43, + 41, 37, 35, 34, 44,102,117,110, 99,116,105,111,110, 32, 40, + 110, 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,114, + 101,116,117,114,110, 32, 86, 91,116,111,110,117,109, 98,101, + 114, 40,110, 41, 93, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,101,110,100, 41, 10, 10, 32,115,101,108,102, 46, 99,111, + 100,101, 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, + 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 32, 34, 92, + 110, 37,115, 42, 37, 36, 40, 91, 94, 92,110, 93, 43, 41, 34, + 44, 32,102,117,110, 99,116,105,111,110, 32, 40,108, 41, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 86,101,114, 98, + 97,116,105,109, 40,108, 46, 46, 34, 92,110, 34, 41, 10, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,114,101,116,117,114, + 110, 32, 34, 92,110, 34, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 32, 32,101,110,100, 41, 10,101,110,100, 10, 10, 45, + 45, 32,116,114, 97,110,115,108, 97,116,101, 32,118,101,114, + 98, 97,116,105,109, 10,102,117,110, 99,116,105,111,110, 32, + 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 58,112,114, + 101, 97,109, 98,108,101, 32, 40, 41, 10, 32,111,117,116,112, + 117,116, 40, 39, 47, 42, 92,110, 39, 41, 10, 32,111,117,116, + 112,117,116, 40, 39, 42, 42, 32, 76,117, 97, 32, 98,105,110, + 100,105,110,103, 58, 32, 39, 46, 46,115,101,108,102, 46,110, + 97,109,101, 46, 46, 39, 92,110, 39, 41, 10, 32,111,117,116, + 112,117,116, 40, 39, 42, 42, 32, 71,101,110,101,114, 97,116, + 101,100, 32, 97,117,116,111,109, 97,116,105, 99, 97,108,108, + 121, 32, 98,121, 32, 39, 46, 46, 84, 79, 76, 85, 65, 95, 86, + 69, 82, 83, 73, 79, 78, 46, 46, 39, 32,111,110, 32, 39, 46, + 46,100, 97,116,101, 40, 41, 46, 46, 39, 46, 92,110, 39, 41, + 10, 32,111,117,116,112,117,116, 40, 39, 42, 47, 92,110, 92, + 110, 39, 41, 10, 10, 9,111,117,116,112,117,116, 40, 39, 35, + 105,102,110,100,101,102, 32, 95, 95, 99,112,108,117,115,112, + 108,117,115, 92,110, 39, 41, 10, 9,111,117,116,112,117,116, + 40, 39, 35,105,110, 99,108,117,100,101, 32, 34,115,116,100, + 108,105, 98, 46,104, 34, 92,110, 39, 41, 10, 9,111,117,116, + 112,117,116, 40, 39, 35,101,110,100,105,102, 92,110, 39, 41, + 10, 9,111,117,116,112,117,116, 40, 39, 35,105,110, 99,108, + 117,100,101, 32, 34,115,116,114,105,110,103, 46,104, 34, 92, + 110, 92,110, 39, 41, 10, 32,111,117,116,112,117,116, 40, 39, + 35,105,110, 99,108,117,100,101, 32, 34,116,111,108,117, 97, + 43, 43, 46,104, 34, 92,110, 92,110, 39, 41, 10, 10, 32,105, + 102, 32,110,111,116, 32,102,108, 97,103,115, 46,104, 32,116, + 104,101,110, 10, 32, 32,111,117,116,112,117,116, 40, 39, 47, + 42, 32, 69,120,112,111,114,116,101,100, 32,102,117,110, 99, + 116,105,111,110, 32, 42, 47, 39, 41, 10, 32, 32,111,117,116, + 112,117,116, 40, 39, 84, 79, 76, 85, 65, 95, 65, 80, 73, 32, + 105,110,116, 32, 32,116,111,108,117, 97, 95, 39, 46, 46,115, + 101,108,102, 46,110, 97,109,101, 46, 46, 39, 95,111,112,101, + 110, 32, 40,108,117, 97, 95, 83,116, 97,116,101, 42, 32,116, + 111,108,117, 97, 95, 83, 41, 59, 39, 41, 10, 32, 32,111,117, + 116,112,117,116, 40, 39, 92,110, 39, 41, 10, 32,101,110,100, + 10, 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119, + 104,105,108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, + 10, 32, 32,115,101,108,102, 91,105, 93, 58,112,114,101, 97, + 109, 98,108,101, 40, 41, 10, 32, 32,105, 32, 61, 32,105, 43, + 49, 10, 32,101,110,100, 10, 10, 9,105,102, 32,115,101,108, + 102, 58,114,101,113,117,105,114,101, 99,111,108,108,101, 99, + 116,105,111,110, 40, 95, 99,111,108,108,101, 99,116, 41, 32, + 116,104,101,110, 10, 9, 9,111,117,116,112,117,116, 40, 39, + 92,110, 39, 41, 10, 9, 9,111,117,116,112,117,116, 40, 39, + 47, 42, 32,102,117,110, 99,116,105,111,110, 32,116,111, 32, + 114,101,108,101, 97,115,101, 32, 99,111,108,108,101, 99,116, + 101,100, 32,111, 98,106,101, 99,116, 32,118,105, 97, 32,100, + 101,115,116,114,117, 99,116,111,114, 32, 42, 47, 39, 41, 10, + 9, 9,111,117,116,112,117,116, 40, 39, 35,105,102,100,101, + 102, 32, 95, 95, 99,112,108,117,115,112,108,117,115, 92,110, + 39, 41, 10, 9, 9,102,111,114, 32,105, 44,118, 32,105,110, + 32,112, 97,105,114,115, 40, 95, 99,111,108,108,101, 99,116, + 41, 32,100,111, 10, 9, 9, 32,111,117,116,112,117,116, 40, + 39, 92,110,115,116, 97,116,105, 99, 32,105,110,116, 32, 39, + 46, 46,118, 46, 46, 39, 32, 40,108,117, 97, 95, 83,116, 97, + 116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 39, 41, 10, + 9, 9, 9,111,117,116,112,117,116, 40, 39,123, 39, 41, 10, + 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, 39, 46, 46, + 105, 46, 46, 39, 42, 32,115,101,108,102, 32, 61, 32, 40, 39, + 46, 46,105, 46, 46, 39, 42, 41, 32,116,111,108,117, 97, 95, + 116,111,117,115,101,114,116,121,112,101, 40,116,111,108,117, + 97, 95, 83, 44, 49, 44, 48, 41, 59, 39, 41, 10, 9, 9, 9, + 111,117,116,112,117,116, 40, 39, 9, 77,116,111,108,117, 97, + 95,100,101,108,101,116,101, 40,115,101,108,102, 41, 59, 39, + 41, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, 9,114, + 101,116,117,114,110, 32, 48, 59, 39, 41, 10, 9, 9, 9,111, + 117,116,112,117,116, 40, 39,125, 39, 41, 10, 9, 9,101,110, + 100, 10, 9, 9,111,117,116,112,117,116, 40, 39, 35,101,110, + 100,105,102, 92,110, 92,110, 39, 41, 10, 9,101,110,100, 10, + 10, 32,111,117,116,112,117,116, 40, 39, 92,110, 39, 41, 10, + 32,111,117,116,112,117,116, 40, 39, 47, 42, 32,102,117,110, + 99,116,105,111,110, 32,116,111, 32,114,101,103,105,115,116, + 101,114, 32,116,121,112,101, 32, 42, 47, 39, 41, 10, 32,111, + 117,116,112,117,116, 40, 39,115,116, 97,116,105, 99, 32,118, + 111,105,100, 32,116,111,108,117, 97, 95,114,101,103, 95,116, + 121,112,101,115, 32, 40,108,117, 97, 95, 83,116, 97,116,101, + 42, 32,116,111,108,117, 97, 95, 83, 41, 39, 41, 10, 32,111, + 117,116,112,117,116, 40, 39,123, 39, 41, 10, 10, 9,105,102, + 32,102,108, 97,103,115, 46,116, 32,116,104,101,110, 10, 9, + 9,111,117,116,112,117,116, 40, 34, 35,105,102,110,100,101, + 102, 32, 77,116,111,108,117, 97, 95,116,121,112,101,105,100, + 92,110, 35,100,101,102,105,110,101, 32, 77,116,111,108,117, + 97, 95,116,121,112,101,105,100, 40, 76, 44, 84, 73, 44, 84, + 41, 92,110, 35,101,110,100,105,102, 92,110, 34, 41, 10, 9, + 101,110,100, 10, 9,102,111,114,101, 97, 99,104, 40, 95,117, + 115,101,114,116,121,112,101, 44,102,117,110, 99,116,105,111, + 110, 40,110, 44,118, 41, 10, 9, 9,105,102, 32, 40,110,111, + 116, 32, 95,103,108,111, 98, 97,108, 95, 99,108, 97,115,115, + 101,115, 91,118, 93, 41, 32,111,114, 32, 95,103,108,111, 98, + 97,108, 95, 99,108, 97,115,115,101,115, 91,118, 93, 58, 99, + 104,101, 99,107, 95,112,117, 98,108,105, 99, 95, 97, 99, 99, + 101,115,115, 40, 41, 32,116,104,101,110, 10, 9, 9, 9,111, + 117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,117, + 115,101,114,116,121,112,101, 40,116,111,108,117, 97, 95, 83, + 44, 34, 39, 44,118, 44, 39, 34, 41, 59, 39, 41, 10, 9, 9, + 9,105,102, 32,102,108, 97,103,115, 46,116, 32,116,104,101, + 110, 10, 9, 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, + 77,116,111,108,117, 97, 95,116,121,112,101,105,100, 40,116, + 111,108,117, 97, 95, 83, 44,116,121,112,101,105,100, 40, 39, + 44,118, 44, 39, 41, 44, 32, 34, 39, 44,118, 44, 39, 34, 41, + 59, 39, 41, 10, 9, 9, 9,101,110,100, 10, 9, 9,101,110, + 100, 10, 9, 32,101,110,100, 41, 10, 32,111,117,116,112,117, + 116, 40, 39,125, 39, 41, 10, 32,111,117,116,112,117,116, 40, + 39, 92,110, 39, 41, 10,101,110,100, 10, 10, 45, 45, 32,114, + 101,103,105,115,116,101,114, 32,112, 97, 99,107, 97,103,101, + 10, 45, 45, 32,119,114,105,116,101, 32,112, 97, 99,107, 97, + 103,101, 32,111,112,101,110, 32,102,117,110, 99,116,105,111, + 110, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 80, 97, 99,107, 97,103,101, 58,114,101,103,105,115,116, + 101,114, 32, 40,112,114,101, 41, 10, 32,112,114,101, 32, 61, + 32,112,114,101, 32,111,114, 32, 39, 39, 10, 32,112,117,115, + 104, 40,115,101,108,102, 41, 10, 32,111,117,116,112,117,116, + 40,112,114,101, 46, 46, 34, 47, 42, 32, 79,112,101,110, 32, + 102,117,110, 99,116,105,111,110, 32, 42, 47, 34, 41, 10, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 34, 84, 79, + 76, 85, 65, 95, 65, 80, 73, 32,105,110,116, 32,116,111,108, + 117, 97, 95, 34, 46, 46,115,101,108,102, 46,110, 97,109,101, + 46, 46, 34, 95,111,112,101,110, 32, 40,108,117, 97, 95, 83, + 116, 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 34, + 41, 10, 32,111,117,116,112,117,116, 40,112,114,101, 46, 46, + 34,123, 34, 41, 10, 32,111,117,116,112,117,116, 40,112,114, + 101, 46, 46, 34, 32,116,111,108,117, 97, 95,111,112,101,110, + 40,116,111,108,117, 97, 95, 83, 41, 59, 34, 41, 10, 32,111, + 117,116,112,117,116, 40,112,114,101, 46, 46, 34, 32,116,111, + 108,117, 97, 95,114,101,103, 95,116,121,112,101,115, 40,116, + 111,108,117, 97, 95, 83, 41, 59, 34, 41, 10, 32,111,117,116, + 112,117,116, 40,112,114,101, 46, 46, 34, 32,116,111,108,117, + 97, 95,109,111,100,117,108,101, 40,116,111,108,117, 97, 95, + 83, 44, 78, 85, 76, 76, 44, 34, 44,115,101,108,102, 58,104, + 97,115,118, 97,114, 40, 41, 44, 34, 41, 59, 34, 41, 10, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 34, 32,116, + 111,108,117, 97, 95, 98,101,103,105,110,109,111,100,117,108, + 101, 40,116,111,108,117, 97, 95, 83, 44, 78, 85, 76, 76, 41, + 59, 34, 41, 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, + 32,119,104,105,108,101, 32,115,101,108,102, 91,105, 93, 32, + 100,111, 10, 32, 32,115,101,108,102, 91,105, 93, 58,114,101, + 103,105,115,116,101,114, 40,112,114,101, 46, 46, 34, 32, 32, + 34, 41, 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101, + 110,100, 10, 32,111,117,116,112,117,116, 40,112,114,101, 46, + 46, 34, 32,116,111,108,117, 97, 95,101,110,100,109,111,100, + 117,108,101, 40,116,111,108,117, 97, 95, 83, 41, 59, 34, 41, + 10, 32,111,117,116,112,117,116, 40,112,114,101, 46, 46, 34, + 32,114,101,116,117,114,110, 32, 49, 59, 34, 41, 10, 32,111, + 117,116,112,117,116, 40,112,114,101, 46, 46, 34,125, 34, 41, + 10, 10, 32,111,117,116,112,117,116, 40, 34, 92,110, 92,110, + 34, 41, 10, 32,111,117,116,112,117,116, 40, 34, 35,105,102, + 32,100,101,102,105,110,101,100, 40, 76, 85, 65, 95, 86, 69, + 82, 83, 73, 79, 78, 95, 78, 85, 77, 41, 32, 38, 38, 32, 76, + 85, 65, 95, 86, 69, 82, 83, 73, 79, 78, 95, 78, 85, 77, 32, + 62, 61, 32, 53, 48, 49, 92,110, 34, 41, 59, 10, 32,111,117, + 116,112,117,116, 40,112,114,101, 46, 46, 34, 84, 79, 76, 85, + 65, 95, 65, 80, 73, 32,105,110,116, 32,108,117, 97,111,112, + 101,110, 95, 34, 46, 46,115,101,108,102, 46,110, 97,109,101, + 46, 46, 34, 32, 40,108,117, 97, 95, 83,116, 97,116,101, 42, + 32,116,111,108,117, 97, 95, 83, 41, 32,123, 34, 41, 10, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 34, 32,114, + 101,116,117,114,110, 32,116,111,108,117, 97, 95, 34, 46, 46, + 115,101,108,102, 46,110, 97,109,101, 46, 46, 34, 95,111,112, + 101,110, 40,116,111,108,117, 97, 95, 83, 41, 59, 34, 41, 10, + 32,111,117,116,112,117,116, 40,112,114,101, 46, 46, 34,125, + 59, 34, 41, 10, 32,111,117,116,112,117,116, 40, 34, 35,101, + 110,100,105,102, 92,110, 92,110, 34, 41, 10, 10, 9,112,111, + 112, 40, 41, 10,101,110,100, 10, 10, 45, 45, 32,119,114,105, + 116,101, 32,104,101, 97,100,101,114, 32,102,105,108,101, 10, + 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 80, + 97, 99,107, 97,103,101, 58,104,101, 97,100,101,114, 32, 40, + 41, 10, 32,111,117,116,112,117,116, 40, 39, 47, 42, 92,110, + 39, 41, 32,111,117,116,112,117,116, 40, 39, 42, 42, 32, 76, + 117, 97, 32, 98,105,110,100,105,110,103, 58, 32, 39, 46, 46, + 115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 92,110, 39, + 41, 10, 32,111,117,116,112,117,116, 40, 39, 42, 42, 32, 71, + 101,110,101,114, 97,116,101,100, 32, 97,117,116,111,109, 97, + 116,105, 99, 97,108,108,121, 32, 98,121, 32, 39, 46, 46, 84, + 79, 76, 85, 65, 95, 86, 69, 82, 83, 73, 79, 78, 46, 46, 39, + 32,111,110, 32, 39, 46, 46,100, 97,116,101, 40, 41, 46, 46, + 39, 46, 92,110, 39, 41, 10, 32,111,117,116,112,117,116, 40, + 39, 42, 47, 92,110, 92,110, 39, 41, 10, 10, 32,105,102, 32, + 110,111,116, 32,102,108, 97,103,115, 46,104, 32,116,104,101, + 110, 10, 32, 32,111,117,116,112,117,116, 40, 39, 47, 42, 32, + 69,120,112,111,114,116,101,100, 32,102,117,110, 99,116,105, + 111,110, 32, 42, 47, 39, 41, 10, 32, 32,111,117,116,112,117, + 116, 40, 39, 84, 79, 76, 85, 65, 95, 65, 80, 73, 32,105,110, + 116, 32, 32,116,111,108,117, 97, 95, 39, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 39, 95,111,112,101,110, 32, + 40,108,117, 97, 95, 83,116, 97,116,101, 42, 32,116,111,108, + 117, 97, 95, 83, 41, 59, 39, 41, 10, 32, 32,111,117,116,112, + 117,116, 40, 39, 92,110, 39, 41, 10, 32,101,110,100, 10,101, + 110,100, 10, 10, 45, 45, 32, 73,110,116,101,114,110, 97,108, + 32, 99,111,110,115,116,114,117, 99,116,111,114, 10,102,117, + 110, 99,116,105,111,110, 32, 95, 80, 97, 99,107, 97,103,101, + 32, 40,115,101,108,102, 41, 10, 32,115,101,116,109,101,116, + 97,116, 97, 98,108,101, 40,115,101,108,102, 44, 99,108, 97, + 115,115, 80, 97, 99,107, 97,103,101, 41, 10, 32,114,101,116, + 117,114,110, 32,115,101,108,102, 10,101,110,100, 10, 10, 45, + 45, 32, 80, 97,114,115,101, 32, 67, 32,104,101, 97,100,101, + 114, 32,102,105,108,101, 32,119,105,116,104, 32,116,111,108, + 117, 97, 32,100,105,114,101, 99,116,105,118,101,115, 10, 45, + 45, 32, 42, 42, 42, 32, 84,104, 97,110,107,115, 32,116,111, + 32, 65,114,105,101,108, 32, 77, 97,110,122,117,114, 32,102, + 111,114, 32,102,105,120,105,110,103, 32, 98,117,103,115, 32, + 105,110, 32,110,101,115,116,101,100, 32,100,105,114,101, 99, + 116,105,118,101,115, 32, 42, 42, 42, 10,102,117,110, 99,116, + 105,111,110, 32,101,120,116,114, 97, 99,116, 95, 99,111,100, + 101, 40,102,110, 44,115, 41, 10, 9,108,111, 99, 97,108, 32, + 99,111,100,101, 32, 61, 32, 39, 92,110, 36, 35,105,110, 99, + 108,117,100,101, 32, 34, 39, 46, 46,102,110, 46, 46, 39, 34, + 92,110, 39, 10, 9,115, 61, 32, 34, 92,110, 34, 32, 46, 46, + 32,115, 32, 46, 46, 32, 34, 92,110, 34, 32, 45, 45, 32, 97, + 100,100, 32, 98,108, 97,110,107, 32,108,105,110,101,115, 32, + 97,115, 32,115,101,110,116,105,110,101,108,115, 10, 9,108, + 111, 99, 97,108, 32, 95, 44,101, 44, 99, 44,116, 32, 61, 32, + 115,116,114,102,105,110,100, 40,115, 44, 32, 34, 92,110, 40, + 91, 94, 92,110, 93, 45, 41, 91, 84,116, 93, 91, 79,111, 93, + 91, 76,108, 93, 91, 85,117, 93, 91, 65, 97, 93, 95, 40, 91, + 94, 37,115, 93, 42, 41, 91, 94, 92,110, 93, 42, 92,110, 34, + 41, 10, 9,119,104,105,108,101, 32,101, 32,100,111, 10, 9, + 9,116, 32, 61, 32,115,116,114,108,111,119,101,114, 40,116, + 41, 10, 9, 9,105,102, 32,116, 32, 61, 61, 32, 34, 98,101, + 103,105,110, 34, 32,116,104,101,110, 10, 9, 9, 9, 95, 44, + 101, 44, 99, 32, 61, 32,115,116,114,102,105,110,100, 40,115, + 44, 34, 40, 46, 45, 41, 92,110, 91, 94, 92,110, 93, 42, 91, + 84,116, 93, 91, 79,111, 93, 91, 76,108, 93, 91, 85,117, 93, + 91, 65, 97, 93, 95, 91, 69,101, 93, 91, 78,110, 93, 91, 68, + 100, 93, 91, 94, 92,110, 93, 42, 92,110, 34, 44,101, 41, 10, + 9, 9, 9,105,102, 32,110,111,116, 32,101, 32,116,104,101, + 110, 10, 9, 9, 9, 32,116,111,108,117, 97, 95,101,114,114, + 111,114, 40, 34, 85,110, 98, 97,108, 97,110, 99,101,100, 32, + 39,116,111,108,117, 97, 95, 98,101,103,105,110, 39, 32,100, + 105,114,101, 99,116,105,118,101, 32,105,110, 32,104,101, 97, + 100,101,114, 32,102,105,108,101, 34, 41, 10, 9, 9, 9,101, + 110,100, 10, 9, 9,101,110,100, 10, 9, 9, 99,111,100,101, + 32, 61, 32, 99,111,100,101, 32, 46, 46, 32, 99, 32, 46, 46, + 32, 34, 92,110, 34, 10, 9, 32, 95, 44,101, 44, 99, 44,116, + 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 32, 34, + 92,110, 40, 91, 94, 92,110, 93, 45, 41, 91, 84,116, 93, 91, + 79,111, 93, 91, 76,108, 93, 91, 85,117, 93, 91, 65, 97, 93, + 95, 40, 91, 94, 37,115, 93, 42, 41, 91, 94, 92,110, 93, 42, + 92,110, 34, 44,101, 41, 10, 9,101,110,100, 10, 9,114,101, + 116,117,114,110, 32, 99,111,100,101, 10,101,110,100, 10, 10, + 45, 45, 32, 67,111,110,115,116,114,117, 99,116,111,114, 10, + 45, 45, 32, 69,120,112,101, 99,116,115, 32,116,104,101, 32, + 112, 97, 99,107, 97,103,101, 32,110, 97,109,101, 44, 32,116, + 104,101, 32,102,105,108,101, 32,101,120,116,101,110,115,105, + 111,110, 44, 32, 97,110,100, 32,116,104,101, 32,102,105,108, + 101, 32,116,101,120,116, 46, 10,102,117,110, 99,116,105,111, + 110, 32, 80, 97, 99,107, 97,103,101, 32, 40,110, 97,109,101, + 44,102,110, 41, 10, 32,108,111, 99, 97,108, 32,101,120,116, + 32, 61, 32, 34,112,107,103, 34, 10, 10, 32, 45, 45, 32,111, + 112,101,110, 32,105,110,112,117,116, 32,102,105,108,101, 44, + 32,105,102, 32, 97,110,121, 10, 32,108,111, 99, 97,108, 32, + 115,116, 44,109,115,103, 10, 32,105,102, 32,102,110, 32,116, + 104,101,110, 10, 32, 32,115,116, 44, 32,109,115,103, 32, 61, + 32,114,101, 97,100,102,114,111,109, 40,102,108, 97,103,115, + 46,102, 41, 10, 32, 32,105,102, 32,110,111,116, 32,115,116, + 32,116,104,101,110, 10, 32, 32, 32,101,114,114,111,114, 40, + 39, 35, 39, 46, 46,109,115,103, 41, 10, 32, 32,101,110,100, + 10, 32, 32,108,111, 99, 97,108, 32, 95, 59, 32, 95, 44, 32, + 95, 44, 32,101,120,116, 32, 61, 32,115,116,114,102,105,110, + 100, 40,102,110, 44, 34, 46, 42, 37, 46, 40, 46, 42, 41, 36, + 34, 41, 10, 32,101,110,100, 10, 32,108,111, 99, 97,108, 32, + 99,111,100,101, 10, 32,105,102, 32,101,120,116, 32, 61, 61, + 32, 39,112,107,103, 39, 32,116,104,101,110, 10, 32, 32, 99, + 111,100,101, 32, 61, 32,112,114,101,112, 40,115,116, 41, 10, + 32,101,108,115,101, 10, 32, 32, 99,111,100,101, 32, 61, 32, + 34, 92,110, 34, 32, 46, 46, 32,114,101, 97,100, 40, 39, 42, + 97, 39, 41, 10, 32, 32,105,102, 32,101,120,116, 32, 61, 61, + 32, 39,104, 39, 32,111,114, 32,101,120,116, 32, 61, 61, 32, + 39,104,112,112, 39, 32,116,104,101,110, 10, 32, 32, 32, 99, + 111,100,101, 32, 61, 32,101,120,116,114, 97, 99,116, 95, 99, + 111,100,101, 40,102,110, 44, 99,111,100,101, 41, 10, 32, 32, + 101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, 99, + 108,111,115,101, 32,102,105,108,101, 10, 32,105,102, 32,102, + 110, 32,116,104,101,110, 10, 32, 32,114,101, 97,100,102,114, + 111,109, 40, 41, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, + 100,101, 97,108, 32,119,105,116,104, 32,105,110, 99,108,117, + 100,101, 32,100,105,114,101, 99,116,105,118,101, 10, 32,108, + 111, 99, 97,108, 32,110,115,117, 98,115,116, 10, 32,114,101, + 112,101, 97,116, 10, 32, 32, 99,111,100,101, 44,110,115,117, + 98,115,116, 32, 61, 32,103,115,117, 98, 40, 99,111,100,101, + 44, 39, 92,110, 37,115, 42, 37, 36, 40, 46, 41,102,105,108, + 101, 37,115, 42, 34, 40, 46, 45, 41, 34, 40, 91, 94, 92,110, + 93, 42, 41, 92,110, 39, 44, 10, 9, 9,102,117,110, 99,116, + 105,111,110, 32, 40,107,105,110,100, 44,102,110, 44,101,120, + 116,114, 97, 41, 10, 9, 9, 9,108,111, 99, 97,108, 32, 95, + 44, 32, 95, 44, 32,101,120,116, 32, 61, 32,115,116,114,102, + 105,110,100, 40,102,110, 44, 34, 46, 42, 37, 46, 40, 46, 42, + 41, 36, 34, 41, 10, 9, 9, 9,108,111, 99, 97,108, 32,102, + 112, 44,109,115,103, 32, 61, 32,111,112,101,110,102,105,108, + 101, 40,102,110, 44, 39,114, 39, 41, 10, 9, 9, 9,105,102, + 32,110,111,116, 32,102,112, 32,116,104,101,110, 10, 9, 9, + 9, 9,101,114,114,111,114, 40, 39, 35, 39, 46, 46,109,115, + 103, 46, 46, 39, 58, 32, 39, 46, 46,102,110, 41, 10, 9, 9, + 9,101,110,100, 10, 9, 9, 9,105,102, 32,107,105,110,100, + 32, 61, 61, 32, 39,112, 39, 32,116,104,101,110, 10, 9, 9, + 9, 9,108,111, 99, 97,108, 32,115, 32, 61, 32,112,114,101, + 112, 40,102,112, 41, 10, 9, 9, 9, 9, 99,108,111,115,101, + 102,105,108,101, 40,102,112, 41, 10, 9, 9, 9, 9,114,101, + 116,117,114,110, 32,115, 10, 9, 9, 9,101,110,100, 10, 9, + 9, 9,108,111, 99, 97,108, 32,115, 32, 61, 32,114,101, 97, + 100, 40,102,112, 44, 39, 42, 97, 39, 41, 10, 9, 9, 9, 99, + 108,111,115,101,102,105,108,101, 40,102,112, 41, 10, 9, 9, + 9,105,102, 32,107,105,110,100, 32, 61, 61, 32, 39, 99, 39, + 32,111,114, 32,107,105,110,100, 32, 61, 61, 32, 39,104, 39, + 32,116,104,101,110, 10, 9, 9, 9, 9,114,101,116,117,114, + 110, 32,101,120,116,114, 97, 99,116, 95, 99,111,100,101, 40, + 102,110, 44,115, 41, 10, 9, 9, 9,101,108,115,101,105,102, + 32,107,105,110,100, 32, 61, 61, 32, 39,108, 39, 32,116,104, + 101,110, 10, 9, 9, 9, 9,114,101,116,117,114,110, 32, 34, + 92,110, 36, 91, 45, 45, 35, 35, 34, 46, 46,102,110, 46, 46, + 34, 92,110, 34, 32, 46, 46, 32,115, 32, 46, 46, 32, 34, 92, + 110, 36, 93, 92,110, 34, 10, 9, 9, 9,101,108,115,101,105, + 102, 32,107,105,110,100, 32, 61, 61, 32, 39,105, 39, 32,116, + 104,101,110, 10, 9, 9, 9, 9,108,111, 99, 97,108, 32,116, + 32, 61, 32,123, 99,111,100,101, 61,115,125, 10, 9, 9, 9, + 9,101,120,116,114, 97, 32, 61, 32,115,116,114,105,110,103, + 46,103,115,117, 98, 40,101,120,116,114, 97, 44, 32, 34, 94, + 37,115, 42, 44, 37,115, 42, 34, 44, 32, 34, 34, 41, 10, 9, + 9, 9, 9,108,111, 99, 97,108, 32,112, 97,114,115, 32, 61, + 32,115,112,108,105,116, 95, 99, 95,116,111,107,101,110,115, + 40,101,120,116,114, 97, 44, 32, 34, 44, 34, 41, 10, 9, 9, + 9, 9,105,110, 99,108,117,100,101, 95,102,105,108,101, 95, + 104,111,111,107, 40,116, 44, 32,102,110, 44, 32,117,110,112, + 97, 99,107, 40,112, 97,114,115, 41, 41, 10, 9, 9, 9, 9, + 114,101,116,117,114,110, 32, 34, 92,110, 92,110, 34, 32, 46, + 46, 32,116, 46, 99,111,100,101, 10, 9, 9, 9,101,108,115, + 101, 10, 9, 9, 9, 9,101,114,114,111,114, 40, 39, 35, 73, + 110,118, 97,108,105,100, 32,105,110, 99,108,117,100,101, 32, + 100,105,114,101, 99,116,105,118,101, 32, 40,117,115,101, 32, + 36, 99,102,105,108,101, 44, 32, 36,112,102,105,108,101, 44, + 32, 36,108,102,105,108,101, 32,111,114, 32, 36,105,102,105, + 108,101, 41, 39, 41, 10, 9, 9, 9,101,110,100, 10, 9, 9, + 101,110,100, 41, 10, 32,117,110,116,105,108, 32,110,115,117, + 98,115,116, 61, 61, 48, 10, 10, 32, 45, 45, 32,100,101, 97, + 108, 32,119,105,116,104, 32,114,101,110, 97,109,105,110,103, + 32,100,105,114,101, 99,116,105,118,101, 10, 32,114,101,112, + 101, 97,116, 32, 45, 45, 32, 73, 32,100,111,110, 39,116, 32, + 107,110,111,119, 32,119,104,121, 32,116,104,105,115, 32,105, + 115, 32,110,101, 99,101,115, 97,114,121, 10, 9, 99,111,100, + 101, 44,110,115,117, 98,115,116, 32, 61, 32,103,115,117, 98, + 40, 99,111,100,101, 44, 39, 92,110, 37,115, 42, 37, 36,114, + 101,110, 97,109,105,110,103, 37,115, 42, 40, 46, 45, 41, 37, + 115, 42, 92,110, 39, 44, 32,102,117,110, 99,116,105,111,110, + 32, 40,114, 41, 32, 97,112,112,101,110,100,114,101,110, 97, + 109,105,110,103, 40,114, 41, 32,114,101,116,117,114,110, 32, + 34, 92,110, 34, 32,101,110,100, 41, 10, 32,117,110,116,105, + 108, 32,110,115,117, 98,115,116, 32, 61, 61, 32, 48, 10, 10, + 32,108,111, 99, 97,108, 32,116, 32, 61, 32, 95, 80, 97, 99, + 107, 97,103,101, 40, 95, 67,111,110,116, 97,105,110,101,114, + 123,110, 97,109,101, 61,110, 97,109,101, 44, 32, 99,111,100, + 101, 61, 99,111,100,101,125, 41, 10, 32,112,117,115,104, 40, + 116, 41, 10, 32,112,114,101,112,114,111, 99,101,115,115, 95, + 104,111,111,107, 40,116, 41, 10, 32,116, 58,112,114,101,112, + 114,111, 99,101,115,115, 40, 41, 10, 32,112,114,101,112, 97, + 114,115,101, 95,104,111,111,107, 40,116, 41, 10, 32,116, 58, + 112, 97,114,115,101, 40,116, 46, 99,111,100,101, 41, 10, 32, + 112,111,112, 40, 41, 10, 32,114,101,116,117,114,110, 32,116, + 10,101,110,100, 10, 10, 10,115,101,116,109,101,116, 97,116, + 97, 98,108,101, 40, 95,101,120,116,114, 97, 95,112, 97,114, + 97,109,101,116,101,114,115, 44, 32,123, 32, 95, 95,105,110, + 100,101,120, 32, 61, 32, 95, 71, 32,125, 41, 10, 10,102,117, + 110, 99,116,105,111,110, 32,112,114,101,112, 40,102,105,108, + 101, 41, 10, 10, 32, 32,108,111, 99, 97,108, 32, 99,104,117, + 110,107, 32, 61, 32,123, 39,108,111, 99, 97,108, 32, 95, 95, + 114,101,116, 32, 61, 32,123, 34, 92, 92,110, 34,125, 92,110, + 39,125, 10, 32, 32,102,111,114, 32,108,105,110,101, 32,105, + 110, 32,102,105,108,101, 58,108,105,110,101,115, 40, 41, 32, + 100,111, 10, 32, 32, 32, 32, 32,105,102, 32,115,116,114,105, + 110,103, 46,102,105,110,100, 40,108,105,110,101, 44, 32, 34, + 94, 35, 35, 34, 41, 32,116,104,101,110, 10, 32, 32, 32, 32, + 32, 32,116, 97, 98,108,101, 46,105,110,115,101,114,116, 40, + 99,104,117,110,107, 44, 32,115,116,114,105,110,103, 46,115, + 117, 98, 40,108,105,110,101, 44, 32, 51, 41, 32, 46, 46, 32, + 34, 92,110, 34, 41, 10, 32, 32, 32, 32, 32,101,108,115,101, + 10, 32, 32, 32, 32, 32, 32,108,111, 99, 97,108, 32,108, 97, + 115,116, 32, 61, 32, 49, 10, 32, 32, 32, 32, 32, 32,102,111, + 114, 32,116,101,120,116, 44, 32,101,120,112,114, 44, 32,105, + 110,100,101,120, 32,105,110, 32,115,116,114,105,110,103, 46, + 103,102,105,110,100, 40,108,105,110,101, 44, 32, 34, 40, 46, + 45, 41, 36, 40, 37, 98, 40, 41, 41, 40, 41, 34, 41, 32,100, + 111, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,108, 97,115,116, + 32, 61, 32,105,110,100,101,120, 10, 32, 32, 32, 32, 32, 32, + 32, 32,105,102, 32,116,101,120,116, 32,126, 61, 32, 34, 34, + 32,116,104,101,110, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32,116, 97, 98,108,101, 46,105,110,115,101,114,116, 40, 99, + 104,117,110,107, 44, 32,115,116,114,105,110,103, 46,102,111, + 114,109, 97,116, 40, 39,116, 97, 98,108,101, 46,105,110,115, + 101,114,116, 40, 95, 95,114,101,116, 44, 32, 37,113, 32, 41, + 39, 44, 32,116,101,120,116, 41, 41, 10, 32, 32, 32, 32, 32, + 32, 32, 32,101,110,100, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 116, 97, 98,108,101, 46,105,110,115,101,114,116, 40, 99,104, + 117,110,107, 44, 32,115,116,114,105,110,103, 46,102,111,114, + 109, 97,116, 40, 39,116, 97, 98,108,101, 46,105,110,115,101, + 114,116, 40, 95, 95,114,101,116, 44, 32, 37,115, 32, 41, 39, + 44, 32,101,120,112,114, 41, 41, 10, 32, 32, 32, 32, 32, 32, + 101,110,100, 10, 32, 32, 32, 32, 32, 32,116, 97, 98,108,101, + 46,105,110,115,101,114,116, 40, 99,104,117,110,107, 44, 32, + 115,116,114,105,110,103, 46,102,111,114,109, 97,116, 40, 39, + 116, 97, 98,108,101, 46,105,110,115,101,114,116, 40, 95, 95, + 114,101,116, 44, 32, 37,113, 41, 92,110, 39, 44, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32,115,116,114,105,110,103, + 46,115,117, 98, 40,108,105,110,101, 44, 32,108, 97,115,116, + 41, 46, 46, 34, 92,110, 34, 41, 41, 10, 32, 32, 32, 32,101, + 110,100, 10, 32, 32,101,110,100, 10, 32, 32,116, 97, 98,108, + 101, 46,105,110,115,101,114,116, 40, 99,104,117,110,107, 44, + 32, 39, 92,110,114,101,116,117,114,110, 32,116, 97, 98,108, + 101, 46, 99,111,110, 99, 97,116, 40, 95, 95,114,101,116, 41, + 92,110, 39, 41, 10, 32, 32,108,111, 99, 97,108, 32,102, 44, + 101, 32, 61, 32,108,111, 97,100,115,116,114,105,110,103, 40, + 116, 97, 98,108,101, 46, 99,111,110, 99, 97,116, 40, 99,104, + 117,110,107, 41, 41, 10, 32, 32,105,102, 32,101, 32,116,104, + 101,110, 10, 32, 32, 9,101,114,114,111,114, 40, 34, 35, 34, + 46, 46,101, 41, 10, 32, 32,101,110,100, 10, 32, 32,115,101, + 116,102,101,110,118, 40,102, 44, 32, 95,101,120,116,114, 97, + 95,112, 97,114, 97,109,101,116,101,114,115, 41, 10, 32, 32, + 114,101,116,117,114,110, 32,102, 40, 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/package.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,109,111,100,117,108, + 101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105,116, + 116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, 97,114, + 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71,114, + 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74, + 117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73,100, 58, + 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111,100, + 101, 32,105,115, 32,102,114,101,101, 32,115,111,102,116,119, + 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32,114,101, + 100,105,115,116,114,105, 98,117,116,101, 32,105,116, 32, 97, + 110,100, 47,111,114, 32,109,111,100,105,102,121, 32,105,116, + 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116,119, 97, + 114,101, 32,112,114,111,118,105,100,101,100, 32,104,101,114, + 101,117,110,100,101,114, 32,105,115, 32,111,110, 32, 97,110, + 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, 44, + 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97,117,116, + 104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98,108,105, + 103, 97,116,105,111,110, 32,116,111, 32,112,114,111,118,105, + 100,101, 32,109, 97,105,110,116,101,110, 97,110, 99,101, 44, + 32,115,117,112,112,111,114,116, 44, 32,117,112,100, 97,116, + 101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101,109, + 101,110,116,115, 44, 32,111,114, 32,109,111,100,105,102,105, + 99, 97,116,105,111,110,115, 46, 10, 10, 10, 10, 45, 45, 32, + 77,111,100,117,108,101, 32, 99,108, 97,115,115, 10, 45, 45, + 32, 82,101,112,114,101,115,101,110,116,115, 32,109,111,100, + 117,108,101, 46, 10, 45, 45, 32, 84,104,101, 32,102,111,108, + 108,111,119,105,110,103, 32,102,105,101,108,100,115, 32, 97, + 114,101, 32,115,116,111,114,101,100, 58, 10, 45, 45, 32, 32, + 32, 32,123,105,125, 32, 61, 32,108,105,115,116, 32,111,102, + 32,111, 98,106,101, 99,116,115, 32,105,110, 32,116,104,101, + 32,109,111,100,117,108,101, 46, 10, 99,108, 97,115,115, 77, + 111,100,117,108,101, 32, 61, 32,123, 10, 32, 99,108, 97,115, + 115,116,121,112,101, 32, 61, 32, 39,109,111,100,117,108,101, + 39, 10,125, 10, 99,108, 97,115,115, 77,111,100,117,108,101, + 46, 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97,115, + 115, 77,111,100,117,108,101, 10,115,101,116,109,101,116, 97, + 116, 97, 98,108,101, 40, 99,108, 97,115,115, 77,111,100,117, + 108,101, 44, 99,108, 97,115,115, 67,111,110,116, 97,105,110, + 101,114, 41, 10, 10, 45, 45, 32,114,101,103,105,115,116,101, + 114, 32,109,111,100,117,108,101, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 77,111,100,117,108,101, 58, + 114,101,103,105,115,116,101,114, 32, 40,112,114,101, 41, 10, + 32,112,114,101, 32, 61, 32,112,114,101, 32,111,114, 32, 39, + 39, 10, 32,112,117,115,104, 40,115,101,108,102, 41, 10, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 39,116,111, + 108,117, 97, 95,109,111,100,117,108,101, 40,116,111,108,117, + 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46,110, 97, + 109,101, 46, 46, 39, 34, 44, 39, 44,115,101,108,102, 58,104, + 97,115,118, 97,114, 40, 41, 44, 39, 41, 59, 39, 41, 10, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 39,116,111, + 108,117, 97, 95, 98,101,103,105,110,109,111,100,117,108,101, + 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46,115,101, + 108,102, 46,110, 97,109,101, 46, 46, 39, 34, 41, 59, 39, 41, + 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104, + 105,108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10, + 32, 32,115,101,108,102, 91,105, 93, 58,114,101,103,105,115, + 116,101,114, 40,112,114,101, 46, 46, 39, 32, 39, 41, 10, 32, + 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 39,116,111, + 108,117, 97, 95,101,110,100,109,111,100,117,108,101, 40,116, + 111,108,117, 97, 95, 83, 41, 59, 39, 41, 10, 9,112,111,112, + 40, 41, 10,101,110,100, 10, 10, 45, 45, 32, 80,114,105,110, + 116, 32,109,101,116,104,111,100, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 77,111,100,117,108,101, 58, + 112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108, + 111,115,101, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 77,111,100,117,108,101,123, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 34, 39, 59, 34, 41, 10, 32, + 108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104,105,108, + 101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10, 32, 32, + 115,101,108,102, 91,105, 93, 58,112,114,105,110,116, 40,105, + 100,101,110,116, 46, 46, 34, 32, 34, 44, 34, 44, 34, 41, 10, + 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, 10, + 10, 45, 45, 32, 73,110,116,101,114,110, 97,108, 32, 99,111, + 110,115,116,114,117, 99,116,111,114, 10,102,117,110, 99,116, + 105,111,110, 32, 95, 77,111,100,117,108,101, 32, 40,116, 41, + 10, 32,115,101,116,109,101,116, 97,116, 97, 98,108,101, 40, + 116, 44, 99,108, 97,115,115, 77,111,100,117,108,101, 41, 10, + 32, 97,112,112,101,110,100, 40,116, 41, 10, 32,114,101,116, + 117,114,110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, 67, + 111,110,115,116,114,117, 99,116,111,114, 10, 45, 45, 32, 69, + 120,112,101, 99,116,115, 32,116,119,111, 32,115,116,114,105, + 110,103, 32,114,101,112,114,101,115,101,110,116,105,110,103, + 32,116,104,101, 32,109,111,100,117,108,101, 32,110, 97,109, + 101, 32, 97,110,100, 32, 98,111,100,121, 46, 10,102,117,110, + 99,116,105,111,110, 32, 77,111,100,117,108,101, 32, 40,110, + 44, 98, 41, 10, 32,108,111, 99, 97,108, 32,116, 32, 61, 32, + 95, 77,111,100,117,108,101, 40, 95, 67,111,110,116, 97,105, + 110,101,114,123,110, 97,109,101, 61,110,125, 41, 10, 32,112, + 117,115,104, 40,116, 41, 10, 32,116, 58,112, 97,114,115,101, + 40,115,116,114,115,117, 98, 40, 98, 44, 50, 44,115,116,114, + 108,101,110, 40, 98, 41, 45, 49, 41, 41, 32, 45, 45, 32,101, + 108,105,109,105,110, 97,116,101, 32, 98,114, 97, 99,101,115, + 10, 32,112,111,112, 40, 41, 10, 32,114,101,116,117,114,110, + 32,116, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/module.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,110, 97,109,101,115, + 112, 97, 99,101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87, + 114,105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101, + 109, 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, + 67, 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, + 45, 32, 74,117,108, 32, 50, 48, 48, 51, 10, 45, 45, 32, 36, + 73,100, 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, + 99,111,100,101, 32,105,115, 32,102,114,101,101, 32,115,111, + 102,116,119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, + 32,114,101,100,105,115,116,114,105, 98,117,116,101, 32,105, + 116, 32, 97,110,100, 47,111,114, 32,109,111,100,105,102,121, + 32,105,116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102, + 116,119, 97,114,101, 32,112,114,111,118,105,100,101,100, 32, + 104,101,114,101,117,110,100,101,114, 32,105,115, 32,111,110, + 32, 97,110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115, + 105,115, 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, + 97,117,116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, + 98,108,105,103, 97,116,105,111,110, 32,116,111, 32,112,114, + 111,118,105,100,101, 32,109, 97,105,110,116,101,110, 97,110, + 99,101, 44, 32,115,117,112,112,111,114,116, 44, 32,117,112, + 100, 97,116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, + 99,101,109,101,110,116,115, 44, 32,111,114, 32,109,111,100, + 105,102,105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 45, + 45, 32, 78, 97,109,101,115,112, 97, 99,101, 32, 99,108, 97, + 115,115, 10, 45, 45, 32, 82,101,112,114,101,115,101,110,116, + 115, 32, 97, 32,110, 97,109,101,115, 97,112, 99,101, 32,100, + 101,102,105,110,105,116,105,111,110, 46, 10, 45, 45, 32, 83, + 116,111,114,101,115, 32,116,104,101, 32,102,111,108,108,111, + 119,105,110,103, 32,102,105,101,108,100,115, 58, 10, 45, 45, + 32, 32, 32, 32,110, 97,109,101, 32, 61, 32, 99,108, 97,115, + 115, 32,110, 97,109,101, 10, 45, 45, 32, 32, 32, 32,123,105, + 125, 32, 32, 61, 32,108,105,115,116, 32,111,102, 32,109,101, + 109, 98,101,114,115, 10, 99,108, 97,115,115, 78, 97,109,101, + 115,112, 97, 99,101, 32, 61, 32,123, 10, 32, 99,108, 97,115, + 115,116,121,112,101, 32, 61, 32, 39,110, 97,109,101,115,112, + 97, 99,101, 39, 44, 10, 32,110, 97,109,101, 32, 61, 32, 39, + 39, 44, 10,125, 10, 99,108, 97,115,115, 78, 97,109,101,115, + 112, 97, 99,101, 46, 95, 95,105,110,100,101,120, 32, 61, 32, + 99,108, 97,115,115, 78, 97,109,101,115,112, 97, 99,101, 10, + 115,101,116,109,101,116, 97,116, 97, 98,108,101, 40, 99,108, + 97,115,115, 78, 97,109,101,115,112, 97, 99,101, 44, 99,108, + 97,115,115, 77,111,100,117,108,101, 41, 10, 10, 45, 45, 32, + 80,114,105,110,116, 32,109,101,116,104,111,100, 10,102,117, + 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 78, 97,109, + 101,115,112, 97, 99,101, 58,112,114,105,110,116, 32, 40,105, + 100,101,110,116, 44, 99,108,111,115,101, 41, 10, 32,112,114, + 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 78, 97,109, + 101,115,112, 97, 99,101,123, 34, 41, 10, 32,112,114,105,110, + 116, 40,105,100,101,110,116, 46, 46, 34, 32,110, 97,109,101, + 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,110, 97,109, + 101, 46, 46, 34, 39, 44, 34, 41, 10, 32,108,111, 99, 97,108, + 32,105, 61, 49, 10, 32,119,104,105,108,101, 32,115,101,108, + 102, 91,105, 93, 32,100,111, 10, 32, 32,115,101,108,102, 91, + 105, 93, 58,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32, 34, 44, 34, 44, 34, 41, 10, 32, 32,105, 32, 61, + 32,105, 43, 49, 10, 32,101,110,100, 10, 32,112,114,105,110, + 116, 40,105,100,101,110,116, 46, 46, 34,125, 34, 46, 46, 99, + 108,111,115,101, 41, 10,101,110,100, 10, 10, 45, 45, 32, 73, + 110,116,101,114,110, 97,108, 32, 99,111,110,115,116,114,117, + 99,116,111,114, 10,102,117,110, 99,116,105,111,110, 32, 95, + 78, 97,109,101,115,112, 97, 99,101, 32, 40,116, 41, 10, 32, + 115,101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, 44, + 99,108, 97,115,115, 78, 97,109,101,115,112, 97, 99,101, 41, + 10, 32, 97,112,112,101,110,100, 40,116, 41, 10, 32,114,101, + 116,117,114,110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, + 67,111,110,115,116,114,117, 99,116,111,114, 10, 45, 45, 32, + 69,120,112,101, 99,116,115, 32,116,104,101, 32,110, 97,109, + 101, 32, 97,110,100, 32,116,104,101, 32, 98,111,100,121, 32, + 111,102, 32,116,104,101, 32,110, 97,109,101,115,112, 97, 99, + 101, 46, 10,102,117,110, 99,116,105,111,110, 32, 78, 97,109, + 101,115,112, 97, 99,101, 32, 40,110, 44, 98, 41, 10, 32,108, + 111, 99, 97,108, 32, 99, 32, 61, 32, 95, 78, 97,109,101,115, + 112, 97, 99,101, 40, 95, 67,111,110,116, 97,105,110,101,114, + 123,110, 97,109,101, 61,110,125, 41, 10, 32,112,117,115,104, + 40, 99, 41, 10, 32, 99, 58,112, 97,114,115,101, 40,115,116, + 114,115,117, 98, 40, 98, 44, 50, 44,115,116,114,108,101,110, + 40, 98, 41, 45, 49, 41, 41, 32, 45, 45, 32,101,108,105,109, + 105,110, 97,116,101, 32, 98,114, 97, 99,101,115, 10, 32,112, + 111,112, 40, 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/namespace.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,100,101,102,105,110, + 101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105,116, + 116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, 97,114, + 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71,114, + 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74, + 117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73,100, 58, + 32,100,101,102,105,110,101, 46,108,117, 97, 44,118, 32, 49, + 46, 50, 32, 49, 57, 57, 57, 47, 48, 55, 47, 50, 56, 32, 50, + 50, 58, 50, 49, 58, 48, 56, 32, 99,101,108,101,115, 32, 69, + 120,112, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99, + 111,100,101, 32,105,115, 32,102,114,101,101, 32,115,111,102, + 116,119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32, + 114,101,100,105,115,116,114,105, 98,117,116,101, 32,105,116, + 32, 97,110,100, 47,111,114, 32,109,111,100,105,102,121, 32, + 105,116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116, + 119, 97,114,101, 32,112,114,111,118,105,100,101,100, 32,104, + 101,114,101,117,110,100,101,114, 32,105,115, 32,111,110, 32, + 97,110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105, + 115, 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97, + 117,116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98, + 108,105,103, 97,116,105,111,110, 32,116,111, 32,112,114,111, + 118,105,100,101, 32,109, 97,105,110,116,101,110, 97,110, 99, + 101, 44, 32,115,117,112,112,111,114,116, 44, 32,117,112,100, + 97,116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99, + 101,109,101,110,116,115, 44, 32,111,114, 32,109,111,100,105, + 102,105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 45, 45, + 32, 68,101,102,105,110,101, 32, 99,108, 97,115,115, 10, 45, + 45, 32, 82,101,112,114,101,115,101,110,116,115, 32, 97, 32, + 110,117,109,101,114,105, 99, 32, 99,111,110,115,116, 32,100, + 101,102,105,110,105,116,105,111,110, 10, 45, 45, 32, 84,104, + 101, 32,102,111,108,108,111,119,105,110,103, 32,102,105,108, + 100,115, 32, 97,114,101, 32,115,116,111,114,101,100, 58, 10, + 45, 45, 32, 32, 32,110, 97,109,101, 32, 61, 32, 99,111,110, + 115,116, 97,110,116, 32,110, 97,109,101, 10, 99,108, 97,115, + 115, 68,101,102,105,110,101, 32, 61, 32,123, 10, 32,110, 97, + 109,101, 32, 61, 32, 39, 39, 44, 10,125, 10, 99,108, 97,115, + 115, 68,101,102,105,110,101, 46, 95, 95,105,110,100,101,120, + 32, 61, 32, 99,108, 97,115,115, 68,101,102,105,110,101, 10, + 115,101,116,109,101,116, 97,116, 97, 98,108,101, 40, 99,108, + 97,115,115, 68,101,102,105,110,101, 44, 99,108, 97,115,115, + 70,101, 97,116,117,114,101, 41, 10, 10, 45, 45, 32,114,101, + 103,105,115,116,101,114, 32,100,101,102,105,110,101, 10,102, + 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, + 102,105,110,101, 58,114,101,103,105,115,116,101,114, 32, 40, + 112,114,101, 41, 10, 9,105,102, 32,110,111,116, 32,115,101, + 108,102, 58, 99,104,101, 99,107, 95,112,117, 98,108,105, 99, + 95, 97, 99, 99,101,115,115, 40, 41, 32,116,104,101,110, 10, + 9, 9,114,101,116,117,114,110, 10, 9,101,110,100, 10, 10, + 32,112,114,101, 32, 61, 32,112,114,101, 32,111,114, 32, 39, + 39, 10, 32,111,117,116,112,117,116, 40,112,114,101, 46, 46, + 39,116,111,108,117, 97, 95, 99,111,110,115,116, 97,110,116, + 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46,115,101, + 108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, 44, 39, 46, + 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 41, 59, + 39, 41, 10,101,110,100, 10, 10, 45, 45, 32, 80,114,105,110, + 116, 32,109,101,116,104,111,100, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 68,101,102,105,110,101, 58, + 112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108, + 111,115,101, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 68,101,102,105,110,101,123, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 108,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,108,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, 10, + 10, 10, 45, 45, 32, 73,110,116,101,114,110, 97,108, 32, 99, + 111,110,115,116,114,117, 99,116,111,114, 10,102,117,110, 99, + 116,105,111,110, 32, 95, 68,101,102,105,110,101, 32, 40,116, + 41, 10, 32,115,101,116,109,101,116, 97,116, 97, 98,108,101, + 40,116, 44, 99,108, 97,115,115, 68,101,102,105,110,101, 41, + 10, 32,116, 58, 98,117,105,108,100,110, 97,109,101,115, 40, + 41, 10, 10, 32,105,102, 32,116, 46,110, 97,109,101, 32, 61, + 61, 32, 39, 39, 32,116,104,101,110, 10, 32, 32,101,114,114, + 111,114, 40, 34, 35,105,110,118, 97,108,105,100, 32,100,101, + 102,105,110,101, 34, 41, 10, 32,101,110,100, 10, 10, 32, 97, + 112,112,101,110,100, 40,116, 41, 10, 32,114,101,116,117,114, + 110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, 67,111,110, + 115,116,114,117, 99,116,111,114, 10, 45, 45, 32, 69,120,112, + 101, 99,116,115, 32, 97, 32,115,116,114,105,110,103, 32,114, + 101,112,114,101,115,101,110,116,105,110,103, 32,116,104,101, + 32, 99,111,110,115,116, 97,110,116, 32,110, 97,109,101, 10, + 102,117,110, 99,116,105,111,110, 32, 68,101,102,105,110,101, + 32, 40,110, 41, 10, 32,114,101,116,117,114,110, 32, 95, 68, + 101,102,105,110,101,123, 10, 32, 32,110, 97,109,101, 32, 61, + 32,110, 10, 32,125, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/define.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,101,110,117,109,101, + 114, 97,116,101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87, + 114,105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101, + 109, 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, + 67, 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, + 45, 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, + 73,100, 58, 32,101,110,117,109,101,114, 97,116,101, 46,108, + 117, 97, 44,118, 32, 49, 46, 51, 32, 50, 48, 48, 48, 47, 48, + 49, 47, 50, 52, 32, 50, 48, 58, 52, 49, 58, 49, 53, 32, 99, + 101,108,101,115, 32, 69,120,112, 32, 36, 10, 10, 45, 45, 32, + 84,104,105,115, 32, 99,111,100,101, 32,105,115, 32,102,114, + 101,101, 32,115,111,102,116,119, 97,114,101, 59, 32,121,111, + 117, 32, 99, 97,110, 32,114,101,100,105,115,116,114,105, 98, + 117,116,101, 32,105,116, 32, 97,110,100, 47,111,114, 32,109, + 111,100,105,102,121, 32,105,116, 46, 10, 45, 45, 32, 84,104, + 101, 32,115,111,102,116,119, 97,114,101, 32,112,114,111,118, + 105,100,101,100, 32,104,101,114,101,117,110,100,101,114, 32, + 105,115, 32,111,110, 32, 97,110, 32, 34, 97,115, 32,105,115, + 34, 32, 98, 97,115,105,115, 44, 32, 97,110,100, 10, 45, 45, + 32,116,104,101, 32, 97,117,116,104,111,114, 32,104, 97,115, + 32,110,111, 32,111, 98,108,105,103, 97,116,105,111,110, 32, + 116,111, 32,112,114,111,118,105,100,101, 32,109, 97,105,110, + 116,101,110, 97,110, 99,101, 44, 32,115,117,112,112,111,114, + 116, 44, 32,117,112,100, 97,116,101,115, 44, 10, 45, 45, 32, + 101,110,104, 97,110, 99,101,109,101,110,116,115, 44, 32,111, + 114, 32,109,111,100,105,102,105, 99, 97,116,105,111,110,115, + 46, 10, 10, 10, 45, 45, 32, 69,110,117,109,101,114, 97,116, + 101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 82,101,112,114, + 101,115,101,110,116,115, 32,101,110,117,109,101,114, 97,116, + 105,111,110, 10, 45, 45, 32, 84,104,101, 32,102,111,108,108, + 111,119,105,110,103, 32,102,105,101,108,100,115, 32, 97,114, + 101, 32,115,116,111,114,101,100, 58, 10, 45, 45, 32, 32, 32, + 32,123,105,125, 32, 61, 32,108,105,115,116, 32,111,102, 32, + 99,111,110,115,116, 97,110,116, 32,110, 97,109,101,115, 10, + 99,108, 97,115,115, 69,110,117,109,101,114, 97,116,101, 32, + 61, 32,123, 10,125, 10, 99,108, 97,115,115, 69,110,117,109, + 101,114, 97,116,101, 46, 95, 95,105,110,100,101,120, 32, 61, + 32, 99,108, 97,115,115, 69,110,117,109,101,114, 97,116,101, + 10,115,101,116,109,101,116, 97,116, 97, 98,108,101, 40, 99, + 108, 97,115,115, 69,110,117,109,101,114, 97,116,101, 44, 99, + 108, 97,115,115, 70,101, 97,116,117,114,101, 41, 10, 10, 45, + 45, 32,114,101,103,105,115,116,101,114, 32,101,110,117,109, + 101,114, 97,116,105,111,110, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 69,110,117,109,101,114, 97,116, + 101, 58,114,101,103,105,115,116,101,114, 32, 40,112,114,101, + 41, 10, 9,105,102, 32,110,111,116, 32,115,101,108,102, 58, + 99,104,101, 99,107, 95,112,117, 98,108,105, 99, 95, 97, 99, + 99,101,115,115, 40, 41, 32,116,104,101,110, 10, 9, 9,114, + 101,116,117,114,110, 10, 9,101,110,100, 10, 32,112,114,101, + 32, 61, 32,112,114,101, 32,111,114, 32, 39, 39, 10, 32,108, + 111, 99, 97,108, 32,110,115,112, 97, 99,101, 32, 61, 32,103, + 101,116,110, 97,109,101,115,112, 97, 99,101, 40, 99,108, 97, + 115,115, 67,111,110,116, 97,105,110,101,114, 46, 99,117,114, + 114, 41, 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32, + 119,104,105,108,101, 32,115,101,108,102, 91,105, 93, 32,100, + 111, 10, 32, 9,105,102, 32,115,101,108,102, 46,108,110, 97, + 109,101,115, 91,105, 93, 32, 97,110,100, 32,115,101,108,102, + 46,108,110, 97,109,101,115, 91,105, 93, 32,126, 61, 32, 34, + 34, 32,116,104,101,110, 10, 9, 10, 9, 9,111,117,116,112, + 117,116, 40,112,114,101, 46, 46, 39,116,111,108,117, 97, 95, + 99,111,110,115,116, 97,110,116, 40,116,111,108,117, 97, 95, + 83, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, 97,109, + 101,115, 91,105, 93, 46, 46, 39, 34, 44, 39, 46, 46,110,115, + 112, 97, 99,101, 46, 46,115,101,108,102, 91,105, 93, 46, 46, + 39, 41, 59, 39, 41, 10, 9,101,110,100, 10, 32, 32,105, 32, + 61, 32,105, 43, 49, 10, 32,101,110,100, 10,101,110,100, 10, + 10, 45, 45, 32, 80,114,105,110,116, 32,109,101,116,104,111, + 100, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 69,110,117,109,101,114, 97,116,101, 58,112,114,105,110, + 116, 32, 40,105,100,101,110,116, 44, 99,108,111,115,101, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34, 69,110,117,109,101,114, 97,116,101,123, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 110, 97,109,101, 32, 61, 32, 34, 46, 46,115,101,108,102, 46, + 110, 97,109,101, 41, 10, 32,108,111, 99, 97,108, 32,105, 61, + 49, 10, 32,119,104,105,108,101, 32,115,101,108,102, 91,105, + 93, 32,100,111, 10, 32, 32,112,114,105,110,116, 40,105,100, + 101,110,116, 46, 46, 34, 32, 39, 34, 46, 46,115,101,108,102, + 91,105, 93, 46, 46, 34, 39, 40, 34, 46, 46,115,101,108,102, + 46,108,110, 97,109,101,115, 91,105, 93, 46, 46, 34, 41, 44, + 34, 41, 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101, + 110,100, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, + 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101, + 110,100, 10, 10, 45, 45, 32, 73,110,116,101,114,110, 97,108, + 32, 99,111,110,115,116,114,117, 99,116,111,114, 10,102,117, + 110, 99,116,105,111,110, 32, 95, 69,110,117,109,101,114, 97, + 116,101, 32, 40,116, 44,118, 97,114,110, 97,109,101, 41, 10, + 32,115,101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, + 44, 99,108, 97,115,115, 69,110,117,109,101,114, 97,116,101, + 41, 10, 32, 97,112,112,101,110,100, 40,116, 41, 10, 32, 97, + 112,112,101,110,100,101,110,117,109, 40,116, 41, 10, 9, 32, + 105,102, 32,118, 97,114,110, 97,109,101, 32, 97,110,100, 32, + 118, 97,114,110, 97,109,101, 32,126, 61, 32, 34, 34, 32,116, + 104,101,110, 10, 9, 9,105,102, 32,116, 46,110, 97,109,101, + 32,126, 61, 32, 34, 34, 32,116,104,101,110, 10, 9, 9, 9, + 86, 97,114,105, 97, 98,108,101, 40,116, 46,110, 97,109,101, + 46, 46, 34, 32, 34, 46, 46,118, 97,114,110, 97,109,101, 41, + 10, 9, 9,101,108,115,101, 10, 9, 9, 9,108,111, 99, 97, + 108, 32,110,115, 32, 61, 32,103,101,116, 99,117,114,114,110, + 97,109,101,115,112, 97, 99,101, 40, 41, 10, 9, 9, 9,119, + 97,114,110,105,110,103, 40, 34, 86, 97,114,105, 97, 98,108, + 101, 32, 34, 46, 46,110,115, 46, 46,118, 97,114,110, 97,109, + 101, 46, 46, 34, 32,111,102, 32,116,121,112,101, 32, 60, 97, + 110,111,110,121,109,111,117,115, 32,101,110,117,109, 62, 32, + 105,115, 32,100,101, 99,108, 97,114,101,100, 32, 97,115, 32, + 114,101, 97,100, 45,111,110,108,121, 34, 41, 10, 9, 9, 9, + 86, 97,114,105, 97, 98,108,101, 40, 34,116,111,108,117, 97, + 95,114,101, 97,100,111,110,108,121, 32,105,110,116, 32, 34, + 46, 46,118, 97,114,110, 97,109,101, 41, 10, 9, 9,101,110, + 100, 10, 9,101,110,100, 10, 9, 32,108,111, 99, 97,108, 32, + 112, 97,114,101,110,116, 32, 61, 32, 99,108, 97,115,115, 67, + 111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 10, 9, + 32,105,102, 32,112, 97,114,101,110,116, 32,116,104,101,110, + 10, 9, 9,116, 46, 97, 99, 99,101,115,115, 32, 61, 32,112, + 97,114,101,110,116, 46, 99,117,114,114, 95,109,101,109, 98, + 101,114, 95, 97, 99, 99,101,115,115, 10, 9, 9,116, 46,103, + 108,111, 98, 97,108, 95, 97, 99, 99,101,115,115, 32, 61, 32, + 116, 58, 99,104,101, 99,107, 95,112,117, 98,108,105, 99, 95, + 97, 99, 99,101,115,115, 40, 41, 10, 9, 32,101,110,100, 10, + 114,101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 45, + 45, 32, 67,111,110,115,116,114,117, 99,116,111,114, 10, 45, + 45, 32, 69,120,112,101, 99,116,115, 32, 97, 32,115,116,114, + 105,110,103, 32,114,101,112,114,101,115,101,110,116,105,110, + 103, 32,116,104,101, 32,101,110,117,109,101,114, 97,116,101, + 32, 98,111,100,121, 10,102,117,110, 99,116,105,111,110, 32, + 69,110,117,109,101,114, 97,116,101, 32, 40,110, 44, 98, 44, + 118, 97,114,110, 97,109,101, 41, 10, 9, 98, 32, 61, 32,115, + 116,114,105,110,103, 46,103,115,117, 98, 40, 98, 44, 32, 34, + 44, 91, 37,115, 92,110, 93, 42,125, 34, 44, 32, 34, 92,110, + 125, 34, 41, 32, 45, 45, 32,101,108,105,109,105,110, 97,116, + 101, 32,108, 97,115,116, 32, 39, 44, 39, 10, 32,108,111, 99, + 97,108, 32,116, 32, 61, 32,115,112,108,105,116, 40,115,116, + 114,115,117, 98, 40, 98, 44, 50, 44, 45, 50, 41, 44, 39, 44, + 39, 41, 32, 45, 45, 32,101,108,105,109,105,110, 97,116,101, + 32, 98,114, 97, 99,101,115, 10, 32,108,111, 99, 97,108, 32, + 105, 32, 61, 32, 49, 10, 32,108,111, 99, 97,108, 32,101, 32, + 61, 32,123,110, 61, 48,125, 10, 32,119,104,105,108,101, 32, + 116, 91,105, 93, 32,100,111, 10, 32, 32,108,111, 99, 97,108, + 32,116,116, 32, 61, 32,115,112,108,105,116, 40,116, 91,105, + 93, 44, 39, 61, 39, 41, 32, 32, 45, 45, 32,100,105,115, 99, + 97,114,100, 32,105,110,105,116,105, 97,108, 32,118, 97,108, + 117,101, 10, 32, 32,101, 46,110, 32, 61, 32,101, 46,110, 32, + 43, 32, 49, 10, 32, 32,101, 91,101, 46,110, 93, 32, 61, 32, + 116,116, 91, 49, 93, 10, 32, 32,105, 32, 61, 32,105, 43, 49, + 10, 32,101,110,100, 10, 32, 45, 45, 32,115,101,116, 32,108, + 117, 97, 32,110, 97,109,101,115, 10, 32,105, 32, 32, 61, 32, + 49, 10, 32,101, 46,108,110, 97,109,101,115, 32, 61, 32,123, + 125, 10, 32,108,111, 99, 97,108, 32,110,115, 32, 61, 32,103, + 101,116, 99,117,114,114,110, 97,109,101,115,112, 97, 99,101, + 40, 41, 10, 32,119,104,105,108,101, 32,101, 91,105, 93, 32, + 100,111, 10, 32, 32,108,111, 99, 97,108, 32,116, 32, 61, 32, + 115,112,108,105,116, 40,101, 91,105, 93, 44, 39, 64, 39, 41, + 10, 32, 32,101, 91,105, 93, 32, 61, 32,116, 91, 49, 93, 10, + 9, 9,105,102, 32,110,111,116, 32,116, 91, 50, 93, 32,116, + 104,101,110, 10, 9, 9, 32,116, 91, 50, 93, 32, 61, 32, 97, + 112,112,108,121,114,101,110, 97,109,105,110,103, 40,116, 91, + 49, 93, 41, 10, 9, 9,101,110,100, 10, 32, 32,101, 46,108, + 110, 97,109,101,115, 91,105, 93, 32, 61, 32,116, 91, 50, 93, + 32,111,114, 32,116, 91, 49, 93, 10, 32, 32, 95,103,108,111, + 98, 97,108, 95,101,110,117,109,115, 91, 32,110,115, 46, 46, + 101, 91,105, 93, 32, 93, 32, 61, 32, 40,110,115, 46, 46,101, + 91,105, 93, 41, 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, + 32,101,110,100, 10, 9,101, 46,110, 97,109,101, 32, 61, 32, + 110, 10, 9,105,102, 32,110, 32,126, 61, 32, 34, 34, 32,116, + 104,101,110, 10, 9, 9, 84,121,112,101,100,101,102, 40, 34, + 105,110,116, 32, 34, 46, 46,110, 41, 10, 9,101,110,100, 10, + 32,114,101,116,117,114,110, 32, 95, 69,110,117,109,101,114, + 97,116,101, 40,101, 44, 32,118, 97,114,110, 97,109,101, 41, + 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/enumerate.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,100,101, 99,108, 97, + 114, 97,116,105,111,110, 32, 99,108, 97,115,115, 10, 45, 45, + 32, 87,114,105,116,116,101,110, 32, 98,121, 32, 87, 97,108, + 100,101,109, 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, + 84,101, 67, 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, + 10, 45, 45, 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, + 32, 36, 73,100, 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105, + 115, 32, 99,111,100,101, 32,105,115, 32,102,114,101,101, 32, + 115,111,102,116,119, 97,114,101, 59, 32,121,111,117, 32, 99, + 97,110, 32,114,101,100,105,115,116,114,105, 98,117,116,101, + 32,105,116, 32, 97,110,100, 47,111,114, 32,109,111,100,105, + 102,121, 32,105,116, 46, 10, 45, 45, 32, 84,104,101, 32,115, + 111,102,116,119, 97,114,101, 32,112,114,111,118,105,100,101, + 100, 32,104,101,114,101,117,110,100,101,114, 32,105,115, 32, + 111,110, 32, 97,110, 32, 34, 97,115, 32,105,115, 34, 32, 98, + 97,115,105,115, 44, 32, 97,110,100, 10, 45, 45, 32,116,104, + 101, 32, 97,117,116,104,111,114, 32,104, 97,115, 32,110,111, + 32,111, 98,108,105,103, 97,116,105,111,110, 32,116,111, 32, + 112,114,111,118,105,100,101, 32,109, 97,105,110,116,101,110, + 97,110, 99,101, 44, 32,115,117,112,112,111,114,116, 44, 32, + 117,112,100, 97,116,101,115, 44, 10, 45, 45, 32,101,110,104, + 97,110, 99,101,109,101,110,116,115, 44, 32,111,114, 32,109, + 111,100,105,102,105, 99, 97,116,105,111,110,115, 46, 10, 10, + 10, 45, 45, 32, 68,101, 99,108, 97,114, 97,116,105,111,110, + 32, 99,108, 97,115,115, 10, 45, 45, 32, 82,101,112,114,101, + 115,101,110,116,115, 32,118, 97,114,105, 97, 98,108,101, 44, + 32,102,117,110, 99,116,105,111,110, 44, 32,111,114, 32, 97, + 114,103,117,109,101,110,116, 32,100,101, 99,108, 97,114, 97, + 116,105,111,110, 46, 10, 45, 45, 32, 83,116,111,114,101,115, + 32,116,104,101, 32,102,111,108,108,111,119,105,110,103, 32, + 102,105,101,108,100,115, 58, 10, 45, 45, 32, 32,109,111,100, + 32, 32, 61, 32,116,121,112,101, 32,109,111,100,105,102,105, + 101,114,115, 10, 45, 45, 32, 32,116,121,112,101, 32, 61, 32, + 116,121,112,101, 10, 45, 45, 32, 32,112,116,114, 32, 32, 61, + 32, 34, 42, 34, 32,111,114, 32, 34, 38, 34, 44, 32,105,102, + 32,114,101,112,114,101,115,101,110,116,105,110,103, 32, 97, + 32,112,111,105,110,116,101,114, 32,111,114, 32, 97, 32,114, + 101,102,101,114,101,110, 99,101, 10, 45, 45, 32, 32,110, 97, + 109,101, 32, 61, 32,110, 97,109,101, 10, 45, 45, 32, 32,100, + 105,109, 32, 32, 61, 32,100,105,109,101,110,115,105,111,110, + 44, 32,105,102, 32, 97, 32,118,101, 99,116,111,114, 10, 45, + 45, 32, 32,100,101,102, 32, 32, 61, 32,100,101,102, 97,117, + 108,116, 32,118, 97,108,117,101, 44, 32,105,102, 32, 97,110, + 121, 32, 40,111,110,108,121, 32,102,111,114, 32, 97,114,103, + 117,109,101,110,116,115, 41, 10, 45, 45, 32, 32,114,101,116, + 32, 32, 61, 32, 34, 42, 34, 32,111,114, 32, 34, 38, 34, 44, + 32,105,102, 32,118, 97,108,117,101, 32,105,115, 32,116,111, + 32, 98,101, 32,114,101,116,117,114,110,101,100, 32, 40,111, + 110,108,121, 32,102,111,114, 32, 97,114,103,117,109,101,110, + 116,115, 41, 10, 99,108, 97,115,115, 68,101, 99,108, 97,114, + 97,116,105,111,110, 32, 61, 32,123, 10, 32,109,111,100, 32, + 61, 32, 39, 39, 44, 10, 32,116,121,112,101, 32, 61, 32, 39, + 39, 44, 10, 32,112,116,114, 32, 61, 32, 39, 39, 44, 10, 32, + 110, 97,109,101, 32, 61, 32, 39, 39, 44, 10, 32,100,105,109, + 32, 61, 32, 39, 39, 44, 10, 32,114,101,116, 32, 61, 32, 39, + 39, 44, 10, 32,100,101,102, 32, 61, 32, 39, 39, 10,125, 10, + 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111, + 110, 46, 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97, + 115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 10,115, + 101,116,109,101,116, 97,116, 97, 98,108,101, 40, 99,108, 97, + 115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 44, 99, + 108, 97,115,115, 70,101, 97,116,117,114,101, 41, 10, 10, 45, + 45, 32, 67,114,101, 97,116,101, 32, 97,110, 32,117,110,105, + 113,117,101, 32,118, 97,114,105, 97, 98,108,101, 32,110, 97, + 109,101, 10,102,117,110, 99,116,105,111,110, 32, 99,114,101, + 97,116,101, 95,118, 97,114,110, 97,109,101, 32, 40, 41, 10, + 32,105,102, 32,110,111,116, 32, 95,118, 97,114,110,117,109, + 98,101,114, 32,116,104,101,110, 32, 95,118, 97,114,110,117, + 109, 98,101,114, 32, 61, 32, 48, 32,101,110,100, 10, 32, 95, + 118, 97,114,110,117,109, 98,101,114, 32, 61, 32, 95,118, 97, + 114,110,117,109, 98,101,114, 32, 43, 32, 49, 10, 32,114,101, + 116,117,114,110, 32, 34,116,111,108,117, 97, 95,118, 97,114, + 95, 34, 46, 46, 95,118, 97,114,110,117,109, 98,101,114, 10, + 101,110,100, 10, 10, 45, 45, 32, 67,104,101, 99,107, 32,100, + 101, 99,108, 97,114, 97,116,105,111,110, 32,110, 97,109,101, + 10, 45, 45, 32, 73,116, 32, 97,108,115,111, 32,105,100,101, + 110,116,105,102,105,101,115, 32,100,101,102, 97,117,108,116, + 32,118, 97,108,117,101,115, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, + 105,111,110, 58, 99,104,101, 99,107,110, 97,109,101, 32, 40, + 41, 10, 10, 32,105,102, 32,115,116,114,115,117, 98, 40,115, + 101,108,102, 46,110, 97,109,101, 44, 49, 44, 49, 41, 32, 61, + 61, 32, 39, 91, 39, 32, 97,110,100, 32,110,111,116, 32,102, + 105,110,100,116,121,112,101, 40,115,101,108,102, 46,116,121, + 112,101, 41, 32,116,104,101,110, 10, 32, 32,115,101,108,102, + 46,110, 97,109,101, 32, 61, 32,115,101,108,102, 46,116,121, + 112,101, 46, 46,115,101,108,102, 46,110, 97,109,101, 10, 32, + 32,108,111, 99, 97,108, 32,109, 32, 61, 32,115,112,108,105, + 116, 40,115,101,108,102, 46,109,111,100, 44, 39, 37,115, 37, + 115, 42, 39, 41, 10, 32, 32,115,101,108,102, 46,116,121,112, + 101, 32, 61, 32,109, 91,109, 46,110, 93, 10, 32, 32,115,101, + 108,102, 46,109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, + 40,109, 44, 49, 44,109, 46,110, 45, 49, 41, 10, 32,101,110, + 100, 10, 10, 32,108,111, 99, 97,108, 32,116, 32, 61, 32,115, + 112,108,105,116, 40,115,101,108,102, 46,110, 97,109,101, 44, + 39, 61, 39, 41, 10, 32,105,102, 32,116, 46,110, 61, 61, 50, + 32,116,104,101,110, 10, 32, 32,115,101,108,102, 46,110, 97, + 109,101, 32, 61, 32,116, 91, 49, 93, 10, 32, 32,115,101,108, + 102, 46,100,101,102, 32, 61, 32,102,105,110,100, 95,101,110, + 117,109, 95,118, 97,114, 40,116, 91,116, 46,110, 93, 41, 10, + 32,101,110,100, 10, 10, 32,108,111, 99, 97,108, 32, 98, 44, + 101, 44,100, 32, 61, 32,115,116,114,102,105,110,100, 40,115, + 101,108,102, 46,110, 97,109,101, 44, 34, 37, 91, 40, 46, 45, + 41, 37, 93, 34, 41, 10, 32,105,102, 32, 98, 32,116,104,101, + 110, 10, 32, 32,115,101,108,102, 46,110, 97,109,101, 32, 61, + 32,115,116,114,115,117, 98, 40,115,101,108,102, 46,110, 97, + 109,101, 44, 49, 44, 98, 45, 49, 41, 10, 32, 32,115,101,108, + 102, 46,100,105,109, 32, 61, 32,102,105,110,100, 95,101,110, + 117,109, 95,118, 97,114, 40,100, 41, 10, 32,101,110,100, 10, + 10, 10, 32,105,102, 32,115,101,108,102, 46,116,121,112,101, + 32,126, 61, 32, 39, 39, 32, 97,110,100, 32,115,101,108,102, + 46,116,121,112,101, 32,126, 61, 32, 39,118,111,105,100, 39, + 32, 97,110,100, 32,115,101,108,102, 46,110, 97,109,101, 32, + 61, 61, 32, 39, 39, 32,116,104,101,110, 10, 32, 32,115,101, + 108,102, 46,110, 97,109,101, 32, 61, 32, 99,114,101, 97,116, + 101, 95,118, 97,114,110, 97,109,101, 40, 41, 10, 32,101,108, + 115,101,105,102, 32,115,101,108,102, 46,107,105,110,100, 61, + 61, 39,118, 97,114, 39, 32,116,104,101,110, 10, 32, 32,105, + 102, 32,115,101,108,102, 46,116,121,112,101, 61, 61, 39, 39, + 32, 97,110,100, 32,115,101,108,102, 46,110, 97,109,101,126, + 61, 39, 39, 32,116,104,101,110, 10, 32, 32, 32,115,101,108, + 102, 46,116,121,112,101, 32, 61, 32,115,101,108,102, 46,116, + 121,112,101, 46, 46,115,101,108,102, 46,110, 97,109,101, 10, + 32, 32, 32,115,101,108,102, 46,110, 97,109,101, 32, 61, 32, + 99,114,101, 97,116,101, 95,118, 97,114,110, 97,109,101, 40, + 41, 10, 32, 32,101,108,115,101,105,102, 32,102,105,110,100, + 116,121,112,101, 40,115,101,108,102, 46,110, 97,109,101, 41, + 32,116,104,101,110, 10, 32, 32, 32,105,102, 32,115,101,108, + 102, 46,116,121,112,101, 61, 61, 39, 39, 32,116,104,101,110, + 32,115,101,108,102, 46,116,121,112,101, 32, 61, 32,115,101, + 108,102, 46,110, 97,109,101, 10, 32, 32, 32,101,108,115,101, + 32,115,101,108,102, 46,116,121,112,101, 32, 61, 32,115,101, + 108,102, 46,116,121,112,101, 46, 46, 39, 32, 39, 46, 46,115, + 101,108,102, 46,110, 97,109,101, 32,101,110,100, 10, 32, 32, + 32,115,101,108,102, 46,110, 97,109,101, 32, 61, 32, 99,114, + 101, 97,116,101, 95,118, 97,114,110, 97,109,101, 40, 41, 10, + 32, 32,101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, + 32, 97,100,106,117,115,116, 32,116,121,112,101, 32,111,102, + 32,115,116,114,105,110,103, 10, 32,105,102, 32,115,101,108, + 102, 46,116,121,112,101, 32, 61, 61, 32, 39, 99,104, 97,114, + 39, 32, 97,110,100, 32,115,101,108,102, 46,100,105,109, 32, + 126, 61, 32, 39, 39, 32,116,104,101,110, 10, 9, 32,115,101, + 108,102, 46,116,121,112,101, 32, 61, 32, 39, 99,104, 97,114, + 42, 39, 10, 32,101,110,100, 10, 10, 9,105,102, 32,115,101, + 108,102, 46,107,105,110,100, 32, 97,110,100, 32,115,101,108, + 102, 46,107,105,110,100, 32, 61, 61, 32, 39,118, 97,114, 39, + 32,116,104,101,110, 10, 9, 9,115,101,108,102, 46,110, 97, + 109,101, 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, + 98, 40,115,101,108,102, 46,110, 97,109,101, 44, 32, 34, 58, + 46, 42, 36, 34, 44, 32, 34, 34, 41, 32, 45, 45, 32, 63, 63, + 63, 10, 9,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, + 67,104,101, 99,107, 32,100,101, 99,108, 97,114, 97,116,105, + 111,110, 32,116,121,112,101, 10, 45, 45, 32, 83,117, 98,115, + 116,105,116,117,116,101,115, 32,116,121,112,101,100,101,102, + 39,115, 46, 10,102,117,110, 99,116,105,111,110, 32, 99,108, + 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 58, + 99,104,101, 99,107,116,121,112,101, 32, 40, 41, 10, 10, 32, + 45, 45, 32, 99,104,101, 99,107, 32,105,102, 32,116,104,101, + 114,101, 32,105,115, 32, 97, 32,112,111,105,110,116,101,114, + 32,116,111, 32, 98, 97,115,105, 99, 32,116,121,112,101, 10, + 32,108,111, 99, 97,108, 32, 98, 97,115,105, 99, 32, 61, 32, + 105,115, 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121, + 112,101, 41, 10, 32,105,102, 32,115,101,108,102, 46,107,105, + 110,100, 32, 61, 61, 32, 39,102,117,110, 99, 39, 32, 97,110, + 100, 32, 98, 97,115,105, 99, 61, 61, 39,110,117,109, 98,101, + 114, 39, 32, 97,110,100, 32,115,116,114,105,110,103, 46,102, + 105,110,100, 40,115,101,108,102, 46,112,116,114, 44, 32, 34, + 37, 42, 34, 41, 32,116,104,101,110, 10, 32, 9,115,101,108, + 102, 46,116,121,112,101, 32, 61, 32, 39, 95,117,115,101,114, + 100, 97,116, 97, 39, 10, 32, 9,115,101,108,102, 46,112,116, + 114, 32, 61, 32, 34, 34, 10, 32,101,110,100, 10, 32,105,102, + 32, 98, 97,115,105, 99, 32, 97,110,100, 32,115,101,108,102, + 46,112,116,114,126, 61, 39, 39, 32,116,104,101,110, 10, 32, + 32,115,101,108,102, 46,114,101,116, 32, 61, 32,115,101,108, + 102, 46,112,116,114, 10, 32, 32,115,101,108,102, 46,112,116, + 114, 32, 61, 32,110,105,108, 10, 32, 32,105,102, 32,105,115, + 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121,112,101, + 41, 32, 61, 61, 32, 39,110,117,109, 98,101,114, 39, 32,116, + 104,101,110, 10, 32, 32, 9,115,101,108,102, 46,114,101,116, + 117,114,110, 95,117,115,101,114,100, 97,116, 97, 32, 61, 32, + 116,114,117,101, 10, 32, 32,101,110,100, 10, 32,101,110,100, + 10, 10, 32, 45, 45, 32, 99,104,101, 99,107, 32,105,102, 32, + 116,104,101,114,101, 32,105,115, 32, 97,114,114, 97,121, 32, + 116,111, 32, 98,101, 32,114,101,116,117,114,110,101,100, 10, + 32,105,102, 32,115,101,108,102, 46,100,105,109,126, 61, 39, + 39, 32, 97,110,100, 32,115,101,108,102, 46,114,101,116,126, + 61, 39, 39, 32,116,104,101,110, 10, 32, 32, 32,101,114,114, + 111,114, 40, 39, 35,105,110,118, 97,108,105,100, 32,112, 97, + 114, 97,109,101,116,101,114, 58, 32, 99, 97,110,110,111,116, + 32,114,101,116,117,114,110, 32, 97,110, 32, 97,114,114, 97, + 121, 32,111,102, 32,118, 97,108,117,101,115, 39, 41, 10, 32, + 101,110,100, 10, 32, 45, 45, 32,114,101,115,116,111,114,101, + 32, 39,118,111,105,100, 42, 39, 32, 97,110,100, 32, 39,115, + 116,114,105,110,103, 42, 39, 10, 32,105,102, 32,115,101,108, + 102, 46,116,121,112,101, 32, 61, 61, 32, 39, 95,117,115,101, + 114,100, 97,116, 97, 39, 32,116,104,101,110, 32,115,101,108, + 102, 46,116,121,112,101, 32, 61, 32, 39,118,111,105,100, 42, + 39, 10, 32,101,108,115,101,105,102, 32,115,101,108,102, 46, + 116,121,112,101, 32, 61, 61, 32, 39, 95, 99,115,116,114,105, + 110,103, 39, 32,116,104,101,110, 32,115,101,108,102, 46,116, + 121,112,101, 32, 61, 32, 39, 99,104, 97,114, 42, 39, 10, 32, + 101,108,115,101,105,102, 32,115,101,108,102, 46,116,121,112, + 101, 32, 61, 61, 32, 39, 95,108,115,116, 97,116,101, 39, 32, + 116,104,101,110, 32,115,101,108,102, 46,116,121,112,101, 32, + 61, 32, 39,108,117, 97, 95, 83,116, 97,116,101, 42, 39, 10, + 32,101,110,100, 10, 10, 32, 45, 45, 32,114,101,115,111,108, + 118,101, 32,116,121,112,101,115, 32,105,110,115,105,100,101, + 32,116,104,101, 32,116,101,109,112,108, 97,116,101,115, 10, + 32,105,102, 32,115,101,108,102, 46,116,121,112,101, 32,116, + 104,101,110, 10, 9, 32,115,101,108,102, 46,116,121,112,101, + 32, 61, 32,114,101,115,111,108,118,101, 95,116,101,109,112, + 108, 97,116,101, 95,116,121,112,101,115, 40,115,101,108,102, + 46,116,121,112,101, 41, 10, 32,101,110,100, 10, 10, 45, 45, + 10, 45, 45, 32, 45, 45, 32,105,102, 32,114,101,116,117,114, + 110,105,110,103, 32,118, 97,108,117,101, 44, 32, 97,117,116, + 111,109, 97,116,105, 99, 97,108,108,121, 32,115,101,116, 32, + 100,101,102, 97,117,108,116, 32,118, 97,108,117,101, 10, 45, + 45, 32,105,102, 32,115,101,108,102, 46,114,101,116, 32,126, + 61, 32, 39, 39, 32, 97,110,100, 32,115,101,108,102, 46,100, + 101,102, 32, 61, 61, 32, 39, 39, 32,116,104,101,110, 10, 45, + 45, 32, 32,115,101,108,102, 46,100,101,102, 32, 61, 32, 39, + 48, 39, 10, 45, 45, 32,101,110,100, 10, 45, 45, 10, 10,101, + 110,100, 10, 10,102,117,110, 99,116,105,111,110, 32,114,101, + 115,111,108,118,101, 95,116,101,109,112,108, 97,116,101, 95, + 116,121,112,101,115, 40,116,121,112,101, 41, 10, 10, 9,105, + 102, 32,105,115, 98, 97,115,105, 99, 40,116,121,112,101, 41, + 32,116,104,101,110, 10, 9, 9,114,101,116,117,114,110, 32, + 116,121,112,101, 10, 9,101,110,100, 10, 9,108,111, 99, 97, + 108, 32, 98, 44, 95, 44,109, 32, 61, 32,115,116,114,105,110, + 103, 46,102,105,110,100, 40,116,121,112,101, 44, 32, 34, 40, + 37, 98, 60, 62, 41, 34, 41, 10, 9,105,102, 32, 98, 32,116, + 104,101,110, 10, 10, 9, 9,109, 32, 61, 32,115,112,108,105, + 116, 95, 99, 95,116,111,107,101,110,115, 40,115,116,114,105, + 110,103, 46,115,117, 98, 40,109, 44, 32, 50, 44, 32, 45, 50, + 41, 44, 32, 34, 44, 34, 41, 10, 9, 9,102,111,114, 32,105, + 61, 49, 44, 32,116, 97, 98,108,101, 46,103,101,116,110, 40, + 109, 41, 32,100,111, 10, 9, 9, 9,109, 91,105, 93, 32, 61, + 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,109, 91, + 105, 93, 44, 34, 37,115, 42, 40, 91, 37, 42, 38, 93, 41, 34, + 44, 32, 34, 37, 49, 34, 41, 10, 9, 9, 9,105,102, 32,110, + 111,116, 32,105,115,101,110,117,109, 40,109, 91,105, 93, 41, + 32,116,104,101,110, 32, 95, 44, 32,109, 91,105, 93, 32, 61, + 32, 97,112,112,108,121,116,121,112,101,100,101,102, 40, 34, + 34, 44, 32,109, 91,105, 93, 41, 32,101,110,100, 10, 9, 9, + 9,109, 91,105, 93, 32, 61, 32,102,105,110,100,116,121,112, + 101, 40,109, 91,105, 93, 41, 32,111,114, 32,109, 91,105, 93, + 10, 9, 9, 9,109, 91,105, 93, 32, 61, 32,114,101,115,111, + 108,118,101, 95,116,101,109,112,108, 97,116,101, 95,116,121, + 112,101,115, 40,109, 91,105, 93, 41, 10, 9, 9,101,110,100, + 10, 10, 9, 9,108,111, 99, 97,108, 32, 98, 44,105, 10, 9, + 9,116,121,112,101, 44, 98, 44,105, 32, 61, 32, 98,114,101, + 97,107, 95,116,101,109,112,108, 97,116,101, 40,116,121,112, + 101, 41, 10, 45, 45,112,114,105,110,116, 40, 34, 99,111,110, + 99, 97,116, 32,105,115, 32, 34, 44, 99,111,110, 99, 97,116, + 40,109, 44, 32, 49, 44, 32,109, 46,110, 41, 41, 10, 9, 9, + 108,111, 99, 97,108, 32,116,101,109,112,108, 97,116,101, 95, + 112, 97,114,116, 32, 61, 32, 34, 60, 34, 46, 46, 99,111,110, + 99, 97,116, 40,109, 44, 32, 49, 44, 32,109, 46,110, 44, 32, + 34, 44, 34, 41, 46, 46, 34, 62, 34, 10, 9, 9,116,121,112, + 101, 32, 61, 32,114,101, 98,117,105,108,100, 95,116,101,109, + 112,108, 97,116,101, 40,116,121,112,101, 44, 32, 98, 44, 32, + 116,101,109,112,108, 97,116,101, 95,112, 97,114,116, 41, 10, + 9, 9,116,121,112,101, 32, 61, 32,115,116,114,105,110,103, + 46,103,115,117, 98, 40,116,121,112,101, 44, 32, 34, 62, 62, + 34, 44, 32, 34, 62, 32, 62, 34, 41, 10, 9,101,110,100, 10, + 9,114,101,116,117,114,110, 32,116,121,112,101, 10,101,110, + 100, 10, 10,102,117,110, 99,116,105,111,110, 32, 98,114,101, + 97,107, 95,116,101,109,112,108, 97,116,101, 40,115, 41, 10, + 9,108,111, 99, 97,108, 32, 98, 44,101, 44,116,105,109,112, + 108, 32, 61, 32,115,116,114,105,110,103, 46,102,105,110,100, + 40,115, 44, 32, 34, 40, 37, 98, 60, 62, 41, 34, 41, 10, 9, + 105,102, 32,116,105,109,112,108, 32,116,104,101,110, 10, 9, + 9,115, 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, + 98, 40,115, 44, 32, 34, 37, 98, 60, 62, 34, 44, 32, 34, 34, + 41, 10, 9, 9,114,101,116,117,114,110, 32,115, 44, 32, 98, + 44, 32,116,105,109,112,108, 10, 9,101,108,115,101, 10, 9, + 9,114,101,116,117,114,110, 32,115, 44, 32, 48, 44, 32,110, + 105,108, 10, 9,101,110,100, 10,101,110,100, 10, 10,102,117, + 110, 99,116,105,111,110, 32,114,101, 98,117,105,108,100, 95, + 116,101,109,112,108, 97,116,101, 40,115, 44, 32, 98, 44, 32, + 116,105,109,112,108, 41, 10, 10, 9,105,102, 32, 98, 32, 61, + 61, 32, 48, 32,116,104,101,110, 10, 9, 9,114,101,116,117, + 114,110, 32,115, 10, 9,101,110,100, 10, 10, 9,114,101,116, + 117,114,110, 32,115,116,114,105,110,103, 46,115,117, 98, 40, + 115, 44, 32, 49, 44, 32, 98, 45, 49, 41, 46, 46,116,105,109, + 112,108, 46, 46,115,116,114,105,110,103, 46,115,117, 98, 40, + 115, 44, 32, 98, 44, 32, 45, 49, 41, 10,101,110,100, 10, 10, + 45, 45, 32, 80,114,105,110,116, 32,109,101,116,104,111,100, + 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, + 68,101, 99,108, 97,114, 97,116,105,111,110, 58,112,114,105, + 110,116, 32, 40,105,100,101,110,116, 44, 99,108,111,115,101, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 68,101, 99,108, 97,114, 97,116,105,111,110,123, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32,109,111,100, 32, 32, 61, 32, 39, 34, 46, 46,115, + 101,108,102, 46,109,111,100, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 112,116,114, 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, + 46,112,116,114, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114, + 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,110, 97, + 109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,110, + 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114,105, + 110,116, 40,105,100,101,110,116, 46, 46, 34, 32,100,105,109, + 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,100,105, + 109, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114,105,110,116, + 40,105,100,101,110,116, 46, 46, 34, 32,100,101,102, 32, 32, + 61, 32, 39, 34, 46, 46,115,101,108,102, 46,100,101,102, 46, + 46, 34, 39, 44, 34, 41, 10, 32,112,114,105,110,116, 40,105, + 100,101,110,116, 46, 46, 34, 32,114,101,116, 32, 32, 61, 32, + 39, 34, 46, 46,115,101,108,102, 46,114,101,116, 46, 46, 34, + 39, 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, + 10,101,110,100, 10, 10, 45, 45, 32, 99,104,101, 99,107, 32, + 105,102, 32, 97,114,114, 97,121, 32,111,102, 32,118, 97,108, + 117,101,115, 32, 97,114,101, 32,114,101,116,117,114,110,101, + 100, 32,116,111, 32, 76,117, 97, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97, + 116,105,111,110, 58,114,101,113,117,105,114,101, 99,111,108, + 108,101, 99,116,105,111,110, 32, 40,116, 41, 10, 32,105,102, + 32,115,101,108,102, 46,109,111,100, 32,126, 61, 32, 39, 99, + 111,110,115,116, 39, 32, 97,110,100, 10, 9, 32, 32, 32, 32, + 115,101,108,102, 46,100,105,109, 32, 97,110,100, 32,115,101, + 108,102, 46,100,105,109, 32,126, 61, 32, 39, 39, 32, 97,110, + 100, 10, 9, 9, 9, 9, 32,110,111,116, 32,105,115, 98, 97, + 115,105, 99, 40,115,101,108,102, 46,116,121,112,101, 41, 32, + 97,110,100, 10, 9, 9, 9, 9, 32,115,101,108,102, 46,112, + 116,114, 32, 61, 61, 32, 39, 39, 32, 97,110,100, 32,115,101, + 108,102, 58, 99,104,101, 99,107, 95,112,117, 98,108,105, 99, + 95, 97, 99, 99,101,115,115, 40, 41, 32,116,104,101,110, 10, + 9, 9,108,111, 99, 97,108, 32,116,121,112,101, 32, 61, 32, + 103,115,117, 98, 40,115,101,108,102, 46,116,121,112,101, 44, + 34, 37,115, 42, 99,111,110,115,116, 37,115, 43, 34, 44, 34, + 34, 41, 10, 9, 9,116, 91,116,121,112,101, 93, 32, 61, 32, + 34,116,111,108,117, 97, 95, 99,111,108,108,101, 99,116, 95, + 34, 32, 46, 46, 32, 99,108,101, 97,110, 95,116,101,109,112, + 108, 97,116,101, 40,116,121,112,101, 41, 10, 9, 9,114,101, + 116,117,114,110, 32,116,114,117,101, 10, 9,101,110,100, 10, + 9,114,101,116,117,114,110, 32,102, 97,108,115,101, 10,101, + 110,100, 10, 10, 45, 45, 32,100,101, 99,108, 97,114,101, 32, + 116, 97,103, 10,102,117,110, 99,116,105,111,110, 32, 99,108, + 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 58, + 100,101, 99,108,116,121,112,101, 32, 40, 41, 10, 10, 9,115, + 101,108,102, 46,116,121,112,101, 32, 61, 32,116,121,112,101, + 118, 97,114, 40,115,101,108,102, 46,116,121,112,101, 41, 10, + 9,105,102, 32,115,116,114,102,105,110,100, 40,115,101,108, + 102, 46,109,111,100, 44, 39, 99,111,110,115,116, 39, 41, 32, + 116,104,101,110, 10, 9, 9,115,101,108,102, 46,116,121,112, + 101, 32, 61, 32, 39, 99,111,110,115,116, 32, 39, 46, 46,115, + 101,108,102, 46,116,121,112,101, 10, 9, 9,115,101,108,102, + 46,109,111,100, 32, 61, 32,103,115,117, 98, 40,115,101,108, + 102, 46,109,111,100, 44, 39, 99,111,110,115,116, 37,115, 42, + 39, 44, 39, 39, 41, 10, 9,101,110,100, 10,101,110,100, 10, + 10, 10, 45, 45, 32,111,117,116,112,117,116, 32,116,121,112, + 101, 32, 99,104,101, 99,107,105,110,103, 10,102,117,110, 99, + 116,105,111,110, 32, 99,108, 97,115,115, 68,101, 99,108, 97, + 114, 97,116,105,111,110, 58,111,117,116, 99,104,101, 99,107, + 116,121,112,101, 32, 40,110, 97,114,103, 41, 10, 32,108,111, + 99, 97,108, 32,100,101,102, 10, 32,108,111, 99, 97,108, 32, + 116, 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101,108, + 102, 46,116,121,112,101, 41, 10, 32,105,102, 32,115,101,108, + 102, 46,100,101,102,126, 61, 39, 39, 32,116,104,101,110, 10, + 32, 32,100,101,102, 32, 61, 32, 49, 10, 32,101,108,115,101, + 10, 32, 32,100,101,102, 32, 61, 32, 48, 10, 32,101,110,100, + 10, 32,105,102, 32,115,101,108,102, 46,100,105,109, 32,126, + 61, 32, 39, 39, 32,116,104,101,110, 10, 9, 45, 45,105,102, + 32,116, 61, 61, 39,115,116,114,105,110,103, 39, 32,116,104, + 101,110, 10, 9, 45, 45, 9,114,101,116,117,114,110, 32, 39, + 116,111,108,117, 97, 95,105,115,115,116,114,105,110,103, 97, + 114,114, 97,121, 40,116,111,108,117, 97, 95, 83, 44, 39, 46, + 46,110, 97,114,103, 46, 46, 39, 44, 39, 46, 46,100,101,102, + 46, 46, 39, 44, 38,116,111,108,117, 97, 95,101,114,114, 41, + 39, 10, 9, 45, 45,101,108,115,101, 10, 9,114,101,116,117, + 114,110, 32, 39, 33,116,111,108,117, 97, 95,105,115,116, 97, + 98,108,101, 40,116,111,108,117, 97, 95, 83, 44, 39, 46, 46, + 110, 97,114,103, 46, 46, 39, 44, 48, 44, 38,116,111,108,117, + 97, 95,101,114,114, 41, 39, 10, 32, 9, 45, 45,101,110,100, + 10, 32,101,108,115,101,105,102, 32,116, 32,116,104,101,110, + 10, 9,114,101,116,117,114,110, 32, 39, 33,116,111,108,117, + 97, 95,105,115, 39, 46, 46,116, 46, 46, 39, 40,116,111,108, + 117, 97, 95, 83, 44, 39, 46, 46,110, 97,114,103, 46, 46, 39, + 44, 39, 46, 46,100,101,102, 46, 46, 39, 44, 38,116,111,108, + 117, 97, 95,101,114,114, 41, 39, 10, 32,101,108,115,101, 10, + 32, 32,108,111, 99, 97,108, 32,105,115, 95,102,117,110, 99, + 32, 61, 32,103,101,116, 95,105,115, 95,102,117,110, 99,116, + 105,111,110, 40,115,101,108,102, 46,116,121,112,101, 41, 10, + 32, 32,105,102, 32,115,101,108,102, 46,112,116,114, 32, 61, + 61, 32, 39, 38, 39, 32,111,114, 32,115,101,108,102, 46,112, + 116,114, 32, 61, 61, 32, 39, 39, 32,116,104,101,110, 10, 32, + 32, 9,114,101,116,117,114,110, 32, 39, 40,116,111,108,117, + 97, 95,105,115,118, 97,108,117,101,110,105,108, 40,116,111, + 108,117, 97, 95, 83, 44, 39, 46, 46,110, 97,114,103, 46, 46, + 39, 44, 38,116,111,108,117, 97, 95,101,114,114, 41, 32,124, + 124, 32, 33, 39, 46, 46,105,115, 95,102,117,110, 99, 46, 46, + 39, 40,116,111,108,117, 97, 95, 83, 44, 39, 46, 46,110, 97, + 114,103, 46, 46, 39, 44, 34, 39, 46, 46,115,101,108,102, 46, + 116,121,112,101, 46, 46, 39, 34, 44, 39, 46, 46,100,101,102, + 46, 46, 39, 44, 38,116,111,108,117, 97, 95,101,114,114, 41, + 41, 39, 10, 32, 32,101,108,115,101, 10, 9,114,101,116,117, + 114,110, 32, 39, 33, 39, 46, 46,105,115, 95,102,117,110, 99, + 46, 46, 39, 40,116,111,108,117, 97, 95, 83, 44, 39, 46, 46, + 110, 97,114,103, 46, 46, 39, 44, 34, 39, 46, 46,115,101,108, + 102, 46,116,121,112,101, 46, 46, 39, 34, 44, 39, 46, 46,100, + 101,102, 46, 46, 39, 44, 38,116,111,108,117, 97, 95,101,114, + 114, 41, 39, 10, 32, 32,101,110,100, 10, 32,101,110,100, 10, + 101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99, + 108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, + 58, 98,117,105,108,100,100,101, 99,108, 97,114, 97,116,105, + 111,110, 32, 40,110, 97,114,103, 44, 32, 99,112,108,117,115, + 112,108,117,115, 41, 10, 32,108,111, 99, 97,108, 32, 97,114, + 114, 97,121, 32, 61, 32,115,101,108,102, 46,100,105,109, 32, + 126, 61, 32, 39, 39, 32, 97,110,100, 32,116,111,110,117,109, + 98,101,114, 40,115,101,108,102, 46,100,105,109, 41, 61, 61, + 110,105,108, 10, 9,108,111, 99, 97,108, 32,108,105,110,101, + 32, 61, 32, 34, 34, 10, 32,108,111, 99, 97,108, 32,112,116, + 114, 32, 61, 32, 39, 39, 10, 32,108,111, 99, 97,108, 32,109, + 111,100, 10, 32,108,111, 99, 97,108, 32,116,121,112,101, 32, + 61, 32,115,101,108,102, 46,116,121,112,101, 10, 32,108,111, + 99, 97,108, 32,110, 99,116,121,112,101, 32, 61, 32,103,115, + 117, 98, 40,115,101,108,102, 46,116,121,112,101, 44, 39, 99, + 111,110,115,116, 37,115, 43, 39, 44, 39, 39, 41, 10, 32,105, + 102, 32,115,101,108,102, 46,100,105,109, 32,126, 61, 32, 39, + 39, 32,116,104,101,110, 10, 9, 32,116,121,112,101, 32, 61, + 32,103,115,117, 98, 40,115,101,108,102, 46,116,121,112,101, + 44, 39, 99,111,110,115,116, 37,115, 43, 39, 44, 39, 39, 41, + 32, 32, 45, 45, 32,101,108,105,109,105,110, 97,116,101,115, + 32, 99,111,110,115,116, 32,109,111,100,105,102,105,101,114, + 32,102,111,114, 32, 97,114,114, 97,121,115, 10, 32,101,110, + 100, 10, 32,105,102, 32,115,101,108,102, 46,112,116,114,126, + 61, 39, 39, 32, 97,110,100, 32,110,111,116, 32,105,115, 98, + 97,115,105, 99, 40,116,121,112,101, 41, 32,116,104,101,110, + 32,112,116,114, 32, 61, 32, 39, 42, 39, 32,101,110,100, 10, + 32,108,105,110,101, 32, 61, 32, 99,111,110, 99, 97,116,112, + 97,114, 97,109, 40,108,105,110,101, 44, 34, 32, 34, 44,115, + 101,108,102, 46,109,111,100, 44,116,121,112,101, 44,112,116, + 114, 41, 10, 32,105,102, 32, 97,114,114, 97,121, 32,116,104, + 101,110, 10, 32, 32,108,105,110,101, 32, 61, 32, 99,111,110, + 99, 97,116,112, 97,114, 97,109, 40,108,105,110,101, 44, 39, + 42, 39, 41, 10, 32,101,110,100, 10, 32,108,105,110,101, 32, + 61, 32, 99,111,110, 99, 97,116,112, 97,114, 97,109, 40,108, + 105,110,101, 44,115,101,108,102, 46,110, 97,109,101, 41, 10, + 32,105,102, 32,115,101,108,102, 46,100,105,109, 32,126, 61, + 32, 39, 39, 32,116,104,101,110, 10, 32, 32,105,102, 32,116, + 111,110,117,109, 98,101,114, 40,115,101,108,102, 46,100,105, + 109, 41,126, 61,110,105,108, 32,116,104,101,110, 10, 32, 32, + 32,108,105,110,101, 32, 61, 32, 99,111,110, 99, 97,116,112, + 97,114, 97,109, 40,108,105,110,101, 44, 39, 91, 39, 44,115, + 101,108,102, 46,100,105,109, 44, 39, 93, 59, 39, 41, 10, 32, + 32,101,108,115,101, 10, 9,105,102, 32, 99,112,108,117,115, + 112,108,117,115, 32,116,104,101,110, 10, 9, 9,108,105,110, + 101, 32, 61, 32, 99,111,110, 99, 97,116,112, 97,114, 97,109, + 40,108,105,110,101, 44, 39, 32, 61, 32, 77,116,111,108,117, + 97, 95,110,101,119, 40, 40, 39, 44,116,121,112,101, 44,112, + 116,114, 44, 39, 41, 91, 39, 46, 46,115,101,108,102, 46,100, + 105,109, 46, 46, 39, 93, 41, 59, 39, 41, 10, 9,101,108,115, + 101, 10, 9, 9,108,105,110,101, 32, 61, 32, 99,111,110, 99, + 97,116,112, 97,114, 97,109, 40,108,105,110,101, 44, 39, 32, + 61, 32, 40, 39, 44,116,121,112,101, 44,112,116,114, 44, 39, + 42, 41, 39, 44, 10, 9, 9, 39,109, 97,108,108,111, 99, 40, + 40, 39, 44,115,101,108,102, 46,100,105,109, 44, 39, 41, 42, + 115,105,122,101,111,102, 40, 39, 44,116,121,112,101, 44,112, + 116,114, 44, 39, 41, 41, 59, 39, 41, 10, 9,101,110,100, 10, + 32, 32,101,110,100, 10, 32,101,108,115,101, 10, 32, 32,108, + 111, 99, 97,108, 32,116, 32, 61, 32,105,115, 98, 97,115,105, + 99, 40,116,121,112,101, 41, 10, 32, 32,108,105,110,101, 32, + 61, 32, 99,111,110, 99, 97,116,112, 97,114, 97,109, 40,108, + 105,110,101, 44, 39, 32, 61, 32, 39, 41, 10, 32, 32,105,102, + 32,116, 32, 61, 61, 32, 39,115,116, 97,116,101, 39, 32,116, + 104,101,110, 10, 32, 32, 9,108,105,110,101, 32, 61, 32, 99, + 111,110, 99, 97,116,112, 97,114, 97,109, 40,108,105,110,101, + 44, 32, 39,116,111,108,117, 97, 95, 83, 59, 39, 41, 10, 32, + 32,101,108,115,101, 10, 32, 32, 9, 45, 45,112,114,105,110, + 116, 40, 34,116, 32,105,115, 32, 34, 46, 46,116,111,115,116, + 114,105,110,103, 40,116, 41, 46, 46, 34, 44, 32,112,116,114, + 32,105,115, 32, 34, 46, 46,116,111,115,116,114,105,110,103, + 40,115,101,108,102, 46,112,116,114, 41, 41, 10, 32, 32, 9, + 105,102, 32,116, 32, 61, 61, 32, 39,110,117,109, 98,101,114, + 39, 32, 97,110,100, 32,115,116,114,105,110,103, 46,102,105, + 110,100, 40,115,101,108,102, 46,112,116,114, 44, 32, 34, 37, + 42, 34, 41, 32,116,104,101,110, 10, 32, 32, 9, 9,116, 32, + 61, 32, 39,117,115,101,114,100, 97,116, 97, 39, 10, 32, 32, + 9,101,110,100, 10, 9,105,102, 32,110,111,116, 32,116, 32, + 97,110,100, 32,112,116,114, 61, 61, 39, 39, 32,116,104,101, + 110, 32,108,105,110,101, 32, 61, 32, 99,111,110, 99, 97,116, + 112, 97,114, 97,109, 40,108,105,110,101, 44, 39, 42, 39, 41, + 32,101,110,100, 10, 9,108,105,110,101, 32, 61, 32, 99,111, + 110, 99, 97,116,112, 97,114, 97,109, 40,108,105,110,101, 44, + 39, 40, 40, 39, 44,115,101,108,102, 46,109,111,100, 44,116, + 121,112,101, 41, 10, 9,105,102, 32,110,111,116, 32,116, 32, + 116,104,101,110, 10, 9, 9,108,105,110,101, 32, 61, 32, 99, + 111,110, 99, 97,116,112, 97,114, 97,109, 40,108,105,110,101, + 44, 39, 42, 39, 41, 10, 9,101,110,100, 10, 9,108,105,110, + 101, 32, 61, 32, 99,111,110, 99, 97,116,112, 97,114, 97,109, + 40,108,105,110,101, 44, 39, 41, 32, 39, 41, 10, 9,105,102, + 32,105,115,101,110,117,109, 40,110, 99,116,121,112,101, 41, + 32,116,104,101,110, 10, 9, 9,108,105,110,101, 32, 61, 32, + 99,111,110, 99, 97,116,112, 97,114, 97,109, 40,108,105,110, + 101, 44, 39, 40,105,110,116, 41, 32, 39, 41, 10, 9,101,110, + 100, 10, 9,108,111, 99, 97,108, 32,100,101,102, 32, 61, 32, + 48, 10, 9,105,102, 32,115,101,108,102, 46,100,101,102, 32, + 126, 61, 32, 39, 39, 32,116,104,101,110, 10, 9, 9,100,101, + 102, 32, 61, 32,115,101,108,102, 46,100,101,102, 10, 9, 9, + 105,102, 32, 40,112,116,114, 32, 61, 61, 32, 39, 39, 32,111, + 114, 32,115,101,108,102, 46,112,116,114, 32, 61, 61, 32, 39, + 38, 39, 41, 32, 97,110,100, 32,110,111,116, 32,116, 32,116, + 104,101,110, 10, 9, 9, 9,100,101,102, 32, 61, 32, 34, 40, + 118,111,105,100, 42, 41, 38, 40, 99,111,110,115,116, 32, 34, + 46, 46,116,121,112,101, 46, 46, 34, 41, 34, 46, 46,100,101, + 102, 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, 9,105, + 102, 32,116, 32,116,104,101,110, 10, 9, 9,108,105,110,101, + 32, 61, 32, 99,111,110, 99, 97,116,112, 97,114, 97,109, 40, + 108,105,110,101, 44, 39,116,111,108,117, 97, 95,116,111, 39, + 46, 46,116, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, 39, + 44,110, 97,114,103, 44, 39, 44, 39, 44,100,101,102, 44, 39, + 41, 41, 59, 39, 41, 10, 9,101,108,115,101, 10, 9, 9,108, + 111, 99, 97,108, 32,116,111, 95,102,117,110, 99, 32, 61, 32, + 103,101,116, 95,116,111, 95,102,117,110, 99,116,105,111,110, + 40,116,121,112,101, 41, 10, 9, 9,108,105,110,101, 32, 61, + 32, 99,111,110, 99, 97,116,112, 97,114, 97,109, 40,108,105, + 110,101, 44,116,111, 95,102,117,110, 99, 46, 46, 39, 40,116, + 111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, + 44, 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, 10, 9, + 101,110,100, 10, 32, 32,101,110,100, 10, 32,101,110,100, 10, + 9,114,101,116,117,114,110, 32,108,105,110,101, 10,101,110, + 100, 10, 10, 45, 45, 32, 68,101, 99,108, 97,114,101, 32,118, + 97,114,105, 97, 98,108,101, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, + 105,111,110, 58,100,101, 99,108, 97,114,101, 32, 40,110, 97, + 114,103, 41, 10, 32,105,102, 32,115,101,108,102, 46,100,105, + 109, 32,126, 61, 32, 39, 39, 32, 97,110,100, 32,116,111,110, + 117,109, 98,101,114, 40,115,101,108,102, 46,100,105,109, 41, + 61, 61,110,105,108, 32,116,104,101,110, 10, 9, 32,111,117, + 116,112,117,116, 40, 39, 35,105,102,100,101,102, 32, 95, 95, + 99,112,108,117,115,112,108,117,115, 92,110, 39, 41, 10, 9, + 9,111,117,116,112,117,116, 40,115,101,108,102, 58, 98,117, + 105,108,100,100,101, 99,108, 97,114, 97,116,105,111,110, 40, + 110, 97,114,103, 44,116,114,117,101, 41, 41, 10, 9, 9,111, + 117,116,112,117,116, 40, 39, 35,101,108,115,101, 92,110, 39, + 41, 10, 9, 9,111,117,116,112,117,116, 40,115,101,108,102, + 58, 98,117,105,108,100,100,101, 99,108, 97,114, 97,116,105, + 111,110, 40,110, 97,114,103, 44,102, 97,108,115,101, 41, 41, + 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,101,110,100, + 105,102, 92,110, 39, 41, 10, 9,101,108,115,101, 10, 9, 9, + 111,117,116,112,117,116, 40,115,101,108,102, 58, 98,117,105, + 108,100,100,101, 99,108, 97,114, 97,116,105,111,110, 40,110, + 97,114,103, 44,102, 97,108,115,101, 41, 41, 10, 9,101,110, + 100, 10,101,110,100, 10, 10, 45, 45, 32, 71,101,116, 32,112, + 97,114, 97,109,101,116,101,114, 32,118, 97,108,117,101, 10, + 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68, + 101, 99,108, 97,114, 97,116,105,111,110, 58,103,101,116, 97, + 114,114, 97,121, 32, 40,110, 97,114,103, 41, 10, 32,105,102, + 32,115,101,108,102, 46,100,105,109, 32,126, 61, 32, 39, 39, + 32,116,104,101,110, 10, 9, 32,108,111, 99, 97,108, 32,116, + 121,112,101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, + 46,116,121,112,101, 44, 39, 99,111,110,115,116, 32, 39, 44, + 39, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32,123, 39, 41, 10, 9, 32,111,117,116,112,117,116, 40, 39, + 35,105,102,110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 82, + 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, 32, 32,108,111, + 99, 97,108, 32,100,101,102, 59, 32,105,102, 32,115,101,108, + 102, 46,100,101,102,126, 61, 39, 39, 32,116,104,101,110, 32, + 100,101,102, 61, 49, 32,101,108,115,101, 32,100,101,102, 61, + 48, 32,101,110,100, 10, 9, 9,108,111, 99, 97,108, 32,116, + 32, 61, 32,105,115, 98, 97,115,105, 99, 40,116,121,112,101, + 41, 10, 9, 9,105,102, 32, 40,116, 41, 32,116,104,101,110, + 10, 9, 9, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32, 32,105,102, 32, 40, 33,116,111,108,117, 97, 95,105,115, + 39, 46, 46,116, 46, 46, 39, 97,114,114, 97,121, 40,116,111, + 108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44, + 39, 44,115,101,108,102, 46,100,105,109, 44, 39, 44, 39, 44, + 100,101,102, 44, 39, 44, 38,116,111,108,117, 97, 95,101,114, + 114, 41, 41, 39, 41, 10, 9, 9,101,108,115,101, 10, 9, 9, + 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, 32,105, + 102, 32, 40, 33,116,111,108,117, 97, 95,105,115,117,115,101, + 114,116,121,112,101, 97,114,114, 97,121, 40,116,111,108,117, + 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44, 34, 39, + 44,116,121,112,101, 44, 39, 34, 44, 39, 44,115,101,108,102, + 46,100,105,109, 44, 39, 44, 39, 44,100,101,102, 44, 39, 44, + 38,116,111,108,117, 97, 95,101,114,114, 41, 41, 39, 41, 10, + 9, 9,101,110,100, 10, 32, 32,111,117,116,112,117,116, 40, + 39, 32, 32, 32, 32,103,111,116,111, 32,116,111,108,117, 97, + 95,108,101,114,114,111,114, 59, 39, 41, 10, 32, 32,111,117, + 116,112,117,116, 40, 39, 32, 32, 32,101,108,115,101, 92,110, + 39, 41, 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,101, + 110,100,105,102, 92,110, 39, 41, 10, 32, 32,111,117,116,112, + 117,116, 40, 39, 32, 32, 32,123, 39, 41, 10, 32, 32,111,117, + 116,112,117,116, 40, 39, 32, 32, 32, 32,105,110,116, 32,105, + 59, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32, 32, 32,102,111,114, 40,105, 61, 48, 59, 32,105, 60, 39, + 46, 46,115,101,108,102, 46,100,105,109, 46, 46, 39, 59,105, + 43, 43, 41, 39, 41, 10, 32, 32,108,111, 99, 97,108, 32,116, + 32, 61, 32,105,115, 98, 97,115,105, 99, 40,116,121,112,101, + 41, 10, 32, 32,108,111, 99, 97,108, 32,112,116,114, 32, 61, + 32, 39, 39, 10, 32, 32,105,102, 32,115,101,108,102, 46,112, + 116,114,126, 61, 39, 39, 32,116,104,101,110, 32,112,116,114, + 32, 61, 32, 39, 42, 39, 32,101,110,100, 10, 32, 32,111,117, + 116,112,117,116, 40, 39, 32, 32, 32, 39, 44,115,101,108,102, + 46,110, 97,109,101, 46, 46, 39, 91,105, 93, 32, 61, 32, 39, + 41, 10, 32, 32,105,102, 32,110,111,116, 32,116, 32, 97,110, + 100, 32,112,116,114, 61, 61, 39, 39, 32,116,104,101,110, 32, + 111,117,116,112,117,116, 40, 39, 42, 39, 41, 32,101,110,100, + 10, 32, 32,111,117,116,112,117,116, 40, 39, 40, 40, 39, 44, + 116,121,112,101, 41, 10, 32, 32,105,102, 32,110,111,116, 32, + 116, 32,116,104,101,110, 10, 32, 32, 32,111,117,116,112,117, + 116, 40, 39, 42, 39, 41, 10, 32, 32,101,110,100, 10, 32, 32, + 111,117,116,112,117,116, 40, 39, 41, 32, 39, 41, 10, 32, 32, + 108,111, 99, 97,108, 32,100,101,102, 32, 61, 32, 48, 10, 32, + 32,105,102, 32,115,101,108,102, 46,100,101,102, 32,126, 61, + 32, 39, 39, 32,116,104,101,110, 32,100,101,102, 32, 61, 32, + 115,101,108,102, 46,100,101,102, 32,101,110,100, 10, 32, 32, + 105,102, 32,116, 32,116,104,101,110, 10, 32, 32, 32,111,117, + 116,112,117,116, 40, 39,116,111,108,117, 97, 95,116,111,102, + 105,101,108,100, 39, 46, 46,116, 46, 46, 39, 40,116,111,108, + 117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44,105, + 43, 49, 44, 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, + 10, 32, 32,101,108,115,101, 10, 32, 32, 32,111,117,116,112, + 117,116, 40, 39,116,111,108,117, 97, 95,116,111,102,105,101, + 108,100,117,115,101,114,116,121,112,101, 40,116,111,108,117, + 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44,105, 43, + 49, 44, 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, 10, + 32, 32,101,110,100, 10, 32, 32,111,117,116,112,117,116, 40, + 39, 32, 32, 32,125, 39, 41, 10, 32, 32,111,117,116,112,117, + 116, 40, 39, 32, 32,125, 39, 41, 10, 32,101,110,100, 10,101, + 110,100, 10, 10, 45, 45, 32, 71,101,116, 32,112, 97,114, 97, + 109,101,116,101,114, 32,118, 97,108,117,101, 10,102,117,110, + 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, 99,108, + 97,114, 97,116,105,111,110, 58,115,101,116, 97,114,114, 97, + 121, 32, 40,110, 97,114,103, 41, 10, 32,105,102, 32,110,111, + 116, 32,115,116,114,102,105,110,100, 40,115,101,108,102, 46, + 116,121,112,101, 44, 39, 99,111,110,115,116, 37,115, 43, 39, + 41, 32, 97,110,100, 32,115,101,108,102, 46,100,105,109, 32, + 126, 61, 32, 39, 39, 32,116,104,101,110, 10, 9, 32,108,111, + 99, 97,108, 32,116,121,112,101, 32, 61, 32,103,115,117, 98, + 40,115,101,108,102, 46,116,121,112,101, 44, 39, 99,111,110, + 115,116, 32, 39, 44, 39, 39, 41, 10, 32, 32,111,117,116,112, + 117,116, 40, 39, 32, 32,123, 39, 41, 10, 32, 32,111,117,116, + 112,117,116, 40, 39, 32, 32, 32,105,110,116, 32,105, 59, 39, + 41, 10, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, 32, + 102,111,114, 40,105, 61, 48, 59, 32,105, 60, 39, 46, 46,115, + 101,108,102, 46,100,105,109, 46, 46, 39, 59,105, 43, 43, 41, + 39, 41, 10, 32, 32,108,111, 99, 97,108, 32,116, 44, 99,116, + 32, 61, 32,105,115, 98, 97,115,105, 99, 40,116,121,112,101, + 41, 10, 32, 32,105,102, 32,116, 32,116,104,101,110, 10, 32, + 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, 32, 32,116, + 111,108,117, 97, 95,112,117,115,104,102,105,101,108,100, 39, + 46, 46,116, 46, 46, 39, 40,116,111,108,117, 97, 95, 83, 44, + 39, 44,110, 97,114,103, 44, 39, 44,105, 43, 49, 44, 40, 39, + 44, 99,116, 44, 39, 41, 39, 44,115,101,108,102, 46,110, 97, + 109,101, 44, 39, 91,105, 93, 41, 59, 39, 41, 10, 32, 32,101, + 108,115,101, 10, 32, 32, 32,105,102, 32,115,101,108,102, 46, + 112,116,114, 32, 61, 61, 32, 39, 39, 32,116,104,101,110, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, + 32,123, 39, 41, 10, 32, 32, 32, 32, 32,111,117,116,112,117, + 116, 40, 39, 35,105,102,100,101,102, 32, 95, 95, 99,112,108, + 117,115,112,108,117,115, 92,110, 39, 41, 10, 32, 32, 32, 32, + 32,111,117,116,112,117,116, 40, 39, 32, 32, 32, 32,118,111, + 105,100, 42, 32,116,111,108,117, 97, 95,111, 98,106, 32, 61, + 32, 77,116,111,108,117, 97, 95,110,101,119, 40, 40, 39, 44, + 116,121,112,101, 44, 39, 41, 40, 39, 44,115,101,108,102, 46, + 110, 97,109,101, 44, 39, 91,105, 93, 41, 41, 59, 39, 41, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, + 32, 32,116,111,108,117, 97, 95,112,117,115,104,102,105,101, + 108,100,117,115,101,114,116,121,112,101, 95, 97,110,100, 95, + 116, 97,107,101,111,119,110,101,114,115,104,105,112, 40,116, + 111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, + 44,105, 43, 49, 44,116,111,108,117, 97, 95,111, 98,106, 44, + 34, 39, 44,116,121,112,101, 44, 39, 34, 41, 59, 39, 41, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 35,101, + 108,115,101, 92,110, 39, 41, 10, 32, 32, 32, 32, 32,111,117, + 116,112,117,116, 40, 39, 32, 32, 32, 32,118,111,105,100, 42, + 32,116,111,108,117, 97, 95,111, 98,106, 32, 61, 32,116,111, + 108,117, 97, 95, 99,111,112,121, 40,116,111,108,117, 97, 95, + 83, 44, 40,118,111,105,100, 42, 41, 38, 39, 44,115,101,108, + 102, 46,110, 97,109,101, 44, 39, 91,105, 93, 44,115,105,122, + 101,111,102, 40, 39, 44,116,121,112,101, 44, 39, 41, 41, 59, + 39, 41, 10, 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, + 39, 32, 32, 32, 32,116,111,108,117, 97, 95,112,117,115,104, + 102,105,101,108,100,117,115,101,114,116,121,112,101, 40,116, + 111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, + 44,105, 43, 49, 44,116,111,108,117, 97, 95,111, 98,106, 44, + 34, 39, 44,116,121,112,101, 44, 39, 34, 41, 59, 39, 41, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 35,101, + 110,100,105,102, 92,110, 39, 41, 10, 32, 32, 32, 32, 32,111, + 117,116,112,117,116, 40, 39, 32, 32, 32,125, 39, 41, 10, 32, + 32, 32,101,108,115,101, 10, 32, 32, 32, 32,111,117,116,112, + 117,116, 40, 39, 32, 32, 32,116,111,108,117, 97, 95,112,117, + 115,104,102,105,101,108,100,117,115,101,114,116,121,112,101, + 40,116,111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, + 44, 39, 44,105, 43, 49, 44, 40,118,111,105,100, 42, 41, 39, + 44,115,101,108,102, 46,110, 97,109,101, 44, 39, 91,105, 93, + 44, 34, 39, 44,116,121,112,101, 44, 39, 34, 41, 59, 39, 41, + 10, 32, 32, 32,101,110,100, 10, 32, 32,101,110,100, 10, 32, + 32,111,117,116,112,117,116, 40, 39, 32, 32,125, 39, 41, 10, + 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, 70,114, + 101,101, 32,100,121,110, 97,109,105, 99, 97,108,108,121, 32, + 97,108,108,111, 99, 97,116,101,100, 32, 97,114,114, 97,121, + 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, + 68,101, 99,108, 97,114, 97,116,105,111,110, 58,102,114,101, + 101, 97,114,114, 97,121, 32, 40, 41, 10, 32,105,102, 32,115, + 101,108,102, 46,100,105,109, 32,126, 61, 32, 39, 39, 32, 97, + 110,100, 32,116,111,110,117,109, 98,101,114, 40,115,101,108, + 102, 46,100,105,109, 41, 61, 61,110,105,108, 32,116,104,101, + 110, 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,105,102, + 100,101,102, 32, 95, 95, 99,112,108,117,115,112,108,117,115, + 92,110, 39, 41, 10, 9, 9,111,117,116,112,117,116, 40, 39, + 32, 32, 77,116,111,108,117, 97, 95,100,101,108,101,116,101, + 95,100,105,109, 40, 39, 44,115,101,108,102, 46,110, 97,109, + 101, 44, 39, 41, 59, 39, 41, 10, 9, 32,111,117,116,112,117, + 116, 40, 39, 35,101,108,115,101, 92,110, 39, 41, 10, 32, 32, + 111,117,116,112,117,116, 40, 39, 32, 32,102,114,101,101, 40, + 39, 44,115,101,108,102, 46,110, 97,109,101, 44, 39, 41, 59, + 39, 41, 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,101, + 110,100,105,102, 92,110, 39, 41, 10, 32,101,110,100, 10,101, + 110,100, 10, 10, 45, 45, 32, 80, 97,115,115, 32,112, 97,114, + 97,109,101,116,101,114, 10,102,117,110, 99,116,105,111,110, + 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105, + 111,110, 58,112, 97,115,115,112, 97,114, 32, 40, 41, 10, 32, + 105,102, 32,115,101,108,102, 46,112,116,114, 61, 61, 39, 38, + 39, 32, 97,110,100, 32,110,111,116, 32,105,115, 98, 97,115, + 105, 99, 40,115,101,108,102, 46,116,121,112,101, 41, 32,116, + 104,101,110, 10, 32, 32,111,117,116,112,117,116, 40, 39, 42, + 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 41, 10, 32, + 101,108,115,101,105,102, 32,115,101,108,102, 46,114,101,116, + 61, 61, 39, 42, 39, 32,116,104,101,110, 10, 32, 32,111,117, + 116,112,117,116, 40, 39, 38, 39, 46, 46,115,101,108,102, 46, + 110, 97,109,101, 41, 10, 32,101,108,115,101, 10, 32, 32,111, + 117,116,112,117,116, 40,115,101,108,102, 46,110, 97,109,101, + 41, 10, 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, + 82,101,116,117,114,110, 32,112, 97,114, 97,109,101,116,101, + 114, 32,118, 97,108,117,101, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, + 105,111,110, 58,114,101,116,118, 97,108,117,101, 32, 40, 41, + 10, 32,105,102, 32,115,101,108,102, 46,114,101,116, 32,126, + 61, 32, 39, 39, 32,116,104,101,110, 10, 32, 32,108,111, 99, + 97,108, 32,116, 44, 99,116, 32, 61, 32,105,115, 98, 97,115, + 105, 99, 40,115,101,108,102, 46,116,121,112,101, 41, 10, 32, + 32,105,102, 32,116, 32, 97,110,100, 32,116,126, 61, 39, 39, + 32,116,104,101,110, 10, 32, 32, 32,111,117,116,112,117,116, + 40, 39, 32, 32, 32,116,111,108,117, 97, 95,112,117,115,104, + 39, 46, 46,116, 46, 46, 39, 40,116,111,108,117, 97, 95, 83, + 44, 40, 39, 44, 99,116, 44, 39, 41, 39, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 39, 41, 59, 39, 41, 10, 32, + 32,101,108,115,101, 10, 32, 32, 32,108,111, 99, 97,108, 32, + 112,117,115,104, 95,102,117,110, 99, 32, 61, 32,103,101,116, + 95,112,117,115,104, 95,102,117,110, 99,116,105,111,110, 40, + 115,101,108,102, 46,116,121,112,101, 41, 10, 32, 32, 32,111, + 117,116,112,117,116, 40, 39, 32, 32, 32, 39, 44,112,117,115, + 104, 95,102,117,110, 99, 44, 39, 40,116,111,108,117, 97, 95, + 83, 44, 40,118,111,105,100, 42, 41, 39, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 39, 44, 34, 39, 44,115,101, + 108,102, 46,116,121,112,101, 44, 39, 34, 41, 59, 39, 41, 10, + 32, 32,101,110,100, 10, 32, 32,114,101,116,117,114,110, 32, + 49, 10, 32,101,110,100, 10, 32,114,101,116,117,114,110, 32, + 48, 10,101,110,100, 10, 10, 45, 45, 32, 73,110,116,101,114, + 110, 97,108, 32, 99,111,110,115,116,114,117, 99,116,111,114, + 10,102,117,110, 99,116,105,111,110, 32, 95, 68,101, 99,108, + 97,114, 97,116,105,111,110, 32, 40,116, 41, 10, 10, 32,115, + 101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, 44, 99, + 108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, + 41, 10, 32,116, 58, 98,117,105,108,100,110, 97,109,101,115, + 40, 41, 10, 32,116, 58, 99,104,101, 99,107,110, 97,109,101, + 40, 41, 10, 32,116, 58, 99,104,101, 99,107,116,121,112,101, + 40, 41, 10, 32,108,111, 99, 97,108, 32,102,116, 32, 61, 32, + 102,105,110,100,116,121,112,101, 40,116, 46,116,121,112,101, + 41, 32,111,114, 32,116, 46,116,121,112,101, 10, 32,105,102, + 32,110,111,116, 32,105,115,101,110,117,109, 40,102,116, 41, + 32,116,104,101,110, 10, 9,116, 46,109,111,100, 44, 32,116, + 46,116,121,112,101, 32, 61, 32, 97,112,112,108,121,116,121, + 112,101,100,101,102, 40,116, 46,109,111,100, 44, 32,102,116, + 41, 10, 32,101,110,100, 10, 10, 32,105,102, 32,116, 46,107, + 105,110,100, 61, 61, 34,118, 97,114, 34, 32, 97,110,100, 32, + 40,115,116,114,105,110,103, 46,102,105,110,100, 40,116, 46, + 109,111,100, 44, 32, 34,116,111,108,117, 97, 95,112,114,111, + 112,101,114,116,121, 37,115, 34, 41, 32,111,114, 32,115,116, + 114,105,110,103, 46,102,105,110,100, 40,116, 46,109,111,100, + 44, 32, 34,116,111,108,117, 97, 95,112,114,111,112,101,114, + 116,121, 36, 34, 41, 41, 32,116,104,101,110, 10, 32, 9,116, + 46,109,111,100, 32, 61, 32,115,116,114,105,110,103, 46,103, + 115,117, 98, 40,116, 46,109,111,100, 44, 32, 34,116,111,108, + 117, 97, 95,112,114,111,112,101,114,116,121, 34, 44, 32, 34, + 116,111,108,117, 97, 95,112,114,111,112,101,114,116,121, 95, + 95, 34, 46, 46,103,101,116, 95,112,114,111,112,101,114,116, + 121, 95,116,121,112,101, 40, 41, 41, 10, 32,101,110,100, 10, + 10, 32,114,101,116,117,114,110, 32,116, 10,101,110,100, 10, + 10, 45, 45, 32, 67,111,110,115,116,114,117, 99,116,111,114, + 10, 45, 45, 32, 69,120,112,101, 99,116,115, 32,116,104,101, + 32,115,116,114,105,110,103, 32,100,101, 99,108, 97,114, 97, + 116,105,111,110, 46, 10, 45, 45, 32, 84,104,101, 32,107,105, + 110,100, 32,111,102, 32,100,101, 99,108, 97,114, 97,116,105, + 111,110, 32, 99, 97,110, 32, 98,101, 32, 34,118, 97,114, 34, + 32,111,114, 32, 34,102,117,110, 99, 34, 46, 10,102,117,110, + 99,116,105,111,110, 32, 68,101, 99,108, 97,114, 97,116,105, + 111,110, 32, 40,115, 44,107,105,110,100, 44,105,115, 95,112, + 97,114, 97,109,101,116,101,114, 41, 10, 10, 32, 45, 45, 32, + 101,108,105,109,105,110, 97,116,101, 32,115,112, 97, 99,101, + 115, 32,105,102, 32,100,101,102, 97,117,108,116, 32,118, 97, + 108,117,101, 32,105,115, 32,112,114,111,118,105,100,101,100, + 10, 32,115, 32, 61, 32,103,115,117, 98, 40,115, 44, 34, 37, + 115, 42, 61, 37,115, 42, 34, 44, 34, 61, 34, 41, 10, 32,115, + 32, 61, 32,103,115,117, 98, 40,115, 44, 32, 34, 37,115, 42, + 60, 34, 44, 32, 34, 60, 34, 41, 10, 10, 32,108,111, 99, 97, + 108, 32,100,101,102, 98, 44,116,109,112,100,101,102, 10, 32, + 100,101,102, 98, 44, 95, 44,116,109,112,100,101,102, 32, 61, + 32,115,116,114,105,110,103, 46,102,105,110,100, 40,115, 44, + 32, 34, 40, 61, 46, 42, 41, 36, 34, 41, 10, 32,105,102, 32, + 100,101,102, 98, 32,116,104,101,110, 10, 32, 9,115, 32, 61, + 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,115, 44, + 32, 34, 61, 46, 42, 36, 34, 44, 32, 34, 34, 41, 10, 32,101, + 108,115,101, 10, 32, 9,116,109,112,100,101,102, 32, 61, 32, + 39, 39, 10, 32,101,110,100, 10, 32,105,102, 32,107,105,110, + 100, 32, 61, 61, 32, 34,118, 97,114, 34, 32,116,104,101,110, + 10, 32, 32, 45, 45, 32, 99,104,101, 99,107, 32,116,104,101, + 32,102,111,114,109, 58, 32,118,111,105,100, 10, 32, 32,105, + 102, 32,115, 32, 61, 61, 32, 39, 39, 32,111,114, 32,115, 32, + 61, 61, 32, 39,118,111,105,100, 39, 32,116,104,101,110, 10, + 32, 32, 32,114,101,116,117,114,110, 32, 95, 68,101, 99,108, + 97,114, 97,116,105,111,110,123,116,121,112,101, 32, 61, 32, + 39,118,111,105,100, 39, 44, 32,107,105,110,100, 32, 61, 32, + 107,105,110,100, 44, 32,105,115, 95,112, 97,114, 97,109,101, + 116,101,114, 32, 61, 32,105,115, 95,112, 97,114, 97,109,101, + 116,101,114,125, 10, 32, 32,101,110,100, 10, 32,101,110,100, + 10, 10, 32, 45, 45, 32, 99,104,101, 99,107, 32,116,104,101, + 32,102,111,114,109, 58, 32,109,111,100, 32,116,121,112,101, + 42, 38, 32,110, 97,109,101, 10, 32,108,111, 99, 97,108, 32, + 116, 32, 61, 32,115,112,108,105,116, 95, 99, 95,116,111,107, + 101,110,115, 40,115, 44, 39, 37, 42, 37,115, 42, 38, 39, 41, + 10, 32,105,102, 32,116, 46,110, 32, 61, 61, 32, 50, 32,116, + 104,101,110, 10, 32, 32,105,102, 32,107,105,110,100, 32, 61, + 61, 32, 39,102,117,110, 99, 39, 32,116,104,101,110, 10, 32, + 32, 32,101,114,114,111,114, 40, 34, 35,105,110,118, 97,108, + 105,100, 32,102,117,110, 99,116,105,111,110, 32,114,101,116, + 117,114,110, 32,116,121,112,101, 58, 32, 34, 46, 46,115, 41, + 10, 32, 32,101,110,100, 10, 32, 32, 45, 45,108,111, 99, 97, + 108, 32,109, 32, 61, 32,115,112,108,105,116, 40,116, 91, 49, + 93, 44, 39, 37,115, 37,115, 42, 39, 41, 10, 32, 32,108,111, + 99, 97,108, 32,109, 32, 61, 32,115,112,108,105,116, 95, 99, + 95,116,111,107,101,110,115, 40,116, 91, 49, 93, 44, 39, 37, + 115, 43, 39, 41, 10, 32, 32,114,101,116,117,114,110, 32, 95, + 68,101, 99,108, 97,114, 97,116,105,111,110,123, 10, 32, 32, + 32,110, 97,109,101, 32, 61, 32,116, 91, 50, 93, 46, 46,116, + 109,112,100,101,102, 44, 10, 32, 32, 32,112,116,114, 32, 61, + 32, 39, 42, 39, 44, 10, 32, 32, 32,114,101,116, 32, 61, 32, + 39, 38, 39, 44, 10, 32, 32, 32, 45, 45,116,121,112,101, 32, + 61, 32,114,101, 98,117,105,108,100, 95,116,101,109,112,108, + 97,116,101, 40,109, 91,109, 46,110, 93, 44, 32,116, 98, 44, + 32,116,105,109,112,108, 41, 44, 10, 32, 32, 32,116,121,112, + 101, 32, 61, 32,109, 91,109, 46,110, 93, 44, 10, 32, 32, 32, + 109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, 40,109, 44, + 49, 44,109, 46,110, 45, 49, 41, 44, 10, 32, 32, 32,105,115, + 95,112, 97,114, 97,109,101,116,101,114, 32, 61, 32,105,115, + 95,112, 97,114, 97,109,101,116,101,114, 44, 10, 32, 32, 32, + 107,105,110,100, 32, 61, 32,107,105,110,100, 10, 32, 32,125, + 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, 99,104,101, 99, + 107, 32,116,104,101, 32,102,111,114,109, 58, 32,109,111,100, + 32,116,121,112,101, 42, 42, 32,110, 97,109,101, 10, 32,116, + 32, 61, 32,115,112,108,105,116, 95, 99, 95,116,111,107,101, + 110,115, 40,115, 44, 39, 37, 42, 37,115, 42, 37, 42, 39, 41, + 10, 32,105,102, 32,116, 46,110, 32, 61, 61, 32, 50, 32,116, + 104,101,110, 10, 32, 32,105,102, 32,107,105,110,100, 32, 61, + 61, 32, 39,102,117,110, 99, 39, 32,116,104,101,110, 10, 32, + 32, 32,101,114,114,111,114, 40, 34, 35,105,110,118, 97,108, + 105,100, 32,102,117,110, 99,116,105,111,110, 32,114,101,116, + 117,114,110, 32,116,121,112,101, 58, 32, 34, 46, 46,115, 41, + 10, 32, 32,101,110,100, 10, 32, 32, 45, 45,108,111, 99, 97, + 108, 32,109, 32, 61, 32,115,112,108,105,116, 40,116, 91, 49, + 93, 44, 39, 37,115, 37,115, 42, 39, 41, 10, 32, 32,108,111, + 99, 97,108, 32,109, 32, 61, 32,115,112,108,105,116, 95, 99, + 95,116,111,107,101,110,115, 40,116, 91, 49, 93, 44, 39, 37, + 115, 43, 39, 41, 10, 32, 32,114,101,116,117,114,110, 32, 95, + 68,101, 99,108, 97,114, 97,116,105,111,110,123, 10, 32, 32, + 32,110, 97,109,101, 32, 61, 32,116, 91, 50, 93, 46, 46,116, + 109,112,100,101,102, 44, 10, 32, 32, 32,112,116,114, 32, 61, + 32, 39, 42, 39, 44, 10, 32, 32, 32,114,101,116, 32, 61, 32, + 39, 42, 39, 44, 10, 32, 32, 32, 45, 45,116,121,112,101, 32, + 61, 32,114,101, 98,117,105,108,100, 95,116,101,109,112,108, + 97,116,101, 40,109, 91,109, 46,110, 93, 44, 32,116, 98, 44, + 32,116,105,109,112,108, 41, 44, 10, 32, 32, 32,116,121,112, + 101, 32, 61, 32,109, 91,109, 46,110, 93, 44, 10, 32, 32, 32, + 109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, 40,109, 44, + 49, 44,109, 46,110, 45, 49, 41, 44, 10, 32, 32, 32,105,115, + 95,112, 97,114, 97,109,101,116,101,114, 32, 61, 32,105,115, + 95,112, 97,114, 97,109,101,116,101,114, 44, 10, 32, 32, 32, + 107,105,110,100, 32, 61, 32,107,105,110,100, 10, 32, 32,125, + 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, 99,104,101, 99, + 107, 32,116,104,101, 32,102,111,114,109, 58, 32,109,111,100, + 32,116,121,112,101, 38, 32,110, 97,109,101, 10, 32,116, 32, + 61, 32,115,112,108,105,116, 95, 99, 95,116,111,107,101,110, + 115, 40,115, 44, 39, 38, 39, 41, 10, 32,105,102, 32,116, 46, + 110, 32, 61, 61, 32, 50, 32,116,104,101,110, 10, 32, 32, 45, + 45,108,111, 99, 97,108, 32,109, 32, 61, 32,115,112,108,105, + 116, 40,116, 91, 49, 93, 44, 39, 37,115, 37,115, 42, 39, 41, + 10, 32, 32,108,111, 99, 97,108, 32,109, 32, 61, 32,115,112, + 108,105,116, 95, 99, 95,116,111,107,101,110,115, 40,116, 91, + 49, 93, 44, 39, 37,115, 43, 39, 41, 10, 32, 32,114,101,116, + 117,114,110, 32, 95, 68,101, 99,108, 97,114, 97,116,105,111, + 110,123, 10, 32, 32, 32,110, 97,109,101, 32, 61, 32,116, 91, + 50, 93, 46, 46,116,109,112,100,101,102, 44, 10, 32, 32, 32, + 112,116,114, 32, 61, 32, 39, 38, 39, 44, 10, 32, 32, 32, 45, + 45,116,121,112,101, 32, 61, 32,114,101, 98,117,105,108,100, + 95,116,101,109,112,108, 97,116,101, 40,109, 91,109, 46,110, + 93, 44, 32,116, 98, 44, 32,116,105,109,112,108, 41, 44, 10, + 32, 32, 32,116,121,112,101, 32, 61, 32,109, 91,109, 46,110, + 93, 44, 10, 32, 32, 32,109,111,100, 32, 61, 32, 99,111,110, + 99, 97,116, 40,109, 44, 49, 44,109, 46,110, 45, 49, 41, 44, + 10, 32, 32, 32,105,115, 95,112, 97,114, 97,109,101,116,101, + 114, 32, 61, 32,105,115, 95,112, 97,114, 97,109,101,116,101, + 114, 44, 10, 32, 32, 32,107,105,110,100, 32, 61, 32,107,105, + 110,100, 10, 32, 32,125, 10, 32,101,110,100, 10, 10, 32, 45, + 45, 32, 99,104,101, 99,107, 32,116,104,101, 32,102,111,114, + 109, 58, 32,109,111,100, 32,116,121,112,101, 42, 32,110, 97, + 109,101, 10, 32,108,111, 99, 97,108, 32,115, 49, 32, 61, 32, + 103,115,117, 98, 40,115, 44, 34, 40, 37, 98, 92, 91, 92, 93, + 41, 34, 44,102,117,110, 99,116,105,111,110, 32, 40,110, 41, + 32,114,101,116,117,114,110, 32,103,115,117, 98, 40,110, 44, + 39, 37, 42, 39, 44, 39, 92, 49, 39, 41, 32,101,110,100, 41, + 10, 32,116, 32, 61, 32,115,112,108,105,116, 95, 99, 95,116, + 111,107,101,110,115, 40,115, 49, 44, 39, 37, 42, 39, 41, 10, + 32,105,102, 32,116, 46,110, 32, 61, 61, 32, 50, 32,116,104, + 101,110, 10, 32, 32,116, 91, 50, 93, 32, 61, 32,103,115,117, + 98, 40,116, 91, 50, 93, 44, 39, 92, 49, 39, 44, 39, 37, 42, + 39, 41, 32, 45, 45, 32,114,101,115,116,111,114,101, 32, 42, + 32,105,110, 32,100,105,109,101,110,115,105,111,110, 32,101, + 120,112,114,101,115,115,105,111,110, 10, 32, 32, 45, 45,108, + 111, 99, 97,108, 32,109, 32, 61, 32,115,112,108,105,116, 40, + 116, 91, 49, 93, 44, 39, 37,115, 37,115, 42, 39, 41, 10, 32, + 32,108,111, 99, 97,108, 32,109, 32, 61, 32,115,112,108,105, + 116, 95, 99, 95,116,111,107,101,110,115, 40,116, 91, 49, 93, + 44, 39, 37,115, 43, 39, 41, 10, 32, 32,114,101,116,117,114, + 110, 32, 95, 68,101, 99,108, 97,114, 97,116,105,111,110,123, + 10, 32, 32, 32,110, 97,109,101, 32, 61, 32,116, 91, 50, 93, + 46, 46,116,109,112,100,101,102, 44, 10, 32, 32, 32,112,116, + 114, 32, 61, 32, 39, 42, 39, 44, 10, 32, 32, 32,116,121,112, + 101, 32, 61, 32,109, 91,109, 46,110, 93, 44, 10, 32, 32, 32, + 45, 45,116,121,112,101, 32, 61, 32,114,101, 98,117,105,108, + 100, 95,116,101,109,112,108, 97,116,101, 40,109, 91,109, 46, + 110, 93, 44, 32,116, 98, 44, 32,116,105,109,112,108, 41, 44, + 10, 32, 32, 32,109,111,100, 32, 61, 32, 99,111,110, 99, 97, + 116, 40,109, 44, 49, 44,109, 46,110, 45, 49, 41, 32, 32, 32, + 44, 10, 32, 32, 32,105,115, 95,112, 97,114, 97,109,101,116, + 101,114, 32, 61, 32,105,115, 95,112, 97,114, 97,109,101,116, + 101,114, 44, 10, 32, 32, 32,107,105,110,100, 32, 61, 32,107, + 105,110,100, 10, 32, 32,125, 10, 32,101,110,100, 10, 10, 32, + 105,102, 32,107,105,110,100, 32, 61, 61, 32, 39,118, 97,114, + 39, 32,116,104,101,110, 10, 32, 32, 45, 45, 32, 99,104,101, + 99,107, 32,116,104,101, 32,102,111,114,109, 58, 32,109,111, + 100, 32,116,121,112,101, 32,110, 97,109,101, 10, 32, 32, 45, + 45,116, 32, 61, 32,115,112,108,105,116, 40,115, 44, 39, 37, + 115, 37,115, 42, 39, 41, 10, 32, 32,116, 32, 61, 32,115,112, + 108,105,116, 95, 99, 95,116,111,107,101,110,115, 40,115, 44, + 39, 37,115, 43, 39, 41, 10, 32, 32,108,111, 99, 97,108, 32, + 118, 10, 32, 32,105,102, 32,102,105,110,100,116,121,112,101, + 40,116, 91,116, 46,110, 93, 41, 32,116,104,101,110, 32,118, + 32, 61, 32, 99,114,101, 97,116,101, 95,118, 97,114,110, 97, + 109,101, 40, 41, 32,101,108,115,101, 32,118, 32, 61, 32,116, + 91,116, 46,110, 93, 59, 32,116, 46,110, 32, 61, 32,116, 46, + 110, 45, 49, 32,101,110,100, 10, 32, 32,114,101,116,117,114, + 110, 32, 95, 68,101, 99,108, 97,114, 97,116,105,111,110,123, + 10, 32, 32, 32,110, 97,109,101, 32, 61, 32,118, 46, 46,116, + 109,112,100,101,102, 44, 10, 32, 32, 32, 45, 45,116,121,112, + 101, 32, 61, 32,114,101, 98,117,105,108,100, 95,116,101,109, + 112,108, 97,116,101, 40,116, 91,116, 46,110, 93, 44, 32,116, + 98, 44, 32,116,105,109,112,108, 41, 44, 10, 32, 32, 32,116, + 121,112,101, 32, 61, 32,116, 91,116, 46,110, 93, 44, 10, 32, + 32, 32,109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, 40, + 116, 44, 49, 44,116, 46,110, 45, 49, 41, 44, 10, 32, 32, 32, + 105,115, 95,112, 97,114, 97,109,101,116,101,114, 32, 61, 32, + 105,115, 95,112, 97,114, 97,109,101,116,101,114, 44, 10, 32, + 32, 32,107,105,110,100, 32, 61, 32,107,105,110,100, 10, 32, + 32,125, 10, 10, 32,101,108,115,101, 32, 45, 45, 32,107,105, + 110,100, 32, 61, 61, 32, 34,102,117,110, 99, 34, 10, 10, 32, + 32, 45, 45, 32, 99,104,101, 99,107, 32,116,104,101, 32,102, + 111,114,109, 58, 32,109,111,100, 32,116,121,112,101, 32,110, + 97,109,101, 10, 32, 32, 45, 45,116, 32, 61, 32,115,112,108, + 105,116, 40,115, 44, 39, 37,115, 37,115, 42, 39, 41, 10, 32, + 32,116, 32, 61, 32,115,112,108,105,116, 95, 99, 95,116,111, + 107,101,110,115, 40,115, 44, 39, 37,115, 43, 39, 41, 10, 32, + 32,108,111, 99, 97,108, 32,118, 32, 61, 32,116, 91,116, 46, + 110, 93, 32, 32, 45, 45, 32,108, 97,115,116, 32,119,111,114, + 100, 32,105,115, 32,116,104,101, 32,102,117,110, 99,116,105, + 111,110, 32,110, 97,109,101, 10, 32, 32,108,111, 99, 97,108, + 32,116,112, 44,109,100, 10, 32, 32,105,102, 32,116, 46,110, + 62, 49, 32,116,104,101,110, 10, 32, 32, 32,116,112, 32, 61, + 32,116, 91,116, 46,110, 45, 49, 93, 10, 32, 32, 32,109,100, + 32, 61, 32, 99,111,110, 99, 97,116, 40,116, 44, 49, 44,116, + 46,110, 45, 50, 41, 10, 32, 32,101,110,100, 10, 32, 32, 45, + 45,105,102, 32,116,112, 32,116,104,101,110, 32,116,112, 32, + 61, 32,114,101, 98,117,105,108,100, 95,116,101,109,112,108, + 97,116,101, 40,116,112, 44, 32,116, 98, 44, 32,116,105,109, + 112,108, 41, 32,101,110,100, 10, 32, 32,114,101,116,117,114, + 110, 32, 95, 68,101, 99,108, 97,114, 97,116,105,111,110,123, + 10, 32, 32, 32,110, 97,109,101, 32, 61, 32,118, 44, 10, 32, + 32, 32,116,121,112,101, 32, 61, 32,116,112, 44, 10, 32, 32, + 32,109,111,100, 32, 61, 32,109,100, 44, 10, 32, 32, 32,105, + 115, 95,112, 97,114, 97,109,101,116,101,114, 32, 61, 32,105, + 115, 95,112, 97,114, 97,109,101,116,101,114, 44, 10, 32, 32, + 32,107,105,110,100, 32, 61, 32,107,105,110,100, 10, 32, 32, + 125, 10, 32,101,110,100, 10, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/declaration.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,118, 97,114,105, 97, + 98,108,101, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114, + 105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, + 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, + 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, + 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73, + 100, 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99, + 111,100,101, 32,105,115, 32,102,114,101,101, 32,115,111,102, + 116,119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32, + 114,101,100,105,115,116,114,105, 98,117,116,101, 32,105,116, + 32, 97,110,100, 47,111,114, 32,109,111,100,105,102,121, 32, + 105,116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116, + 119, 97,114,101, 32,112,114,111,118,105,100,101,100, 32,104, + 101,114,101,117,110,100,101,114, 32,105,115, 32,111,110, 32, + 97,110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105, + 115, 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97, + 117,116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98, + 108,105,103, 97,116,105,111,110, 32,116,111, 32,112,114,111, + 118,105,100,101, 32,109, 97,105,110,116,101,110, 97,110, 99, + 101, 44, 32,115,117,112,112,111,114,116, 44, 32,117,112,100, + 97,116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99, + 101,109,101,110,116,115, 44, 32,111,114, 32,109,111,100,105, + 102,105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 45, 45, + 32, 86, 97,114,105, 97, 98,108,101, 32, 99,108, 97,115,115, + 10, 45, 45, 32, 82,101,112,114,101,115,101,110,116,115, 32, + 97, 32,101,120,116,101,114,110, 32,118, 97,114,105, 97, 98, + 108,101, 32,111,114, 32, 97, 32,112,117, 98,108,105, 99, 32, + 109,101,109, 98,101,114, 32,111,102, 32, 97, 32, 99,108, 97, + 115,115, 46, 10, 45, 45, 32, 83,116,111,114,101,115, 32, 97, + 108,108, 32,102,105,101,108,100,115, 32,112,114,101,115,101, + 110,116, 32,105,110, 32, 97, 32,100,101, 99,108, 97,114, 97, + 116,105,111,110, 46, 10, 99,108, 97,115,115, 86, 97,114,105, + 97, 98,108,101, 32, 61, 32,123, 10, 32, 95,103,101,116, 32, + 61, 32,123,125, 44, 32, 32, 32, 45, 45, 32,109, 97,112,112, + 101,100, 32,103,101,116, 32,102,117,110, 99,116,105,111,110, + 115, 10, 32, 95,115,101,116, 32, 61, 32,123,125, 44, 32, 32, + 32, 45, 45, 32,109, 97,112,112,101,100, 32,115,101,116, 32, + 102,117,110, 99,116,105,111,110,115, 10,125, 10, 99,108, 97, + 115,115, 86, 97,114,105, 97, 98,108,101, 46, 95, 95,105,110, + 100,101,120, 32, 61, 32, 99,108, 97,115,115, 86, 97,114,105, + 97, 98,108,101, 10,115,101,116,109,101,116, 97,116, 97, 98, + 108,101, 40, 99,108, 97,115,115, 86, 97,114,105, 97, 98,108, + 101, 44, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, + 105,111,110, 41, 10, 10, 45, 45, 32, 80,114,105,110,116, 32, + 109,101,116,104,111,100, 10,102,117,110, 99,116,105,111,110, + 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98,108,101, 58, + 112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108, + 111,115,101, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 86, 97,114,105, 97, 98,108,101,123, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32,109,111,100, 32, 32, 61, 32, 39, 34, 46, 46,115, + 101,108,102, 46,109,111,100, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 112,116,114, 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, + 46,112,116,114, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114, + 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,110, 97, + 109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,110, + 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, 32,105,102, 32, + 115,101,108,102, 46,100,105,109, 32,116,104,101,110, 32,112, + 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,100, + 105,109, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,100, + 105,109, 46, 46, 34, 39, 44, 34, 41, 32,101,110,100, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 100,101,102, 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, + 46,100,101,102, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114, + 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,114,101, + 116, 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,114, + 101,116, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114,105,110, + 116, 40,105,100,101,110,116, 46, 46, 34,125, 34, 46, 46, 99, + 108,111,115,101, 41, 10,101,110,100, 10, 10, 45, 45, 32, 71, + 101,110,101,114, 97,116,101,115, 32, 67, 32,102,117,110, 99, + 116,105,111,110, 32,110, 97,109,101, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98, + 108,101, 58, 99,102,117,110, 99,110, 97,109,101, 32, 40,112, + 114,101,102,105,120, 41, 10, 32,108,111, 99, 97,108, 32,112, + 97,114,101,110,116, 32, 61, 32, 34, 34, 10, 32,108,111, 99, + 97,108, 32,117,110,115,105,103,110,101,100, 32, 61, 32, 34, + 34, 10, 32,108,111, 99, 97,108, 32,112,116,114, 32, 61, 32, + 34, 34, 10, 10, 32,108,111, 99, 97,108, 32,112, 32, 61, 32, + 115,101,108,102, 58,105,110,109,111,100,117,108,101, 40, 41, + 32,111,114, 32,115,101,108,102, 58,105,110,110, 97,109,101, + 115,112, 97, 99,101, 40, 41, 32,111,114, 32,115,101,108,102, + 58,105,110, 99,108, 97,115,115, 40, 41, 10, 10, 32,105,102, + 32,112, 32,116,104,101,110, 10, 32, 9,105,102, 32,115,101, + 108,102, 46,112, 97,114,101,110,116, 46, 99,108, 97,115,115, + 116,121,112,101, 32, 61, 61, 32, 39, 99,108, 97,115,115, 39, + 32,116,104,101,110, 10, 9, 9,112, 97,114,101,110,116, 32, + 61, 32, 34, 95, 34, 32, 46, 46, 32,115,101,108,102, 46,112, + 97,114,101,110,116, 46,116,121,112,101, 10, 9,101,108,115, + 101, 10, 9, 32, 32,112, 97,114,101,110,116, 32, 61, 32, 34, + 95, 34, 32, 46, 46, 32,112, 10, 9,101,110,100, 10, 32,101, + 110,100, 10, 10, 32,105,102, 32,115,116,114,102,105,110,100, + 40,115,101,108,102, 46,109,111,100, 44, 34, 40,117,110,115, + 105,103,110,101,100, 41, 34, 41, 32,116,104,101,110, 10, 32, + 32,117,110,115,105,103,110,101,100, 32, 61, 32, 34, 95,117, + 110,115,105,103,110,101,100, 34, 10, 32,101,110,100, 10, 10, + 32,105,102, 32,115,101,108,102, 46,112,116,114, 32, 61, 61, + 32, 34, 42, 34, 32,116,104,101,110, 32,112,116,114, 32, 61, + 32, 34, 95,112,116,114, 34, 10, 32,101,108,115,101,105,102, + 32,115,101,108,102, 46,112,116,114, 32, 61, 61, 32, 34, 38, + 34, 32,116,104,101,110, 32,112,116,114, 32, 61, 32, 34, 95, + 114,101,102, 34, 10, 32,101,110,100, 10, 10, 32,108,111, 99, + 97,108, 32,110, 97,109,101, 32, 61, 32, 32,112,114,101,102, + 105,120, 32, 46, 46, 32,112, 97,114,101,110,116, 32, 46, 46, + 32,117,110,115,105,103,110,101,100, 32, 46, 46, 32, 34, 95, + 34, 32, 46, 46, 32,103,115,117, 98, 40,115,101,108,102, 46, + 108,110, 97,109,101, 32,111,114, 32,115,101,108,102, 46,110, + 97,109,101, 44, 34, 46, 42, 58, 58, 34, 44, 34, 34, 41, 32, + 46, 46, 32,112,116,114, 10, 10, 9,110, 97,109,101, 32, 61, + 32, 99,108,101, 97,110, 95,116,101,109,112,108, 97,116,101, + 40,110, 97,109,101, 41, 10, 32,114,101,116,117,114,110, 32, + 110, 97,109,101, 10, 10,101,110,100, 10, 10, 45, 45, 32, 99, + 104,101, 99,107, 32,105,102, 32,105,116, 32,105,115, 32, 97, + 32,118, 97,114,105, 97, 98,108,101, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98, + 108,101, 58,105,115,118, 97,114,105, 97, 98,108,101, 32, 40, + 41, 10, 32,114,101,116,117,114,110, 32,116,114,117,101, 10, + 101,110,100, 10, 10, 45, 45, 32,103,101,116, 32,118, 97,114, + 105, 97, 98,108,101, 32,118, 97,108,117,101, 10,102,117,110, + 99,116,105,111,110, 32, 99,108, 97,115,115, 86, 97,114,105, + 97, 98,108,101, 58,103,101,116,118, 97,108,117,101, 32, 40, + 99,108, 97,115,115, 44,115,116, 97,116,105, 99, 44, 32,112, + 114,111,112, 95,103,101,116, 41, 10, 10, 9,108,111, 99, 97, + 108, 32,110, 97,109,101, 10, 9,105,102, 32,112,114,111,112, + 95,103,101,116, 32,116,104,101,110, 10, 10, 9, 9,110, 97, + 109,101, 32, 61, 32,112,114,111,112, 95,103,101,116, 46, 46, + 34, 40, 41, 34, 10, 9,101,108,115,101, 10, 9, 9,110, 97, + 109,101, 32, 61, 32,115,101,108,102, 46,110, 97,109,101, 10, + 9,101,110,100, 10, 10, 9,105,102, 32, 99,108, 97,115,115, + 32, 97,110,100, 32,115,116, 97,116,105, 99, 32,116,104,101, + 110, 10, 9, 32,114,101,116,117,114,110, 32,115,101,108,102, + 46,112, 97,114,101,110,116, 46,116,121,112,101, 46, 46, 39, + 58, 58, 39, 46, 46,110, 97,109,101, 10, 9,101,108,115,101, + 105,102, 32, 99,108, 97,115,115, 32,116,104,101,110, 10, 9, + 32,114,101,116,117,114,110, 32, 39,115,101,108,102, 45, 62, + 39, 46, 46,110, 97,109,101, 10, 9,101,108,115,101, 10, 9, + 32,114,101,116,117,114,110, 32,110, 97,109,101, 10, 9,101, + 110,100, 10,101,110,100, 10, 10, 45, 45, 32,103,101,116, 32, + 118, 97,114,105, 97, 98,108,101, 32,112,111,105,110,116,101, + 114, 32,118, 97,108,117,101, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98,108,101, + 58,103,101,116,112,111,105,110,116,101,114,118, 97,108,117, + 101, 32, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, 99, + 41, 10, 32,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, + 32,115,116, 97,116,105, 99, 32,116,104,101,110, 10, 32, 32, + 114,101,116,117,114,110, 32, 99,108, 97,115,115, 46, 46, 39, + 58, 58,112, 39, 10, 32,101,108,115,101,105,102, 32, 99,108, + 97,115,115, 32,116,104,101,110, 10, 32, 32,114,101,116,117, + 114,110, 32, 39,115,101,108,102, 45, 62,112, 39, 10, 32,101, + 108,115,101, 10, 32, 32,114,101,116,117,114,110, 32, 39,112, + 39, 10, 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, + 87,114,105,116,101, 32, 98,105,110,100,105,110,103, 32,102, + 117,110, 99,116,105,111,110,115, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98,108, + 101, 58,115,117,112, 99,111,100,101, 32, 40, 41, 10, 10, 32, + 108,111, 99, 97,108, 32, 99,108, 97,115,115, 32, 61, 32,115, + 101,108,102, 58,105,110, 99,108, 97,115,115, 40, 41, 10, 10, + 9,108,111, 99, 97,108, 32,112,114,111,112, 95,103,101,116, + 44,112,114,111,112, 95,115,101,116, 10, 9,105,102, 32,115, + 116,114,105,110,103, 46,102,105,110,100, 40,115,101,108,102, + 46,109,111,100, 44, 32, 39,116,111,108,117, 97, 95,112,114, + 111,112,101,114,116,121, 39, 41, 32,116,104,101,110, 10, 10, + 9, 9,108,111, 99, 97,108, 32, 95, 44, 95, 44,116,121,112, + 101, 32, 61, 32,115,116,114,105,110,103, 46,102,105,110,100, + 40,115,101,108,102, 46,109,111,100, 44, 32, 34,116,111,108, + 117, 97, 95,112,114,111,112,101,114,116,121, 95, 95, 40, 91, + 94, 37,115, 93, 42, 41, 34, 41, 10, 9, 9,116,121,112,101, + 32, 61, 32,116,121,112,101, 32,111,114, 32, 34,100,101,102, + 97,117,108,116, 34, 10, 9, 9,112,114,111,112, 95,103,101, + 116, 44,112,114,111,112, 95,115,101,116, 32, 61, 32,103,101, + 116, 95,112,114,111,112,101,114,116,121, 95,109,101,116,104, + 111,100,115, 40,116,121,112,101, 44, 32,115,101,108,102, 46, + 110, 97,109,101, 41, 10, 9, 9,115,101,108,102, 46,109,111, + 100, 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, + 40,115,101,108,102, 46,109,111,100, 44, 32, 34,116,111,108, + 117, 97, 95,112,114,111,112,101,114,116,121, 91, 94, 37,115, + 93, 42, 34, 44, 32, 34, 34, 41, 10, 9,101,110,100, 10, 10, + 32, 45, 45, 32,103,101,116, 32,102,117,110, 99,116,105,111, + 110, 32, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 10, 32,105,102, 32, 99,108, 97,115,115, + 32,116,104,101,110, 10, 32, 32,111,117,116,112,117,116, 40, + 34, 47, 42, 32,103,101,116, 32,102,117,110, 99,116,105,111, + 110, 58, 34, 44,115,101,108,102, 46,110, 97,109,101, 44, 34, + 32,111,102, 32, 99,108, 97,115,115, 32, 34, 44, 99,108, 97, + 115,115, 44, 34, 32, 42, 47, 34, 41, 10, 32,101,108,115,101, + 10, 32, 32,111,117,116,112,117,116, 40, 34, 47, 42, 32,103, + 101,116, 32,102,117,110, 99,116,105,111,110, 58, 34, 44,115, + 101,108,102, 46,110, 97,109,101, 44, 34, 32, 42, 47, 34, 41, + 10, 32,101,110,100, 10, 32,115,101,108,102, 46, 99,103,101, + 116,110, 97,109,101, 32, 61, 32,115,101,108,102, 58, 99,102, + 117,110, 99,110, 97,109,101, 40, 34,116,111,108,117, 97, 95, + 103,101,116, 34, 41, 10, 32,111,117,116,112,117,116, 40, 34, + 35,105,102,110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 68, + 73, 83, 65, 66, 76, 69, 95, 34, 46, 46,115,101,108,102, 46, + 99,103,101,116,110, 97,109,101, 41, 10, 32,111,117,116,112, + 117,116, 40, 34, 92,110,115,116, 97,116,105, 99, 32,105,110, + 116, 34, 44,115,101,108,102, 46, 99,103,101,116,110, 97,109, + 101, 44, 34, 40,108,117, 97, 95, 83,116, 97,116,101, 42, 32, + 116,111,108,117, 97, 95, 83, 41, 34, 41, 10, 32,111,117,116, + 112,117,116, 40, 34,123, 34, 41, 10, 10, 32, 45, 45, 32,100, + 101, 99,108, 97,114,101, 32,115,101,108,102, 44, 32,105,102, + 32,116,104,101, 32, 99, 97,115,101, 10, 32,108,111, 99, 97, + 108, 32, 95, 44, 95, 44,115,116, 97,116,105, 99, 32, 61, 32, + 115,116,114,102,105,110,100, 40,115,101,108,102, 46,109,111, + 100, 44, 39, 94, 37,115, 42, 40,115,116, 97,116,105, 99, 41, + 39, 41, 10, 32,105,102, 32, 99,108, 97,115,115, 32, 97,110, + 100, 32,115,116, 97,116,105, 99, 61, 61,110,105,108, 32,116, + 104,101,110, 10, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 39, 44,115,101,108,102, 46,112, 97,114,101,110,116, 46,116, + 121,112,101, 44, 39, 42, 39, 44, 39,115,101,108,102, 32, 61, + 32, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, 39, 40, + 39, 44,115,101,108,102, 46,112, 97,114,101,110,116, 46,116, + 121,112,101, 44, 39, 42, 41, 32, 39, 41, 10, 32, 32,108,111, + 99, 97,108, 32,116,111, 95,102,117,110, 99, 32, 61, 32,103, + 101,116, 95,116,111, 95,102,117,110, 99,116,105,111,110, 40, + 115,101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112, + 101, 41, 10, 32, 32,111,117,116,112,117,116, 40,116,111, 95, + 102,117,110, 99, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, + 49, 44, 48, 41, 59, 39, 41, 10, 32,101,108,115,101,105,102, + 32,115,116, 97,116,105, 99, 32,116,104,101,110, 10, 32, 32, + 95, 44, 95, 44,115,101,108,102, 46,109,111,100, 32, 61, 32, + 115,116,114,102,105,110,100, 40,115,101,108,102, 46,109,111, + 100, 44, 39, 94, 37,115, 42,115,116, 97,116,105, 99, 37,115, + 37,115, 42, 40, 46, 42, 41, 39, 41, 10, 32,101,110,100, 10, + 10, 10, 32, 45, 45, 32, 99,104,101, 99,107, 32,115,101,108, + 102, 32,118, 97,108,117,101, 10, 32,105,102, 32, 99,108, 97, + 115,115, 32, 97,110,100, 32,115,116, 97,116,105, 99, 61, 61, + 110,105,108, 32,116,104,101,110, 10, 9, 32,111,117,116,112, + 117,116, 40, 39, 35,105,102,110,100,101,102, 32, 84, 79, 76, + 85, 65, 95, 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, + 32, 32,111,117,116,112,117,116, 40, 39, 32, 32,105,102, 32, + 40, 33,115,101,108,102, 41, 32,116,111,108,117, 97, 95,101, + 114,114,111,114, 40,116,111,108,117, 97, 95, 83, 44, 34,105, + 110,118, 97,108,105,100, 32, 92, 39,115,101,108,102, 92, 39, + 32,105,110, 32, 97, 99, 99,101,115,115,105,110,103, 32,118, + 97,114,105, 97, 98,108,101, 32, 92, 39, 39, 46, 46,115,101, + 108,102, 46,110, 97,109,101, 46, 46, 39, 92, 39, 34, 44, 78, + 85, 76, 76, 41, 59, 39, 41, 59, 10, 9, 9,111,117,116,112, + 117,116, 40, 39, 35,101,110,100,105,102, 92,110, 39, 41, 10, + 32,101,110,100, 10, 10, 32, 45, 45, 32,114,101,116,117,114, + 110, 32,118, 97,108,117,101, 10, 32,105,102, 32,115,116,114, + 105,110,103, 46,102,105,110,100, 40,115,101,108,102, 46,109, + 111,100, 44, 32, 39,116,111,108,117, 97, 95,105,110,104,101, + 114,105,116,115, 39, 41, 32,116,104,101,110, 10, 9,108,111, + 99, 97,108, 32,112,117,115,104, 95,102,117,110, 99, 32, 61, + 32,103,101,116, 95,112,117,115,104, 95,102,117,110, 99,116, + 105,111,110, 40,115,101,108,102, 46,116,121,112,101, 41, 10, + 32, 9,111,117,116,112,117,116, 40, 39, 35,105,102,100,101, + 102, 32, 95, 95, 99,112,108,117,115,112,108,117,115, 92,110, + 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, 32, 32, 39, + 44,112,117,115,104, 95,102,117,110, 99, 44, 39, 40,116,111, + 108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, 41,115,116, + 97,116,105, 99, 95, 99, 97,115,116, 60, 39, 46, 46,115,101, + 108,102, 46,116,121,112,101, 46, 46, 39, 42, 62, 40,115,101, + 108,102, 41, 44, 32, 34, 39, 44,115,101,108,102, 46,116,121, + 112,101, 44, 39, 34, 41, 59, 39, 41, 10, 9,111,117,116,112, + 117,116, 40, 39, 35,101,108,115,101, 92,110, 39, 41, 10, 9, + 111,117,116,112,117,116, 40, 39, 32, 32, 39, 44,112,117,115, + 104, 95,102,117,110, 99, 44, 39, 40,116,111,108,117, 97, 95, + 83, 44, 40,118,111,105,100, 42, 41, 40, 40, 39, 46, 46,115, + 101,108,102, 46,116,121,112,101, 46, 46, 39, 42, 41,115,101, + 108,102, 41, 44, 32, 34, 39, 44,115,101,108,102, 46,116,121, + 112,101, 44, 39, 34, 41, 59, 39, 41, 10, 9,111,117,116,112, + 117,116, 40, 39, 35,101,110,100,105,102, 92,110, 39, 41, 10, + 32,101,108,115,101, 10, 9,108,111, 99, 97,108, 32,116, 44, + 99,116, 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101, + 108,102, 46,116,121,112,101, 41, 10, 9,105,102, 32,116, 32, + 116,104,101,110, 10, 9, 9,111,117,116,112,117,116, 40, 39, + 32, 32,116,111,108,117, 97, 95,112,117,115,104, 39, 46, 46, + 116, 46, 46, 39, 40,116,111,108,117, 97, 95, 83, 44, 40, 39, + 44, 99,116, 44, 39, 41, 39, 46, 46,115,101,108,102, 58,103, + 101,116,118, 97,108,117,101, 40, 99,108, 97,115,115, 44,115, + 116, 97,116,105, 99, 44,112,114,111,112, 95,103,101,116, 41, + 46, 46, 39, 41, 59, 39, 41, 10, 9,101,108,115,101, 10, 9, + 9,108,111, 99, 97,108, 32,112,117,115,104, 95,102,117,110, + 99, 32, 61, 32,103,101,116, 95,112,117,115,104, 95,102,117, + 110, 99,116,105,111,110, 40,115,101,108,102, 46,116,121,112, + 101, 41, 10, 9, 9,116, 32, 61, 32,115,101,108,102, 46,116, + 121,112,101, 10, 9, 9,105,102, 32,115,101,108,102, 46,112, + 116,114, 32, 61, 61, 32, 39, 38, 39, 32,111,114, 32,115,101, + 108,102, 46,112,116,114, 32, 61, 61, 32, 39, 39, 32,116,104, + 101,110, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, + 32, 39, 44,112,117,115,104, 95,102,117,110, 99, 44, 39, 40, + 116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, 41, + 38, 39, 46, 46,115,101,108,102, 58,103,101,116,118, 97,108, + 117,101, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, 99, + 44,112,114,111,112, 95,103,101,116, 41, 46, 46, 39, 44, 34, + 39, 44,116, 44, 39, 34, 41, 59, 39, 41, 10, 9, 9,101,108, + 115,101, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, + 32, 39, 44,112,117,115,104, 95,102,117,110, 99, 44, 39, 40, + 116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, 41, + 39, 46, 46,115,101,108,102, 58,103,101,116,118, 97,108,117, + 101, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, 99, 44, + 112,114,111,112, 95,103,101,116, 41, 46, 46, 39, 44, 34, 39, + 44,116, 44, 39, 34, 41, 59, 39, 41, 10, 9, 9,101,110,100, + 10, 9,101,110,100, 10, 32,101,110,100, 10, 32,111,117,116, + 112,117,116, 40, 39, 32,114,101,116,117,114,110, 32, 49, 59, + 39, 41, 10, 32,111,117,116,112,117,116, 40, 39,125, 39, 41, + 10, 32,111,117,116,112,117,116, 40, 39, 35,101,110,100,105, + 102, 32, 47, 47, 35,105,102,110,100,101,102, 32, 84, 79, 76, + 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, 92,110, 39, 41, 10, + 32,111,117,116,112,117,116, 40, 39, 92,110, 39, 41, 10, 10, + 32, 45, 45, 32,115,101,116, 32,102,117,110, 99,116,105,111, + 110, 32, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 10, 32,105,102, 32,110,111,116, 32, 40, + 115,116,114,102,105,110,100, 40,115,101,108,102, 46,116,121, + 112,101, 44, 39, 99,111,110,115,116, 37,115, 43, 39, 41, 32, + 111,114, 32,115,116,114,105,110,103, 46,102,105,110,100, 40, + 115,101,108,102, 46,109,111,100, 44, 32, 39,116,111,108,117, + 97, 95,114,101, 97,100,111,110,108,121, 39, 41, 32,111,114, + 32,115,116,114,105,110,103, 46,102,105,110,100, 40,115,101, + 108,102, 46,109,111,100, 44, 32, 39,116,111,108,117, 97, 95, + 105,110,104,101,114,105,116,115, 39, 41, 41, 32, 32,116,104, + 101,110, 10, 32, 32,105,102, 32, 99,108, 97,115,115, 32,116, + 104,101,110, 10, 32, 32, 32,111,117,116,112,117,116, 40, 34, + 47, 42, 32,115,101,116, 32,102,117,110, 99,116,105,111,110, + 58, 34, 44,115,101,108,102, 46,110, 97,109,101, 44, 34, 32, + 111,102, 32, 99,108, 97,115,115, 32, 34, 44, 99,108, 97,115, + 115, 44, 34, 32, 42, 47, 34, 41, 10, 32, 32,101,108,115,101, + 10, 32, 32, 32,111,117,116,112,117,116, 40, 34, 47, 42, 32, + 115,101,116, 32,102,117,110, 99,116,105,111,110, 58, 34, 44, + 115,101,108,102, 46,110, 97,109,101, 44, 34, 32, 42, 47, 34, + 41, 10, 32, 32,101,110,100, 10, 32, 32,115,101,108,102, 46, + 99,115,101,116,110, 97,109,101, 32, 61, 32,115,101,108,102, + 58, 99,102,117,110, 99,110, 97,109,101, 40, 34,116,111,108, + 117, 97, 95,115,101,116, 34, 41, 10, 32, 32,111,117,116,112, + 117,116, 40, 34, 35,105,102,110,100,101,102, 32, 84, 79, 76, + 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, 95, 34, 46, 46,115, + 101,108,102, 46, 99,115,101,116,110, 97,109,101, 41, 10, 32, + 32,111,117,116,112,117,116, 40, 34, 92,110,115,116, 97,116, + 105, 99, 32,105,110,116, 34, 44,115,101,108,102, 46, 99,115, + 101,116,110, 97,109,101, 44, 34, 40,108,117, 97, 95, 83,116, + 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 34, 41, + 10, 32, 32,111,117,116,112,117,116, 40, 34,123, 34, 41, 10, + 10, 32, 32, 45, 45, 32,100,101, 99,108, 97,114,101, 32,115, + 101,108,102, 44, 32,105,102, 32,116,104,101, 32, 99, 97,115, + 101, 10, 32, 32,105,102, 32, 99,108, 97,115,115, 32, 97,110, + 100, 32,115,116, 97,116,105, 99, 61, 61,110,105,108, 32,116, + 104,101,110, 10, 32, 32, 32,111,117,116,112,117,116, 40, 39, + 32, 39, 44,115,101,108,102, 46,112, 97,114,101,110,116, 46, + 116,121,112,101, 44, 39, 42, 39, 44, 39,115,101,108,102, 32, + 61, 32, 39, 41, 10, 32, 32, 32,111,117,116,112,117,116, 40, + 39, 40, 39, 44,115,101,108,102, 46,112, 97,114,101,110,116, + 46,116,121,112,101, 44, 39, 42, 41, 32, 39, 41, 10, 32, 32, + 32,108,111, 99, 97,108, 32,116,111, 95,102,117,110, 99, 32, + 61, 32,103,101,116, 95,116,111, 95,102,117,110, 99,116,105, + 111,110, 40,115,101,108,102, 46,112, 97,114,101,110,116, 46, + 116,121,112,101, 41, 10, 32, 32, 32,111,117,116,112,117,116, + 40,116,111, 95,102,117,110, 99, 44, 39, 40,116,111,108,117, + 97, 95, 83, 44, 49, 44, 48, 41, 59, 39, 41, 10, 32, 32, 32, + 45, 45, 32, 99,104,101, 99,107, 32,115,101,108,102, 32,118, + 97,108,117,101, 10, 9, 9,101,110,100, 10, 32, 32, 45, 45, + 32, 99,104,101, 99,107, 32,116,121,112,101,115, 10, 9, 9, + 111,117,116,112,117,116, 40, 39, 35,105,102,110,100,101,102, + 32, 84, 79, 76, 85, 65, 95, 82, 69, 76, 69, 65, 83, 69, 92, + 110, 39, 41, 10, 9, 9,111,117,116,112,117,116, 40, 39, 32, + 32,116,111,108,117, 97, 95, 69,114,114,111,114, 32,116,111, + 108,117, 97, 95,101,114,114, 59, 39, 41, 10, 32, 32,105,102, + 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,116, 97,116, + 105, 99, 61, 61,110,105,108, 32,116,104,101,110, 10, 32, 32, + 32,111,117,116,112,117,116, 40, 39, 32, 32,105,102, 32, 40, + 33,115,101,108,102, 41, 32,116,111,108,117, 97, 95,101,114, + 114,111,114, 40,116,111,108,117, 97, 95, 83, 44, 34,105,110, + 118, 97,108,105,100, 32, 92, 39,115,101,108,102, 92, 39, 32, + 105,110, 32, 97, 99, 99,101,115,115,105,110,103, 32,118, 97, + 114,105, 97, 98,108,101, 32, 92, 39, 39, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 39, 92, 39, 34, 44, 78, 85, + 76, 76, 41, 59, 39, 41, 59, 10, 32, 32,101,108,115,101,105, + 102, 32,115,116, 97,116,105, 99, 32,116,104,101,110, 10, 32, + 32, 32, 95, 44, 95, 44,115,101,108,102, 46,109,111,100, 32, + 61, 32,115,116,114,102,105,110,100, 40,115,101,108,102, 46, + 109,111,100, 44, 39, 94, 37,115, 42,115,116, 97,116,105, 99, + 37,115, 37,115, 42, 40, 46, 42, 41, 39, 41, 10, 32, 32,101, + 110,100, 10, 10, 32, 32, 45, 45, 32, 99,104,101, 99,107, 32, + 118, 97,114,105, 97, 98,108,101, 32,116,121,112,101, 10, 32, + 32,111,117,116,112,117,116, 40, 39, 32, 32,105,102, 32, 40, + 39, 46, 46,115,101,108,102, 58,111,117,116, 99,104,101, 99, + 107,116,121,112,101, 40, 50, 41, 46, 46, 39, 41, 39, 41, 10, + 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, 32,116,111, + 108,117, 97, 95,101,114,114,111,114, 40,116,111,108,117, 97, + 95, 83, 44, 34, 35,118,105,110,118, 97,108,105,100, 32,116, + 121,112,101, 32,105,110, 32,118, 97,114,105, 97, 98,108,101, + 32, 97,115,115,105,103,110,109,101,110,116, 46, 34, 44, 38, + 116,111,108,117, 97, 95,101,114,114, 41, 59, 39, 41, 10, 9, + 9,111,117,116,112,117,116, 40, 39, 35,101,110,100,105,102, + 92,110, 39, 41, 10, 10, 32, 32, 45, 45, 32, 97,115,115,105, + 103,110, 32,118, 97,108,117,101, 10, 9, 9,108,111, 99, 97, + 108, 32,100,101,102, 32, 61, 32, 48, 10, 9, 9,105,102, 32, + 115,101,108,102, 46,100,101,102, 32,126, 61, 32, 39, 39, 32, + 116,104,101,110, 32,100,101,102, 32, 61, 32,115,101,108,102, + 46,100,101,102, 32,101,110,100, 10, 9, 9,105,102, 32,115, + 101,108,102, 46,116,121,112,101, 32, 61, 61, 32, 39, 99,104, + 97,114, 42, 39, 32, 97,110,100, 32,115,101,108,102, 46,100, + 105,109, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 32, 45, + 45, 32,105,115, 32,115,116,114,105,110,103, 10, 9, 9, 32, + 111,117,116,112,117,116, 40, 39, 32,115,116,114,110, 99,112, + 121, 40, 39, 41, 10, 9, 9, 9,105,102, 32, 99,108, 97,115, + 115, 32, 97,110,100, 32,115,116, 97,116,105, 99, 32,116,104, + 101,110, 10, 9, 9, 9, 9,111,117,116,112,117,116, 40,115, + 101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112,101, + 46, 46, 39, 58, 58, 39, 46, 46,115,101,108,102, 46,110, 97, + 109,101, 41, 10, 9, 9, 9,101,108,115,101,105,102, 32, 99, + 108, 97,115,115, 32,116,104,101,110, 10, 9, 9, 9, 9,111, + 117,116,112,117,116, 40, 39,115,101,108,102, 45, 62, 39, 46, + 46,115,101,108,102, 46,110, 97,109,101, 41, 10, 9, 9, 9, + 101,108,115,101, 10, 9, 9, 9, 9,111,117,116,112,117,116, + 40,115,101,108,102, 46,110, 97,109,101, 41, 10, 9, 9, 9, + 101,110,100, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, + 44,116,111,108,117, 97, 95,116,111,115,116,114,105,110,103, + 40,116,111,108,117, 97, 95, 83, 44, 50, 44, 39, 44,100,101, + 102, 44, 39, 41, 44, 39, 44,115,101,108,102, 46,100,105,109, + 44, 39, 45, 49, 41, 59, 39, 41, 10, 9, 9,101,108,115,101, + 10, 9, 9, 9,108,111, 99, 97,108, 32,112,116,114, 32, 61, + 32, 39, 39, 10, 9, 9, 9,105,102, 32,115,101,108,102, 46, + 112,116,114,126, 61, 39, 39, 32,116,104,101,110, 32,112,116, + 114, 32, 61, 32, 39, 42, 39, 32,101,110,100, 10, 9, 9, 9, + 111,117,116,112,117,116, 40, 39, 32, 39, 41, 10, 9, 9, 9, + 108,111, 99, 97,108, 32,110, 97,109,101, 32, 61, 32,112,114, + 111,112, 95,115,101,116, 32,111,114, 32,115,101,108,102, 46, + 110, 97,109,101, 10, 9, 9, 9,105,102, 32, 99,108, 97,115, + 115, 32, 97,110,100, 32,115,116, 97,116,105, 99, 32,116,104, + 101,110, 10, 9, 9, 9, 9,111,117,116,112,117,116, 40,115, + 101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112,101, + 46, 46, 39, 58, 58, 39, 46, 46,110, 97,109,101, 41, 10, 9, + 9, 9,101,108,115,101,105,102, 32, 99,108, 97,115,115, 32, + 116,104,101,110, 10, 9, 9, 9, 9,111,117,116,112,117,116, + 40, 39,115,101,108,102, 45, 62, 39, 46, 46,110, 97,109,101, + 41, 10, 9, 9, 9,101,108,115,101, 10, 9, 9, 9, 9,111, + 117,116,112,117,116, 40,110, 97,109,101, 41, 10, 9, 9, 9, + 101,110,100, 10, 9, 9, 9,108,111, 99, 97,108, 32,116, 32, + 61, 32,105,115, 98, 97,115,105, 99, 40,115,101,108,102, 46, + 116,121,112,101, 41, 10, 9, 9, 9,105,102, 32,112,114,111, + 112, 95,115,101,116, 32,116,104,101,110, 10, 9, 9, 9, 9, + 111,117,116,112,117,116, 40, 39, 40, 39, 41, 10, 9, 9, 9, + 101,108,115,101, 10, 9, 9, 9, 9,111,117,116,112,117,116, + 40, 39, 32, 61, 32, 39, 41, 10, 9, 9, 9,101,110,100, 10, + 9, 9, 9,105,102, 32,110,111,116, 32,116, 32, 97,110,100, + 32,112,116,114, 61, 61, 39, 39, 32,116,104,101,110, 32,111, + 117,116,112,117,116, 40, 39, 42, 39, 41, 32,101,110,100, 10, + 9, 9, 9,111,117,116,112,117,116, 40, 39, 40, 40, 39, 44, + 115,101,108,102, 46,109,111,100, 44,115,101,108,102, 46,116, + 121,112,101, 41, 10, 9, 9, 9,105,102, 32,110,111,116, 32, + 116, 32,116,104,101,110, 10, 9, 9, 9, 9,111,117,116,112, + 117,116, 40, 39, 42, 39, 41, 10, 9, 9, 9,101,110,100, 10, + 9, 9, 9,111,117,116,112,117,116, 40, 39, 41, 32, 39, 41, + 10, 9, 9, 9,105,102, 32,116, 32,116,104,101,110, 10, 9, + 9, 9, 9,105,102, 32,105,115,101,110,117,109, 40,115,101, + 108,102, 46,116,121,112,101, 41, 32,116,104,101,110, 10, 9, + 9, 9, 9, 9,111,117,116,112,117,116, 40, 39, 40,105,110, + 116, 41, 32, 39, 41, 10, 9, 9, 9, 9,101,110,100, 10, 9, + 9, 9, 9,111,117,116,112,117,116, 40, 39,116,111,108,117, + 97, 95,116,111, 39, 46, 46,116, 44, 39, 40,116,111,108,117, + 97, 95, 83, 44, 50, 44, 39, 44,100,101,102, 44, 39, 41, 41, + 39, 41, 10, 9, 9, 9,101,108,115,101, 10, 9, 9, 9, 9, + 108,111, 99, 97,108, 32,116,111, 95,102,117,110, 99, 32, 61, + 32,103,101,116, 95,116,111, 95,102,117,110, 99,116,105,111, + 110, 40,115,101,108,102, 46,116,121,112,101, 41, 10, 9, 9, + 9, 9,111,117,116,112,117,116, 40,116,111, 95,102,117,110, + 99, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, 50, 44, 39, + 44,100,101,102, 44, 39, 41, 41, 39, 41, 10, 9, 9, 9,101, + 110,100, 10, 9, 9, 9,105,102, 32,112,114,111,112, 95,115, + 101,116, 32,116,104,101,110, 10, 9, 9, 9, 9,111,117,116, + 112,117,116, 40, 34, 41, 34, 41, 10, 9, 9, 9,101,110,100, + 10, 9, 9, 9,111,117,116,112,117,116, 40, 34, 59, 34, 41, + 10, 9, 9,101,110,100, 10, 32, 32,111,117,116,112,117,116, + 40, 39, 32,114,101,116,117,114,110, 32, 48, 59, 39, 41, 10, + 32, 32,111,117,116,112,117,116, 40, 39,125, 39, 41, 10, 32, + 32,111,117,116,112,117,116, 40, 39, 35,101,110,100,105,102, + 32, 47, 47, 35,105,102,110,100,101,102, 32, 84, 79, 76, 85, + 65, 95, 68, 73, 83, 65, 66, 76, 69, 92,110, 39, 41, 10, 32, + 32,111,117,116,112,117,116, 40, 39, 92,110, 39, 41, 10, 32, + 101,110,100, 10, 10,101,110,100, 10, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98, + 108,101, 58,114,101,103,105,115,116,101,114, 32, 40,112,114, + 101, 41, 10, 10, 9,105,102, 32,110,111,116, 32,115,101,108, + 102, 58, 99,104,101, 99,107, 95,112,117, 98,108,105, 99, 95, + 97, 99, 99,101,115,115, 40, 41, 32,116,104,101,110, 10, 9, + 9,114,101,116,117,114,110, 10, 9,101,110,100, 10, 32,112, + 114,101, 32, 61, 32,112,114,101, 32,111,114, 32, 39, 39, 10, + 32,108,111, 99, 97,108, 32,112, 97,114,101,110,116, 32, 61, + 32,115,101,108,102, 58,105,110,109,111,100,117,108,101, 40, + 41, 32,111,114, 32,115,101,108,102, 58,105,110,110, 97,109, + 101,115,112, 97, 99,101, 40, 41, 32,111,114, 32,115,101,108, + 102, 58,105,110, 99,108, 97,115,115, 40, 41, 10, 32,105,102, + 32,110,111,116, 32,112, 97,114,101,110,116, 32,116,104,101, + 110, 10, 32, 32,105,102, 32, 99,108, 97,115,115, 86, 97,114, + 105, 97, 98,108,101, 46, 95,119, 97,114,110,105,110,103, 61, + 61,110,105,108, 32,116,104,101,110, 10, 32, 32, 32,119, 97, + 114,110,105,110,103, 40, 34, 77, 97,112,112,105,110,103, 32, + 118, 97,114,105, 97, 98,108,101, 32,116,111, 32,103,108,111, + 98, 97,108, 32,109, 97,121, 32,100,101,103,114, 97,100,101, + 32,112,101,114,102,111,114,109, 97,110, 99,101, 34, 41, 10, + 32, 32, 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98,108, + 101, 46, 95,119, 97,114,110,105,110,103, 32, 61, 32, 49, 10, + 32, 32,101,110,100, 10, 32,101,110,100, 10, 32,105,102, 32, + 115,101,108,102, 46, 99,115,101,116,110, 97,109,101, 32,116, + 104,101,110, 10, 32, 32,111,117,116,112,117,116, 40,112,114, + 101, 46, 46, 39,116,111,108,117, 97, 95,118, 97,114,105, 97, + 98,108,101, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, + 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, + 44, 39, 46, 46,115,101,108,102, 46, 99,103,101,116,110, 97, + 109,101, 46, 46, 39, 44, 39, 46, 46,115,101,108,102, 46, 99, + 115,101,116,110, 97,109,101, 46, 46, 39, 41, 59, 39, 41, 10, + 32,101,108,115,101, 10, 32, 32,111,117,116,112,117,116, 40, + 112,114,101, 46, 46, 39,116,111,108,117, 97, 95,118, 97,114, + 105, 97, 98,108,101, 40,116,111,108,117, 97, 95, 83, 44, 34, + 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, + 39, 34, 44, 39, 46, 46,115,101,108,102, 46, 99,103,101,116, + 110, 97,109,101, 46, 46, 39, 44, 78, 85, 76, 76, 41, 59, 39, + 41, 10, 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, + 73,110,116,101,114,110, 97,108, 32, 99,111,110,115,116,114, + 117, 99,116,111,114, 10,102,117,110, 99,116,105,111,110, 32, + 95, 86, 97,114,105, 97, 98,108,101, 32, 40,116, 41, 10, 32, + 115,101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, 44, + 99,108, 97,115,115, 86, 97,114,105, 97, 98,108,101, 41, 10, + 32, 97,112,112,101,110,100, 40,116, 41, 10, 32,114,101,116, + 117,114,110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, 67, + 111,110,115,116,114,117, 99,116,111,114, 10, 45, 45, 32, 69, + 120,112,101, 99,116,115, 32, 97, 32,115,116,114,105,110,103, + 32,114,101,112,114,101,115,101,110,116,105,110,103, 32,116, + 104,101, 32,118, 97,114,105, 97, 98,108,101, 32,100,101, 99, + 108, 97,114, 97,116,105,111,110, 46, 10,102,117,110, 99,116, + 105,111,110, 32, 86, 97,114,105, 97, 98,108,101, 32, 40,115, + 41, 10, 32,114,101,116,117,114,110, 32, 95, 86, 97,114,105, + 97, 98,108,101, 32, 40, 68,101, 99,108, 97,114, 97,116,105, + 111,110, 40,115, 44, 39,118, 97,114, 39, 41, 41, 10,101,110, + 100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/variable.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32, 97,114,114, 97,121, + 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105,116,116, + 101,110, 32, 98,121, 32, 87, 97,108,100,101,109, 97,114, 32, + 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71,114, 97, + 102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74,117, + 108, 32, 49, 57, 57, 57, 10, 45, 45, 32, 36, 73,100, 58, 32, + 97,114,114, 97,121, 46,108,117, 97, 44,118, 32, 49, 46, 49, + 32, 50, 48, 48, 48, 47, 49, 49, 47, 48, 54, 32, 50, 50, 58, + 48, 51, 58, 53, 55, 32, 99,101,108,101,115, 32, 69,120,112, + 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111,100, + 101, 32,105,115, 32,102,114,101,101, 32,115,111,102,116,119, + 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32,114,101, + 100,105,115,116,114,105, 98,117,116,101, 32,105,116, 32, 97, + 110,100, 47,111,114, 32,109,111,100,105,102,121, 32,105,116, + 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116,119, 97, + 114,101, 32,112,114,111,118,105,100,101,100, 32,104,101,114, + 101,117,110,100,101,114, 32,105,115, 32,111,110, 32, 97,110, + 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, 44, + 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97,117,116, + 104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98,108,105, + 103, 97,116,105,111,110, 32,116,111, 32,112,114,111,118,105, + 100,101, 32,109, 97,105,110,116,101,110, 97,110, 99,101, 44, + 32,115,117,112,112,111,114,116, 44, 32,117,112,100, 97,116, + 101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101,109, + 101,110,116,115, 44, 32,111,114, 32,109,111,100,105,102,105, + 99, 97,116,105,111,110,115, 46, 10, 10, 10, 45, 45, 32, 65, + 114,114, 97,121, 32, 99,108, 97,115,115, 10, 45, 45, 32, 82, + 101,112,114,101,115,101,110,116,115, 32, 97, 32,101,120,116, + 101,114,110, 32, 97,114,114, 97,121, 32,118, 97,114,105, 97, + 98,108,101, 32,111,114, 32, 97, 32,112,117, 98,108,105, 99, + 32,109,101,109, 98,101,114, 32,111,102, 32, 97, 32, 99,108, + 97,115,115, 46, 10, 45, 45, 32, 83,116,111,114,101,115, 32, + 97,108,108, 32,102,105,101,108,100,115, 32,112,114,101,115, + 101,110,116, 32,105,110, 32, 97, 32,100,101, 99,108, 97,114, + 97,116,105,111,110, 46, 10, 99,108, 97,115,115, 65,114,114, + 97,121, 32, 61, 32,123, 10,125, 10, 99,108, 97,115,115, 65, + 114,114, 97,121, 46, 95, 95,105,110,100,101,120, 32, 61, 32, + 99,108, 97,115,115, 65,114,114, 97,121, 10,115,101,116,109, + 101,116, 97,116, 97, 98,108,101, 40, 99,108, 97,115,115, 65, + 114,114, 97,121, 44, 99,108, 97,115,115, 68,101, 99,108, 97, + 114, 97,116,105,111,110, 41, 10, 10, 45, 45, 32, 80,114,105, + 110,116, 32,109,101,116,104,111,100, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 65,114,114, 97,121, 58, + 112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108, + 111,115,101, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 65,114,114, 97,121,123, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 109,111,100, 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, + 46,109,111,100, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114, + 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,116,121, + 112,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,116, + 121,112,101, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114,105, + 110,116, 40,105,100,101,110,116, 46, 46, 34, 32,112,116,114, + 32, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,112,116, + 114, 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114,105,110,116, + 40,105,100,101,110,116, 46, 46, 34, 32,110, 97,109,101, 32, + 61, 32, 39, 34, 46, 46,115,101,108,102, 46,110, 97,109,101, + 46, 46, 34, 39, 44, 34, 41, 10, 32,112,114,105,110,116, 40, + 105,100,101,110,116, 46, 46, 34, 32,100,101,102, 32, 32, 61, + 32, 39, 34, 46, 46,115,101,108,102, 46,100,101,102, 46, 46, + 34, 39, 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100, + 101,110,116, 46, 46, 34, 32,100,105,109, 32, 32, 61, 32, 39, + 34, 46, 46,115,101,108,102, 46,100,105,109, 46, 46, 34, 39, + 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110, + 116, 46, 46, 34, 32,114,101,116, 32, 32, 61, 32, 39, 34, 46, + 46,115,101,108,102, 46,114,101,116, 46, 46, 34, 39, 44, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110, + 100, 10, 10, 45, 45, 32, 99,104,101, 99,107, 32,105,102, 32, + 105,116, 32,105,115, 32, 97, 32,118, 97,114,105, 97, 98,108, + 101, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 65,114,114, 97,121, 58,105,115,118, 97,114,105, 97, 98, + 108,101, 32, 40, 41, 10, 32,114,101,116,117,114,110, 32,116, + 114,117,101, 10,101,110,100, 10, 10, 10, 45, 45, 32,103,101, + 116, 32,118, 97,114,105, 97, 98,108,101, 32,118, 97,108,117, + 101, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 65,114,114, 97,121, 58,103,101,116,118, 97,108,117,101, + 32, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, 99, 41, + 10, 32,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32, + 115,116, 97,116,105, 99, 32,116,104,101,110, 10, 32, 32,114, + 101,116,117,114,110, 32, 99,108, 97,115,115, 46, 46, 39, 58, + 58, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, + 39, 91,116,111,108,117, 97, 95,105,110,100,101,120, 93, 39, + 10, 32,101,108,115,101,105,102, 32, 99,108, 97,115,115, 32, + 116,104,101,110, 10, 32, 32,114,101,116,117,114,110, 32, 39, + 115,101,108,102, 45, 62, 39, 46, 46,115,101,108,102, 46,110, + 97,109,101, 46, 46, 39, 91,116,111,108,117, 97, 95,105,110, + 100,101,120, 93, 39, 10, 32,101,108,115,101, 10, 32, 32,114, + 101,116,117,114,110, 32,115,101,108,102, 46,110, 97,109,101, + 46, 46, 39, 91,116,111,108,117, 97, 95,105,110,100,101,120, + 93, 39, 10, 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, + 32, 87,114,105,116,101, 32, 98,105,110,100,105,110,103, 32, + 102,117,110, 99,116,105,111,110,115, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 65,114,114, 97,121, 58, + 115,117,112, 99,111,100,101, 32, 40, 41, 10, 32,108,111, 99, + 97,108, 32, 99,108, 97,115,115, 32, 61, 32,115,101,108,102, + 58,105,110, 99,108, 97,115,115, 40, 41, 10, 10, 32, 45, 45, + 32,103,101,116, 32,102,117,110, 99,116,105,111,110, 32, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 10, 32,105,102, 32, 99,108, 97,115,115, 32,116,104, + 101,110, 10, 32, 32,111,117,116,112,117,116, 40, 34, 47, 42, + 32,103,101,116, 32,102,117,110, 99,116,105,111,110, 58, 34, + 44,115,101,108,102, 46,110, 97,109,101, 44, 34, 32,111,102, + 32, 99,108, 97,115,115, 32, 34, 44, 99,108, 97,115,115, 44, + 34, 32, 42, 47, 34, 41, 10, 32,101,108,115,101, 10, 32, 32, + 111,117,116,112,117,116, 40, 34, 47, 42, 32,103,101,116, 32, + 102,117,110, 99,116,105,111,110, 58, 34, 44,115,101,108,102, + 46,110, 97,109,101, 44, 34, 32, 42, 47, 34, 41, 10, 32,101, + 110,100, 10, 32,115,101,108,102, 46, 99,103,101,116,110, 97, + 109,101, 32, 61, 32,115,101,108,102, 58, 99,102,117,110, 99, + 110, 97,109,101, 40, 34,116,111,108,117, 97, 95,103,101,116, + 34, 41, 10, 32,111,117,116,112,117,116, 40, 34, 35,105,102, + 110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, + 66, 76, 69, 95, 34, 46, 46,115,101,108,102, 46, 99,103,101, + 116,110, 97,109,101, 41, 10, 32,111,117,116,112,117,116, 40, + 34, 92,110,115,116, 97,116,105, 99, 32,105,110,116, 34, 44, + 115,101,108,102, 46, 99,103,101,116,110, 97,109,101, 44, 34, + 40,108,117, 97, 95, 83,116, 97,116,101, 42, 32,116,111,108, + 117, 97, 95, 83, 41, 34, 41, 10, 32,111,117,116,112,117,116, + 40, 34,123, 34, 41, 10, 32,111,117,116,112,117,116, 40, 34, + 32,105,110,116, 32,116,111,108,117, 97, 95,105,110,100,101, + 120, 59, 34, 41, 10, 10, 32, 45, 45, 32,100,101, 99,108, 97, + 114,101, 32,115,101,108,102, 44, 32,105,102, 32,116,104,101, + 32, 99, 97,115,101, 10, 32,108,111, 99, 97,108, 32, 95, 44, + 95, 44,115,116, 97,116,105, 99, 32, 61, 32,115,116,114,102, + 105,110,100, 40,115,101,108,102, 46,109,111,100, 44, 39, 94, + 37,115, 42, 40,115,116, 97,116,105, 99, 41, 39, 41, 10, 32, + 105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,116, + 97,116,105, 99, 61, 61,110,105,108, 32,116,104,101,110, 10, + 32, 32,111,117,116,112,117,116, 40, 39, 32, 39, 44,115,101, + 108,102, 46,112, 97,114,101,110,116, 46,116,121,112,101, 44, + 39, 42, 39, 44, 39,115,101,108,102, 59, 39, 41, 10, 32, 32, + 111,117,116,112,117,116, 40, 39, 32,108,117, 97, 95,112,117, + 115,104,115,116,114,105,110,103, 40,116,111,108,117, 97, 95, + 83, 44, 34, 46,115,101,108,102, 34, 41, 59, 39, 41, 10, 32, + 32,111,117,116,112,117,116, 40, 39, 32,108,117, 97, 95,114, + 97,119,103,101,116, 40,116,111,108,117, 97, 95, 83, 44, 49, + 41, 59, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, 39, + 32,115,101,108,102, 32, 61, 32, 39, 41, 10, 32, 32,111,117, + 116,112,117,116, 40, 39, 40, 39, 44,115,101,108,102, 46,112, + 97,114,101,110,116, 46,116,121,112,101, 44, 39, 42, 41, 32, + 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, 39,108,117, + 97, 95,116,111,117,115,101,114,100, 97,116, 97, 40,116,111, + 108,117, 97, 95, 83, 44, 45, 49, 41, 59, 39, 41, 10, 32,101, + 108,115,101,105,102, 32,115,116, 97,116,105, 99, 32,116,104, + 101,110, 10, 32, 32, 95, 44, 95, 44,115,101,108,102, 46,109, + 111,100, 32, 61, 32,115,116,114,102,105,110,100, 40,115,101, + 108,102, 46,109,111,100, 44, 39, 94, 37,115, 42,115,116, 97, + 116,105, 99, 37,115, 37,115, 42, 40, 46, 42, 41, 39, 41, 10, + 32,101,110,100, 10, 10, 32, 45, 45, 32, 99,104,101, 99,107, + 32,105,110,100,101,120, 10, 9,111,117,116,112,117,116, 40, + 39, 35,105,102,110,100,101,102, 32, 84, 79, 76, 85, 65, 95, + 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, 9,111,117, + 116,112,117,116, 40, 39, 32,123, 39, 41, 10, 9,111,117,116, + 112,117,116, 40, 39, 32, 32,116,111,108,117, 97, 95, 69,114, + 114,111,114, 32,116,111,108,117, 97, 95,101,114,114, 59, 39, + 41, 10, 32,111,117,116,112,117,116, 40, 39, 32, 32,105,102, + 32, 40, 33,116,111,108,117, 97, 95,105,115,110,117,109, 98, + 101,114, 40,116,111,108,117, 97, 95, 83, 44, 50, 44, 48, 44, + 38,116,111,108,117, 97, 95,101,114,114, 41, 41, 39, 41, 10, + 32,111,117,116,112,117,116, 40, 39, 32, 32, 32,116,111,108, + 117, 97, 95,101,114,114,111,114, 40,116,111,108,117, 97, 95, + 83, 44, 34, 35,118,105,110,118, 97,108,105,100, 32,116,121, + 112,101, 32,105,110, 32, 97,114,114, 97,121, 32,105,110,100, + 101,120,105,110,103, 46, 34, 44, 38,116,111,108,117, 97, 95, + 101,114,114, 41, 59, 39, 41, 10, 9,111,117,116,112,117,116, + 40, 39, 32,125, 39, 41, 10, 9,111,117,116,112,117,116, 40, + 39, 35,101,110,100,105,102, 92,110, 39, 41, 10, 9,105,102, + 32,102,108, 97,103,115, 91, 39, 49, 39, 93, 32,116,104,101, + 110, 32, 45, 45, 32,102,111,114, 32, 99,111,109,112, 97,116, + 105, 98,105,108,105,116,121, 32,119,105,116,104, 32,116,111, + 108,117, 97, 53, 32, 63, 10, 9, 9,111,117,116,112,117,116, + 40, 39, 32,116,111,108,117, 97, 95,105,110,100,101,120, 32, + 61, 32, 40,105,110,116, 41,116,111,108,117, 97, 95,116,111, + 110,117,109, 98,101,114, 40,116,111,108,117, 97, 95, 83, 44, + 50, 44, 48, 41, 45, 49, 59, 39, 41, 10, 9,101,108,115,101, + 10, 9, 9,111,117,116,112,117,116, 40, 39, 32,116,111,108, + 117, 97, 95,105,110,100,101,120, 32, 61, 32, 40,105,110,116, + 41,116,111,108,117, 97, 95,116,111,110,117,109, 98,101,114, + 40,116,111,108,117, 97, 95, 83, 44, 50, 44, 48, 41, 59, 39, + 41, 10, 9,101,110,100, 10, 9,111,117,116,112,117,116, 40, + 39, 35,105,102,110,100,101,102, 32, 84, 79, 76, 85, 65, 95, + 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, 9,105,102, + 32,115,101,108,102, 46,100,105,109, 32, 97,110,100, 32,115, + 101,108,102, 46,100,105,109, 32,126, 61, 32, 39, 39, 32,116, + 104,101,110, 10, 9, 32, 32,111,117,116,112,117,116, 40, 39, + 32,105,102, 32, 40,116,111,108,117, 97, 95,105,110,100,101, + 120, 60, 48, 32,124,124, 32,116,111,108,117, 97, 95,105,110, + 100,101,120, 62, 61, 39, 46, 46,115,101,108,102, 46,100,105, + 109, 46, 46, 39, 41, 39, 41, 10, 9,101,108,115,101, 10, 9, + 32, 32,111,117,116,112,117,116, 40, 39, 32,105,102, 32, 40, + 116,111,108,117, 97, 95,105,110,100,101,120, 60, 48, 41, 39, + 41, 10, 9,101,110,100, 10, 32,111,117,116,112,117,116, 40, + 39, 32, 32,116,111,108,117, 97, 95,101,114,114,111,114, 40, + 116,111,108,117, 97, 95, 83, 44, 34, 97,114,114, 97,121, 32, + 105,110,100,101,120,105,110,103, 32,111,117,116, 32,111,102, + 32,114, 97,110,103,101, 46, 34, 44, 78, 85, 76, 76, 41, 59, + 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, 35,101,110, + 100,105,102, 92,110, 39, 41, 10, 10, 32, 45, 45, 32,114,101, + 116,117,114,110, 32,118, 97,108,117,101, 10, 32,108,111, 99, + 97,108, 32,116, 44, 99,116, 32, 61, 32,105,115, 98, 97,115, + 105, 99, 40,115,101,108,102, 46,116,121,112,101, 41, 10, 32, + 108,111, 99, 97,108, 32,112,117,115,104, 95,102,117,110, 99, + 32, 61, 32,103,101,116, 95,112,117,115,104, 95,102,117,110, + 99,116,105,111,110, 40,116, 41, 10, 32,105,102, 32,116, 32, + 116,104,101,110, 10, 32, 32,111,117,116,112,117,116, 40, 39, + 32,116,111,108,117, 97, 95,112,117,115,104, 39, 46, 46,116, + 46, 46, 39, 40,116,111,108,117, 97, 95, 83, 44, 40, 39, 44, + 99,116, 44, 39, 41, 39, 46, 46,115,101,108,102, 58,103,101, + 116,118, 97,108,117,101, 40, 99,108, 97,115,115, 44,115,116, + 97,116,105, 99, 41, 46, 46, 39, 41, 59, 39, 41, 10, 32,101, + 108,115,101, 10, 9, 9,116, 32, 61, 32,115,101,108,102, 46, + 116,121,112,101, 10, 32, 32,105,102, 32,115,101,108,102, 46, + 112,116,114, 32, 61, 61, 32, 39, 38, 39, 32,111,114, 32,115, + 101,108,102, 46,112,116,114, 32, 61, 61, 32, 39, 39, 32,116, + 104,101,110, 10, 32, 32, 32,111,117,116,112,117,116, 40, 39, + 32, 39, 44,112,117,115,104, 95,102,117,110, 99, 44, 39, 40, + 116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, 41, + 38, 39, 46, 46,115,101,108,102, 58,103,101,116,118, 97,108, + 117,101, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, 99, + 41, 46, 46, 39, 44, 34, 39, 44,116, 44, 39, 34, 41, 59, 39, + 41, 10, 32, 32,101,108,115,101, 10, 32, 32, 32,111,117,116, + 112,117,116, 40, 39, 32, 39, 44,112,117,115,104, 95,102,117, + 110, 99, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, 40,118, + 111,105,100, 42, 41, 39, 46, 46,115,101,108,102, 58,103,101, + 116,118, 97,108,117,101, 40, 99,108, 97,115,115, 44,115,116, + 97,116,105, 99, 41, 46, 46, 39, 44, 34, 39, 44,116, 44, 39, + 34, 41, 59, 39, 41, 10, 32, 32,101,110,100, 10, 32,101,110, + 100, 10, 32,111,117,116,112,117,116, 40, 39, 32,114,101,116, + 117,114,110, 32, 49, 59, 39, 41, 10, 32,111,117,116,112,117, + 116, 40, 39,125, 39, 41, 10, 32,111,117,116,112,117,116, 40, + 39, 35,101,110,100,105,102, 32, 47, 47, 35,105,102,110,100, + 101,102, 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, 66, 76, + 69, 92,110, 39, 41, 10, 32,111,117,116,112,117,116, 40, 39, + 92,110, 39, 41, 10, 10, 32, 45, 45, 32,115,101,116, 32,102, + 117,110, 99,116,105,111,110, 32, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 10, 32,105,102, + 32,110,111,116, 32,115,116,114,102,105,110,100, 40,115,101, + 108,102, 46,116,121,112,101, 44, 39, 99,111,110,115,116, 39, + 41, 32,116,104,101,110, 10, 32, 32,105,102, 32, 99,108, 97, + 115,115, 32,116,104,101,110, 10, 32, 32, 32,111,117,116,112, + 117,116, 40, 34, 47, 42, 32,115,101,116, 32,102,117,110, 99, + 116,105,111,110, 58, 34, 44,115,101,108,102, 46,110, 97,109, + 101, 44, 34, 32,111,102, 32, 99,108, 97,115,115, 32, 34, 44, + 99,108, 97,115,115, 44, 34, 32, 42, 47, 34, 41, 10, 32, 32, + 101,108,115,101, 10, 32, 32, 32,111,117,116,112,117,116, 40, + 34, 47, 42, 32,115,101,116, 32,102,117,110, 99,116,105,111, + 110, 58, 34, 44,115,101,108,102, 46,110, 97,109,101, 44, 34, + 32, 42, 47, 34, 41, 10, 32, 32,101,110,100, 10, 32, 32,115, + 101,108,102, 46, 99,115,101,116,110, 97,109,101, 32, 61, 32, + 115,101,108,102, 58, 99,102,117,110, 99,110, 97,109,101, 40, + 34,116,111,108,117, 97, 95,115,101,116, 34, 41, 10, 32, 32, + 111,117,116,112,117,116, 40, 34, 35,105,102,110,100,101,102, + 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, 95, + 34, 46, 46,115,101,108,102, 46, 99,115,101,116,110, 97,109, + 101, 41, 10, 32, 32,111,117,116,112,117,116, 40, 34, 92,110, + 115,116, 97,116,105, 99, 32,105,110,116, 34, 44,115,101,108, + 102, 46, 99,115,101,116,110, 97,109,101, 44, 34, 40,108,117, + 97, 95, 83,116, 97,116,101, 42, 32,116,111,108,117, 97, 95, + 83, 41, 34, 41, 10, 32, 32,111,117,116,112,117,116, 40, 34, + 123, 34, 41, 10, 10, 32, 32, 45, 45, 32,100,101, 99,108, 97, + 114,101, 32,105,110,100,101,120, 10, 32, 32,111,117,116,112, + 117,116, 40, 39, 32,105,110,116, 32,116,111,108,117, 97, 95, + 105,110,100,101,120, 59, 39, 41, 10, 10, 32, 32, 45, 45, 32, + 100,101, 99,108, 97,114,101, 32,115,101,108,102, 44, 32,105, + 102, 32,116,104,101, 32, 99, 97,115,101, 10, 32, 32,108,111, + 99, 97,108, 32, 95, 44, 95, 44,115,116, 97,116,105, 99, 32, + 61, 32,115,116,114,102,105,110,100, 40,115,101,108,102, 46, + 109,111,100, 44, 39, 94, 37,115, 42, 40,115,116, 97,116,105, + 99, 41, 39, 41, 10, 32, 32,105,102, 32, 99,108, 97,115,115, + 32, 97,110,100, 32,115,116, 97,116,105, 99, 61, 61,110,105, + 108, 32,116,104,101,110, 10, 32, 32, 32,111,117,116,112,117, + 116, 40, 39, 32, 39, 44,115,101,108,102, 46,112, 97,114,101, + 110,116, 46,116,121,112,101, 44, 39, 42, 39, 44, 39,115,101, + 108,102, 59, 39, 41, 10, 32, 32, 32,111,117,116,112,117,116, + 40, 39, 32,108,117, 97, 95,112,117,115,104,115,116,114,105, + 110,103, 40,116,111,108,117, 97, 95, 83, 44, 34, 46,115,101, + 108,102, 34, 41, 59, 39, 41, 10, 32, 32, 32,111,117,116,112, + 117,116, 40, 39, 32,108,117, 97, 95,114, 97,119,103,101,116, + 40,116,111,108,117, 97, 95, 83, 44, 49, 41, 59, 39, 41, 10, + 32, 32, 32,111,117,116,112,117,116, 40, 39, 32,115,101,108, + 102, 32, 61, 32, 39, 41, 10, 32, 32, 32,111,117,116,112,117, + 116, 40, 39, 40, 39, 44,115,101,108,102, 46,112, 97,114,101, + 110,116, 46,116,121,112,101, 44, 39, 42, 41, 32, 39, 41, 10, + 32, 32, 32,111,117,116,112,117,116, 40, 39,108,117, 97, 95, + 116,111,117,115,101,114,100, 97,116, 97, 40,116,111,108,117, + 97, 95, 83, 44, 45, 49, 41, 59, 39, 41, 10, 32, 32,101,108, + 115,101,105,102, 32,115,116, 97,116,105, 99, 32,116,104,101, + 110, 10, 32, 32, 32, 95, 44, 95, 44,115,101,108,102, 46,109, + 111,100, 32, 61, 32,115,116,114,102,105,110,100, 40,115,101, + 108,102, 46,109,111,100, 44, 39, 94, 37,115, 42,115,116, 97, + 116,105, 99, 37,115, 37,115, 42, 40, 46, 42, 41, 39, 41, 10, + 32, 32,101,110,100, 10, 10, 32, 32, 45, 45, 32, 99,104,101, + 99,107, 32,105,110,100,101,120, 10, 9, 32,111,117,116,112, + 117,116, 40, 39, 35,105,102,110,100,101,102, 32, 84, 79, 76, + 85, 65, 95, 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, + 9, 32,111,117,116,112,117,116, 40, 39, 32,123, 39, 41, 10, + 9, 32,111,117,116,112,117,116, 40, 39, 32, 32,116,111,108, + 117, 97, 95, 69,114,114,111,114, 32,116,111,108,117, 97, 95, + 101,114,114, 59, 39, 41, 10, 32, 32,111,117,116,112,117,116, + 40, 39, 32, 32,105,102, 32, 40, 33,116,111,108,117, 97, 95, + 105,115,110,117,109, 98,101,114, 40,116,111,108,117, 97, 95, + 83, 44, 50, 44, 48, 44, 38,116,111,108,117, 97, 95,101,114, + 114, 41, 41, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, + 39, 32, 32, 32,116,111,108,117, 97, 95,101,114,114,111,114, + 40,116,111,108,117, 97, 95, 83, 44, 34, 35,118,105,110,118, + 97,108,105,100, 32,116,121,112,101, 32,105,110, 32, 97,114, + 114, 97,121, 32,105,110,100,101,120,105,110,103, 46, 34, 44, + 38,116,111,108,117, 97, 95,101,114,114, 41, 59, 39, 41, 10, + 9, 9,111,117,116,112,117,116, 40, 39, 32,125, 39, 41, 10, + 9, 9,111,117,116,112,117,116, 40, 39, 35,101,110,100,105, + 102, 92,110, 39, 41, 10, 10, 9,105,102, 32,102,108, 97,103, + 115, 91, 39, 49, 39, 93, 32,116,104,101,110, 32, 45, 45, 32, + 102,111,114, 32, 99,111,109,112, 97,116,105, 98,105,108,105, + 116,121, 32,119,105,116,104, 32,116,111,108,117, 97, 53, 32, + 63, 10, 9, 9,111,117,116,112,117,116, 40, 39, 32,116,111, + 108,117, 97, 95,105,110,100,101,120, 32, 61, 32, 40,105,110, + 116, 41,116,111,108,117, 97, 95,116,111,110,117,109, 98,101, + 114, 40,116,111,108,117, 97, 95, 83, 44, 50, 44, 48, 41, 45, + 49, 59, 39, 41, 10, 9,101,108,115,101, 10, 9, 9,111,117, + 116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,105,110, + 100,101,120, 32, 61, 32, 40,105,110,116, 41,116,111,108,117, + 97, 95,116,111,110,117,109, 98,101,114, 40,116,111,108,117, + 97, 95, 83, 44, 50, 44, 48, 41, 59, 39, 41, 10, 9,101,110, + 100, 10, 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,105, + 102,110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 82, 69, 76, + 69, 65, 83, 69, 92,110, 39, 41, 10, 9,105,102, 32,115,101, + 108,102, 46,100,105,109, 32, 97,110,100, 32,115,101,108,102, + 46,100,105,109, 32,126, 61, 32, 39, 39, 32,116,104,101,110, + 10, 9, 32, 32,111,117,116,112,117,116, 40, 39, 32,105,102, + 32, 40,116,111,108,117, 97, 95,105,110,100,101,120, 60, 48, + 32,124,124, 32,116,111,108,117, 97, 95,105,110,100,101,120, + 62, 61, 39, 46, 46,115,101,108,102, 46,100,105,109, 46, 46, + 39, 41, 39, 41, 10, 9,101,108,115,101, 10, 9, 32, 32,111, + 117,116,112,117,116, 40, 39, 32,105,102, 32, 40,116,111,108, + 117, 97, 95,105,110,100,101,120, 60, 48, 41, 39, 41, 10, 9, + 101,110,100, 10, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32,116,111,108,117, 97, 95,101,114,114,111,114, 40,116,111, + 108,117, 97, 95, 83, 44, 34, 97,114,114, 97,121, 32,105,110, + 100,101,120,105,110,103, 32,111,117,116, 32,111,102, 32,114, + 97,110,103,101, 46, 34, 44, 78, 85, 76, 76, 41, 59, 39, 41, + 10, 9, 9,111,117,116,112,117,116, 40, 39, 35,101,110,100, + 105,102, 92,110, 39, 41, 10, 10, 32, 32, 45, 45, 32, 97,115, + 115,105,103,110, 32,118, 97,108,117,101, 10, 32, 32,108,111, + 99, 97,108, 32,112,116,114, 32, 61, 32, 39, 39, 10, 32, 32, + 105,102, 32,115,101,108,102, 46,112,116,114,126, 61, 39, 39, + 32,116,104,101,110, 32,112,116,114, 32, 61, 32, 39, 42, 39, + 32,101,110,100, 10, 32, 32,111,117,116,112,117,116, 40, 39, + 32, 39, 41, 10, 32, 32,105,102, 32, 99,108, 97,115,115, 32, + 97,110,100, 32,115,116, 97,116,105, 99, 32,116,104,101,110, + 10, 32, 32, 32,111,117,116,112,117,116, 40, 99,108, 97,115, + 115, 46, 46, 39, 58, 58, 39, 46, 46,115,101,108,102, 46,110, + 97,109,101, 46, 46, 39, 91,116,111,108,117, 97, 95,105,110, + 100,101,120, 93, 39, 41, 10, 32, 32,101,108,115,101,105,102, + 32, 99,108, 97,115,115, 32,116,104,101,110, 10, 32, 32, 32, + 111,117,116,112,117,116, 40, 39,115,101,108,102, 45, 62, 39, + 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 91, + 116,111,108,117, 97, 95,105,110,100,101,120, 93, 39, 41, 10, + 32, 32,101,108,115,101, 10, 32, 32, 32,111,117,116,112,117, + 116, 40,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 91, + 116,111,108,117, 97, 95,105,110,100,101,120, 93, 39, 41, 10, + 32, 32,101,110,100, 10, 32, 32,108,111, 99, 97,108, 32,116, + 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101,108,102, + 46,116,121,112,101, 41, 10, 32, 32,111,117,116,112,117,116, + 40, 39, 32, 61, 32, 39, 41, 10, 32, 32,105,102, 32,110,111, + 116, 32,116, 32, 97,110,100, 32,112,116,114, 61, 61, 39, 39, + 32,116,104,101,110, 32,111,117,116,112,117,116, 40, 39, 42, + 39, 41, 32,101,110,100, 10, 32, 32,111,117,116,112,117,116, + 40, 39, 40, 40, 39, 44,115,101,108,102, 46,109,111,100, 44, + 115,101,108,102, 46,116,121,112,101, 41, 10, 32, 32,105,102, + 32,110,111,116, 32,116, 32,116,104,101,110, 10, 32, 32, 32, + 111,117,116,112,117,116, 40, 39, 42, 39, 41, 10, 32, 32,101, + 110,100, 10, 32, 32,111,117,116,112,117,116, 40, 39, 41, 32, + 39, 41, 10, 32, 32,108,111, 99, 97,108, 32,100,101,102, 32, + 61, 32, 48, 10, 32, 32,105,102, 32,115,101,108,102, 46,100, + 101,102, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 32,100, + 101,102, 32, 61, 32,115,101,108,102, 46,100,101,102, 32,101, + 110,100, 10, 32, 32,105,102, 32,116, 32,116,104,101,110, 10, + 32, 32, 32,111,117,116,112,117,116, 40, 39,116,111,108,117, + 97, 95,116,111, 39, 46, 46,116, 44, 39, 40,116,111,108,117, + 97, 95, 83, 44, 51, 44, 39, 44,100,101,102, 44, 39, 41, 41, + 59, 39, 41, 10, 32, 32,101,108,115,101, 10, 32, 32, 32,108, + 111, 99, 97,108, 32,116,111, 95,102,117,110, 99, 32, 61, 32, + 103,101,116, 95,116,111, 95,102,117,110, 99,116,105,111,110, + 40,115,101,108,102, 46,116,121,112,101, 41, 10, 32, 32, 32, + 111,117,116,112,117,116, 40,116,111, 95,102,117,110, 99, 44, + 39, 40,116,111,108,117, 97, 95, 83, 44, 51, 44, 39, 44,100, + 101,102, 44, 39, 41, 41, 59, 39, 41, 10, 32, 32,101,110,100, + 10, 32, 32,111,117,116,112,117,116, 40, 39, 32,114,101,116, + 117,114,110, 32, 48, 59, 39, 41, 10, 32, 32,111,117,116,112, + 117,116, 40, 39,125, 39, 41, 10, 32, 32,111,117,116,112,117, + 116, 40, 39, 35,101,110,100,105,102, 32, 47, 47, 35,105,102, + 110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, + 66, 76, 69, 92,110, 39, 41, 10, 32, 32,111,117,116,112,117, + 116, 40, 39, 92,110, 39, 41, 10, 32,101,110,100, 10, 10,101, + 110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, + 97,115,115, 65,114,114, 97,121, 58,114,101,103,105,115,116, + 101,114, 32, 40,112,114,101, 41, 10, 9,105,102, 32,110,111, + 116, 32,115,101,108,102, 58, 99,104,101, 99,107, 95,112,117, + 98,108,105, 99, 95, 97, 99, 99,101,115,115, 40, 41, 32,116, + 104,101,110, 10, 9, 9,114,101,116,117,114,110, 10, 9,101, + 110,100, 10, 10, 32,112,114,101, 32, 61, 32,112,114,101, 32, + 111,114, 32, 39, 39, 10, 32,105,102, 32,115,101,108,102, 46, + 99,115,101,116,110, 97,109,101, 32,116,104,101,110, 10, 32, + 32,111,117,116,112,117,116, 40,112,114,101, 46, 46, 39,116, + 111,108,117, 97, 95, 97,114,114, 97,121, 40,116,111,108,117, + 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, + 97,109,101, 46, 46, 39, 34, 44, 39, 46, 46,115,101,108,102, + 46, 99,103,101,116,110, 97,109,101, 46, 46, 39, 44, 39, 46, + 46,115,101,108,102, 46, 99,115,101,116,110, 97,109,101, 46, + 46, 39, 41, 59, 39, 41, 10, 32,101,108,115,101, 10, 32, 32, + 111,117,116,112,117,116, 40,112,114,101, 46, 46, 39,116,111, + 108,117, 97, 95, 97,114,114, 97,121, 40,116,111,108,117, 97, + 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, 97, + 109,101, 46, 46, 39, 34, 44, 39, 46, 46,115,101,108,102, 46, + 99,103,101,116,110, 97,109,101, 46, 46, 39, 44, 78, 85, 76, + 76, 41, 59, 39, 41, 10, 32,101,110,100, 10,101,110,100, 10, + 10, 45, 45, 32, 73,110,116,101,114,110, 97,108, 32, 99,111, + 110,115,116,114,117, 99,116,111,114, 10,102,117,110, 99,116, + 105,111,110, 32, 95, 65,114,114, 97,121, 32, 40,116, 41, 10, + 32,115,101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, + 44, 99,108, 97,115,115, 65,114,114, 97,121, 41, 10, 32, 97, + 112,112,101,110,100, 40,116, 41, 10, 32,114,101,116,117,114, + 110, 32,116, 10,101,110,100, 10, 10, 45, 45, 32, 67,111,110, + 115,116,114,117, 99,116,111,114, 10, 45, 45, 32, 69,120,112, + 101, 99,116,115, 32, 97, 32,115,116,114,105,110,103, 32,114, + 101,112,114,101,115,101,110,116,105,110,103, 32,116,104,101, + 32,118, 97,114,105, 97, 98,108,101, 32,100,101, 99,108, 97, + 114, 97,116,105,111,110, 46, 10,102,117,110, 99,116,105,111, + 110, 32, 65,114,114, 97,121, 32, 40,115, 41, 10, 32,114,101, + 116,117,114,110, 32, 95, 65,114,114, 97,121, 32, 40, 68,101, + 99,108, 97,114, 97,116,105,111,110, 40,115, 44, 39,118, 97, + 114, 39, 41, 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/array.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114, + 105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, + 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, + 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, + 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73, + 100, 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99, + 111,100,101, 32,105,115, 32,102,114,101,101, 32,115,111,102, + 116,119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32, + 114,101,100,105,115,116,114,105, 98,117,116,101, 32,105,116, + 32, 97,110,100, 47,111,114, 32,109,111,100,105,102,121, 32, + 105,116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116, + 119, 97,114,101, 32,112,114,111,118,105,100,101,100, 32,104, + 101,114,101,117,110,100,101,114, 32,105,115, 32,111,110, 32, + 97,110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105, + 115, 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97, + 117,116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98, + 108,105,103, 97,116,105,111,110, 32,116,111, 32,112,114,111, + 118,105,100,101, 32,109, 97,105,110,116,101,110, 97,110, 99, + 101, 44, 32,115,117,112,112,111,114,116, 44, 32,117,112,100, + 97,116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99, + 101,109,101,110,116,115, 44, 32,111,114, 32,109,111,100,105, + 102,105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 10, 45, + 45, 32, 70,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 10, 45, 45, 32, 82,101,112,114,101,115,101,110,116,115, + 32, 97, 32,102,117,110, 99,116,105,111,110, 32,111,114, 32, + 97, 32, 99,108, 97,115,115, 32,109,101,116,104,111,100, 46, + 10, 45, 45, 32, 84,104,101, 32,102,111,108,108,111,119,105, + 110,103, 32,102,105,101,108,100,115, 32, 97,114,101, 32,115, + 116,111,114,101,100, 58, 10, 45, 45, 32, 32,109,111,100, 32, + 32, 61, 32,116,121,112,101, 32,109,111,100,105,102,105,101, + 114,115, 10, 45, 45, 32, 32,116,121,112,101, 32, 61, 32,116, + 121,112,101, 10, 45, 45, 32, 32,112,116,114, 32, 32, 61, 32, + 34, 42, 34, 32,111,114, 32, 34, 38, 34, 44, 32,105,102, 32, + 114,101,112,114,101,115,101,110,116,105,110,103, 32, 97, 32, + 112,111,105,110,116,101,114, 32,111,114, 32, 97, 32,114,101, + 102,101,114,101,110, 99,101, 10, 45, 45, 32, 32,110, 97,109, + 101, 32, 61, 32,110, 97,109,101, 10, 45, 45, 32, 32,108,110, + 97,109,101, 32, 61, 32,108,117, 97, 32,110, 97,109,101, 10, + 45, 45, 32, 32, 97,114,103,115, 32, 32, 61, 32,108,105,115, + 116, 32,111,102, 32, 97,114,103,117,109,101,110,116, 32,100, + 101, 99,108, 97,114, 97,116,105,111,110,115, 10, 45, 45, 32, + 32, 99,111,110,115,116, 32, 61, 32,105,102, 32,105,116, 32, + 105,115, 32, 97, 32,109,101,116,104,111,100, 32,114,101, 99, + 101,105,118,105,110,103, 32, 97, 32, 99,111,110,115,116, 32, + 34,116,104,105,115, 34, 46, 10, 99,108, 97,115,115, 70,117, + 110, 99,116,105,111,110, 32, 61, 32,123, 10, 32,109,111,100, + 32, 61, 32, 39, 39, 44, 10, 32,116,121,112,101, 32, 61, 32, + 39, 39, 44, 10, 32,112,116,114, 32, 61, 32, 39, 39, 44, 10, + 32,110, 97,109,101, 32, 61, 32, 39, 39, 44, 10, 32, 97,114, + 103,115, 32, 61, 32,123,110, 61, 48,125, 44, 10, 32, 99,111, + 110,115,116, 32, 61, 32, 39, 39, 44, 10,125, 10, 99,108, 97, + 115,115, 70,117,110, 99,116,105,111,110, 46, 95, 95,105,110, + 100,101,120, 32, 61, 32, 99,108, 97,115,115, 70,117,110, 99, + 116,105,111,110, 10,115,101,116,109,101,116, 97,116, 97, 98, + 108,101, 40, 99,108, 97,115,115, 70,117,110, 99,116,105,111, + 110, 44, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 41, + 10, 10, 45, 45, 32,100,101, 99,108, 97,114,101, 32,116, 97, + 103,115, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 70,117,110, 99,116,105,111,110, 58,100,101, 99,108, + 116,121,112,101, 32, 40, 41, 10, 32,115,101,108,102, 46,116, + 121,112,101, 32, 61, 32,116,121,112,101,118, 97,114, 40,115, + 101,108,102, 46,116,121,112,101, 41, 10, 32,105,102, 32,115, + 116,114,102,105,110,100, 40,115,101,108,102, 46,109,111,100, + 44, 39, 99,111,110,115,116, 39, 41, 32,116,104,101,110, 10, + 9, 32,115,101,108,102, 46,116,121,112,101, 32, 61, 32, 39, + 99,111,110,115,116, 32, 39, 46, 46,115,101,108,102, 46,116, + 121,112,101, 10, 9, 9,115,101,108,102, 46,109,111,100, 32, + 61, 32,103,115,117, 98, 40,115,101,108,102, 46,109,111,100, + 44, 39, 99,111,110,115,116, 39, 44, 39, 39, 41, 10, 9,101, + 110,100, 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32, + 119,104,105,108,101, 32,115,101,108,102, 46, 97,114,103,115, + 91,105, 93, 32,100,111, 10, 32, 32,115,101,108,102, 46, 97, + 114,103,115, 91,105, 93, 58,100,101, 99,108,116,121,112,101, + 40, 41, 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101, + 110,100, 10,101,110,100, 10, 10, 10, 45, 45, 32, 87,114,105, + 116,101, 32, 98,105,110,100,105,110,103, 32,102,117,110, 99, + 116,105,111,110, 10, 45, 45, 32, 79,117,116,112,117,116,115, + 32, 67, 47, 67, 43, 43, 32, 98,105,110,100,105,110,103, 32, + 102,117,110, 99,116,105,111,110, 46, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 70,117,110, 99,116,105, + 111,110, 58,115,117,112, 99,111,100,101, 32, 40,108,111, 99, + 97,108, 95, 99,111,110,115,116,114,117, 99,116,111,114, 41, + 10, 10, 32,108,111, 99, 97,108, 32,111,118,101,114,108,111, + 97,100, 32, 61, 32,115,116,114,115,117, 98, 40,115,101,108, + 102, 46, 99,110, 97,109,101, 44, 45, 50, 44, 45, 49, 41, 32, + 45, 32, 49, 32, 32, 45, 45, 32,105,110,100,105, 99, 97,116, + 101, 32,111,118,101,114,108,111, 97,100,101,100, 32,102,117, + 110, 99, 10, 32,108,111, 99, 97,108, 32,110,114,101,116, 32, + 61, 32, 48, 32, 32, 32, 32, 32, 32, 45, 45, 32,110,117,109, + 98,101,114, 32,111,102, 32,114,101,116,117,114,110,101,100, + 32,118, 97,108,117,101,115, 10, 32,108,111, 99, 97,108, 32, + 99,108, 97,115,115, 32, 61, 32,115,101,108,102, 58,105,110, + 99,108, 97,115,115, 40, 41, 10, 32,108,111, 99, 97,108, 32, + 95, 44, 95, 44,115,116, 97,116,105, 99, 32, 61, 32,115,116, + 114,102,105,110,100, 40,115,101,108,102, 46,109,111,100, 44, + 39, 94, 37,115, 42, 40,115,116, 97,116,105, 99, 41, 39, 41, + 10, 32,105,102, 32, 99,108, 97,115,115, 32,116,104,101,110, + 10, 10, 32, 9,105,102, 32,115,101,108,102, 46,110, 97,109, + 101, 32, 61, 61, 32, 39,110,101,119, 39, 32, 97,110,100, 32, + 115,101,108,102, 46,112, 97,114,101,110,116, 46,102,108, 97, + 103,115, 46,112,117,114,101, 95,118,105,114,116,117, 97,108, + 32,116,104,101,110, 10, 32, 9, 9, 45, 45, 32,110,111, 32, + 99,111,110,115,116,114,117, 99,116,111,114, 32,102,111,114, + 32, 99,108, 97,115,115,101,115, 32,119,105,116,104, 32,112, + 117,114,101, 32,118,105,114,116,117, 97,108, 32,109,101,116, + 104,111,100,115, 10, 32, 9, 9,114,101,116,117,114,110, 10, + 32, 9,101,110,100, 10, 10, 32, 9,105,102, 32,108,111, 99, + 97,108, 95, 99,111,110,115,116,114,117, 99,116,111,114, 32, + 116,104,101,110, 10, 9, 9,111,117,116,112,117,116, 40, 34, + 47, 42, 32,109,101,116,104,111,100, 58, 32,110,101,119, 95, + 108,111, 99, 97,108, 32,111,102, 32, 99,108, 97,115,115, 32, + 34, 44, 99,108, 97,115,115, 44, 34, 32, 42, 47, 34, 41, 10, + 9,101,108,115,101, 10, 9, 9,111,117,116,112,117,116, 40, + 34, 47, 42, 32,109,101,116,104,111,100, 58, 34, 44,115,101, + 108,102, 46,110, 97,109,101, 44, 34, 32,111,102, 32, 99,108, + 97,115,115, 32, 34, 44, 99,108, 97,115,115, 44, 34, 32, 42, + 47, 34, 41, 10, 9,101,110,100, 10, 32,101,108,115,101, 10, + 32, 32,111,117,116,112,117,116, 40, 34, 47, 42, 32,102,117, + 110, 99,116,105,111,110, 58, 34, 44,115,101,108,102, 46,110, + 97,109,101, 44, 34, 32, 42, 47, 34, 41, 10, 32,101,110,100, + 10, 10, 32,105,102, 32,108,111, 99, 97,108, 95, 99,111,110, + 115,116,114,117, 99,116,111,114, 32,116,104,101,110, 10, 32, + 32,111,117,116,112,117,116, 40, 34, 35,105,102,110,100,101, + 102, 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, + 95, 34, 46, 46,115,101,108,102, 46, 99,110, 97,109,101, 46, + 46, 34, 95,108,111, 99, 97,108, 34, 41, 10, 32, 32,111,117, + 116,112,117,116, 40, 34, 92,110,115,116, 97,116,105, 99, 32, + 105,110,116, 34, 44,115,101,108,102, 46, 99,110, 97,109,101, + 46, 46, 34, 95,108,111, 99, 97,108, 34, 44, 34, 40,108,117, + 97, 95, 83,116, 97,116,101, 42, 32,116,111,108,117, 97, 95, + 83, 41, 34, 41, 10, 32,101,108,115,101, 10, 32, 32,111,117, + 116,112,117,116, 40, 34, 35,105,102,110,100,101,102, 32, 84, + 79, 76, 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, 95, 34, 46, + 46,115,101,108,102, 46, 99,110, 97,109,101, 41, 10, 32, 32, + 111,117,116,112,117,116, 40, 34, 92,110,115,116, 97,116,105, + 99, 32,105,110,116, 34, 44,115,101,108,102, 46, 99,110, 97, + 109,101, 44, 34, 40,108,117, 97, 95, 83,116, 97,116,101, 42, + 32,116,111,108,117, 97, 95, 83, 41, 34, 41, 10, 32,101,110, + 100, 10, 32,111,117,116,112,117,116, 40, 34,123, 34, 41, 10, + 10, 32, 45, 45, 32, 99,104,101, 99,107, 32,116,121,112,101, + 115, 10, 9,105,102, 32,111,118,101,114,108,111, 97,100, 32, + 60, 32, 48, 32,116,104,101,110, 10, 9, 32,111,117,116,112, + 117,116, 40, 39, 35,105,102,110,100,101,102, 32, 84, 79, 76, + 85, 65, 95, 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, + 9,101,110,100, 10, 9,111,117,116,112,117,116, 40, 39, 32, + 116,111,108,117, 97, 95, 69,114,114,111,114, 32,116,111,108, + 117, 97, 95,101,114,114, 59, 39, 41, 10, 32,111,117,116,112, + 117,116, 40, 39, 32,105,102, 32, 40, 92,110, 39, 41, 10, 32, + 45, 45, 32, 99,104,101, 99,107, 32,115,101,108,102, 10, 32, + 108,111, 99, 97,108, 32,110, 97,114,103, 10, 32,105,102, 32, + 99,108, 97,115,115, 32,116,104,101,110, 32,110, 97,114,103, + 61, 50, 32,101,108,115,101, 32,110, 97,114,103, 61, 49, 32, + 101,110,100, 10, 32,105,102, 32, 99,108, 97,115,115, 32,116, + 104,101,110, 10, 9, 9,108,111, 99, 97,108, 32,102,117,110, + 99, 32, 61, 32,103,101,116, 95,105,115, 95,102,117,110, 99, + 116,105,111,110, 40,115,101,108,102, 46,112, 97,114,101,110, + 116, 46,116,121,112,101, 41, 10, 9, 9,108,111, 99, 97,108, + 32,116,121,112,101, 32, 61, 32,115,101,108,102, 46,112, 97, + 114,101,110,116, 46,116,121,112,101, 10, 9, 9,105,102, 32, + 115,101,108,102, 46,110, 97,109,101, 61, 61, 39,110,101,119, + 39, 32,111,114, 32,115,116, 97,116,105, 99,126, 61,110,105, + 108, 32,116,104,101,110, 10, 9, 9, 9,102,117,110, 99, 32, + 61, 32, 39,116,111,108,117, 97, 95,105,115,117,115,101,114, + 116, 97, 98,108,101, 39, 10, 9, 9, 9,116,121,112,101, 32, + 61, 32,115,101,108,102, 46,112, 97,114,101,110,116, 46,116, + 121,112,101, 10, 9, 9,101,110,100, 10, 9, 9,105,102, 32, + 115,101,108,102, 46, 99,111,110,115,116, 32,126, 61, 32, 39, + 39, 32,116,104,101,110, 10, 9, 9, 9,116,121,112,101, 32, + 61, 32, 34, 99,111,110,115,116, 32, 34, 46, 46,116,121,112, + 101, 10, 9, 9,101,110,100, 10, 9, 9,111,117,116,112,117, + 116, 40, 39, 32, 32, 32, 32, 32, 33, 39, 46, 46,102,117,110, + 99, 46, 46, 39, 40,116,111,108,117, 97, 95, 83, 44, 49, 44, + 34, 39, 46, 46,116,121,112,101, 46, 46, 39, 34, 44, 48, 44, + 38,116,111,108,117, 97, 95,101,114,114, 41, 32,124,124, 92, + 110, 39, 41, 10, 32,101,110,100, 10, 32, 45, 45, 32, 99,104, + 101, 99,107, 32, 97,114,103,115, 10, 32,105,102, 32,115,101, + 108,102, 46, 97,114,103,115, 91, 49, 93, 46,116,121,112,101, + 32,126, 61, 32, 39,118,111,105,100, 39, 32,116,104,101,110, + 10, 32, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32, 32, + 119,104,105,108,101, 32,115,101,108,102, 46, 97,114,103,115, + 91,105, 93, 32,100,111, 10, 32, 32, 32,108,111, 99, 97,108, + 32, 98,116,121,112,101, 32, 61, 32,105,115, 98, 97,115,105, + 99, 40,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 46, + 116,121,112,101, 41, 10, 32, 32, 32,105,102, 32, 98,116,121, + 112,101, 32,126, 61, 32, 39,118, 97,108,117,101, 39, 32, 97, + 110,100, 32, 98,116,121,112,101, 32,126, 61, 32, 39,115,116, + 97,116,101, 39, 32,116,104,101,110, 10, 32, 32, 32, 32,111, + 117,116,112,117,116, 40, 39, 32, 32, 32, 32, 32, 39, 46, 46, + 115,101,108,102, 46, 97,114,103,115, 91,105, 93, 58,111,117, + 116, 99,104,101, 99,107,116,121,112,101, 40,110, 97,114,103, + 41, 46, 46, 39, 32,124,124, 92,110, 39, 41, 10, 32, 32, 32, + 101,110,100, 10, 32, 32, 32,105,102, 32, 98,116,121,112,101, + 32,126, 61, 32, 39,115,116, 97,116,101, 39, 32,116,104,101, + 110, 10, 9, 32, 32, 32,110, 97,114,103, 32, 61, 32,110, 97, + 114,103, 43, 49, 10, 32, 32, 32,101,110,100, 10, 32, 32, 32, + 105, 32, 61, 32,105, 43, 49, 10, 32, 32,101,110,100, 10, 32, + 101,110,100, 10, 32, 45, 45, 32, 99,104,101, 99,107, 32,101, + 110,100, 32,111,102, 32,108,105,115,116, 10, 32,111,117,116, + 112,117,116, 40, 39, 32, 32, 32, 32, 32, 33,116,111,108,117, + 97, 95,105,115,110,111,111, 98,106, 40,116,111,108,117, 97, + 95, 83, 44, 39, 46, 46,110, 97,114,103, 46, 46, 39, 44, 38, + 116,111,108,117, 97, 95,101,114,114, 41, 92,110, 32, 41, 39, + 41, 10, 9,111,117,116,112,117,116, 40, 39, 32, 32,103,111, + 116,111, 32,116,111,108,117, 97, 95,108,101,114,114,111,114, + 59, 39, 41, 10, 10, 32,111,117,116,112,117,116, 40, 39, 32, + 101,108,115,101, 92,110, 39, 41, 10, 9,105,102, 32,111,118, + 101,114,108,111, 97,100, 32, 60, 32, 48, 32,116,104,101,110, + 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,101,110,100, + 105,102, 92,110, 39, 41, 10, 9,101,110,100, 10, 9,111,117, + 116,112,117,116, 40, 39, 32,123, 39, 41, 10, 10, 32, 45, 45, + 32,100,101, 99,108, 97,114,101, 32,115,101,108,102, 44, 32, + 105,102, 32,116,104,101, 32, 99, 97,115,101, 10, 32,108,111, + 99, 97,108, 32,110, 97,114,103, 10, 32,105,102, 32, 99,108, + 97,115,115, 32,116,104,101,110, 32,110, 97,114,103, 61, 50, + 32,101,108,115,101, 32,110, 97,114,103, 61, 49, 32,101,110, + 100, 10, 32,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, + 32,115,101,108,102, 46,110, 97,109,101,126, 61, 39,110,101, + 119, 39, 32, 97,110,100, 32,115,116, 97,116,105, 99, 61, 61, + 110,105,108, 32,116,104,101,110, 10, 32, 32,111,117,116,112, + 117,116, 40, 39, 32, 39, 44,115,101,108,102, 46, 99,111,110, + 115,116, 44,115,101,108,102, 46,112, 97,114,101,110,116, 46, + 116,121,112,101, 44, 39, 42, 39, 44, 39,115,101,108,102, 32, + 61, 32, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40, 39, + 40, 39, 44,115,101,108,102, 46, 99,111,110,115,116, 44,115, + 101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112,101, + 44, 39, 42, 41, 32, 39, 41, 10, 32, 32,108,111, 99, 97,108, + 32,116,111, 95,102,117,110, 99, 32, 61, 32,103,101,116, 95, + 116,111, 95,102,117,110, 99,116,105,111,110, 40,115,101,108, + 102, 46,112, 97,114,101,110,116, 46,116,121,112,101, 41, 10, + 32, 32,111,117,116,112,117,116, 40,116,111, 95,102,117,110, + 99, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, 49, 44, 48, + 41, 59, 39, 41, 10, 32,101,108,115,101,105,102, 32,115,116, + 97,116,105, 99, 32,116,104,101,110, 10, 32, 32, 95, 44, 95, + 44,115,101,108,102, 46,109,111,100, 32, 61, 32,115,116,114, + 102,105,110,100, 40,115,101,108,102, 46,109,111,100, 44, 39, + 94, 37,115, 42,115,116, 97,116,105, 99, 37,115, 37,115, 42, + 40, 46, 42, 41, 39, 41, 10, 32,101,110,100, 10, 32, 45, 45, + 32,100,101, 99,108, 97,114,101, 32,112, 97,114, 97,109,101, + 116,101,114,115, 10, 32,105,102, 32,115,101,108,102, 46, 97, + 114,103,115, 91, 49, 93, 46,116,121,112,101, 32,126, 61, 32, + 39,118,111,105,100, 39, 32,116,104,101,110, 10, 32, 32,108, + 111, 99, 97,108, 32,105, 61, 49, 10, 32, 32,119,104,105,108, + 101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32, + 100,111, 10, 32, 32, 32,115,101,108,102, 46, 97,114,103,115, + 91,105, 93, 58,100,101, 99,108, 97,114,101, 40,110, 97,114, + 103, 41, 10, 32, 32, 32,105,102, 32,105,115, 98, 97,115,105, + 99, 40,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 46, + 116,121,112,101, 41, 32,126, 61, 32, 34,115,116, 97,116,101, + 34, 32,116,104,101,110, 10, 9, 32, 32, 32,110, 97,114,103, + 32, 61, 32,110, 97,114,103, 43, 49, 10, 32, 32, 32,101,110, + 100, 10, 32, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32, 32, + 101,110,100, 10, 32,101,110,100, 10, 10, 32, 45, 45, 32, 99, + 104,101, 99,107, 32,115,101,108,102, 10, 32,105,102, 32, 99, + 108, 97,115,115, 32, 97,110,100, 32,115,101,108,102, 46,110, + 97,109,101,126, 61, 39,110,101,119, 39, 32, 97,110,100, 32, + 115,116, 97,116,105, 99, 61, 61,110,105,108, 32,116,104,101, + 110, 10, 9, 32,111,117,116,112,117,116, 40, 39, 35,105,102, + 110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 82, 69, 76, 69, + 65, 83, 69, 92,110, 39, 41, 10, 32, 32,111,117,116,112,117, + 116, 40, 39, 32, 32,105,102, 32, 40, 33,115,101,108,102, 41, + 32,116,111,108,117, 97, 95,101,114,114,111,114, 40,116,111, + 108,117, 97, 95, 83, 44, 34,105,110,118, 97,108,105,100, 32, + 92, 39,115,101,108,102, 92, 39, 32,105,110, 32,102,117,110, + 99,116,105,111,110, 32, 92, 39, 39, 46, 46,115,101,108,102, + 46,110, 97,109,101, 46, 46, 39, 92, 39, 34, 44, 78, 85, 76, + 76, 41, 59, 39, 41, 59, 10, 9, 32,111,117,116,112,117,116, + 40, 39, 35,101,110,100,105,102, 92,110, 39, 41, 10, 32,101, + 110,100, 10, 10, 32, 45, 45, 32,103,101,116, 32, 97,114,114, + 97,121, 32,101,108,101,109,101,110,116, 32,118, 97,108,117, + 101,115, 10, 32,105,102, 32, 99,108, 97,115,115, 32,116,104, + 101,110, 32,110, 97,114,103, 61, 50, 32,101,108,115,101, 32, + 110, 97,114,103, 61, 49, 32,101,110,100, 10, 32,105,102, 32, + 115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46,116,121, + 112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32,116,104, + 101,110, 10, 32, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, + 32, 32,119,104,105,108,101, 32,115,101,108,102, 46, 97,114, + 103,115, 91,105, 93, 32,100,111, 10, 32, 32, 32,115,101,108, + 102, 46, 97,114,103,115, 91,105, 93, 58,103,101,116, 97,114, + 114, 97,121, 40,110, 97,114,103, 41, 10, 32, 32, 32,110, 97, + 114,103, 32, 61, 32,110, 97,114,103, 43, 49, 10, 32, 32, 32, + 105, 32, 61, 32,105, 43, 49, 10, 32, 32,101,110,100, 10, 32, + 101,110,100, 10, 10, 32,108,111, 99, 97,108, 32,111,117,116, + 32, 61, 32,115,116,114,105,110,103, 46,102,105,110,100, 40, + 115,101,108,102, 46,109,111,100, 44, 32, 34,116,111,108,117, + 97, 95,111,117,116,115,105,100,101, 34, 41, 10, 32, 45, 45, + 32, 99, 97,108,108, 32,102,117,110, 99,116,105,111,110, 10, + 32,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32,115, + 101,108,102, 46,110, 97,109,101, 61, 61, 39,100,101,108,101, + 116,101, 39, 32,116,104,101,110, 10, 32, 32,111,117,116,112, + 117,116, 40, 39, 32, 32, 77,116,111,108,117, 97, 95,100,101, + 108,101,116,101, 40,115,101,108,102, 41, 59, 39, 41, 10, 32, + 101,108,115,101,105,102, 32, 99,108, 97,115,115, 32, 97,110, + 100, 32,115,101,108,102, 46,110, 97,109,101, 32, 61, 61, 32, + 39,111,112,101,114, 97,116,111,114, 38, 91, 93, 39, 32,116, + 104,101,110, 10, 32, 32,105,102, 32,102,108, 97,103,115, 91, + 39, 49, 39, 93, 32,116,104,101,110, 32, 45, 45, 32,102,111, + 114, 32, 99,111,109,112, 97,116,105, 98,105,108,105,116,121, + 32,119,105,116,104, 32,116,111,108,117, 97, 53, 32, 63, 10, + 9,111,117,116,112,117,116, 40, 39, 32, 32,115,101,108,102, + 45, 62,111,112,101,114, 97,116,111,114, 91, 93, 40, 39, 44, + 115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46,110, 97, + 109,101, 44, 39, 45, 49, 41, 32, 61, 32, 39, 44,115,101,108, + 102, 46, 97,114,103,115, 91, 50, 93, 46,110, 97,109,101, 44, + 39, 59, 39, 41, 10, 32, 32,101,108,115,101, 10, 32, 32, 32, + 32,111,117,116,112,117,116, 40, 39, 32, 32,115,101,108,102, + 45, 62,111,112,101,114, 97,116,111,114, 91, 93, 40, 39, 44, + 115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46,110, 97, + 109,101, 44, 39, 41, 32, 61, 32, 39, 44,115,101,108,102, 46, + 97,114,103,115, 91, 50, 93, 46,110, 97,109,101, 44, 39, 59, + 39, 41, 10, 32, 32,101,110,100, 10, 32,101,108,115,101, 10, + 32, 32,111,117,116,112,117,116, 40, 39, 32, 32,123, 39, 41, + 10, 32, 32,105,102, 32,115,101,108,102, 46,116,121,112,101, + 32,126, 61, 32, 39, 39, 32, 97,110,100, 32,115,101,108,102, + 46,116,121,112,101, 32,126, 61, 32, 39,118,111,105,100, 39, + 32,116,104,101,110, 10, 32, 32, 32,111,117,116,112,117,116, + 40, 39, 32, 32, 39, 44,115,101,108,102, 46,109,111,100, 44, + 115,101,108,102, 46,116,121,112,101, 44,115,101,108,102, 46, + 112,116,114, 44, 39,116,111,108,117, 97, 95,114,101,116, 32, + 61, 32, 39, 41, 10, 32, 32, 32,111,117,116,112,117,116, 40, + 39, 40, 39, 44,115,101,108,102, 46,109,111,100, 44,115,101, + 108,102, 46,116,121,112,101, 44,115,101,108,102, 46,112,116, + 114, 44, 39, 41, 32, 39, 41, 10, 32, 32,101,108,115,101, 10, + 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, 39, 41, + 10, 32, 32,101,110,100, 10, 32, 32,105,102, 32, 99,108, 97, + 115,115, 32, 97,110,100, 32,115,101,108,102, 46,110, 97,109, + 101, 61, 61, 39,110,101,119, 39, 32,116,104,101,110, 10, 32, + 32, 32,111,117,116,112,117,116, 40, 39, 77,116,111,108,117, + 97, 95,110,101,119, 40, 40, 39, 44,115,101,108,102, 46,116, + 121,112,101, 44, 39, 41, 40, 39, 41, 10, 32, 32,101,108,115, + 101,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32,115, + 116, 97,116,105, 99, 32,116,104,101,110, 10, 9,105,102, 32, + 111,117,116, 32,116,104,101,110, 10, 9, 9,111,117,116,112, + 117,116, 40,115,101,108,102, 46,110, 97,109,101, 44, 39, 40, + 39, 41, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,112, + 117,116, 40, 99,108, 97,115,115, 46, 46, 39, 58, 58, 39, 46, + 46,115,101,108,102, 46,110, 97,109,101, 44, 39, 40, 39, 41, + 10, 9,101,110,100, 10, 32, 32,101,108,115,101,105,102, 32, + 99,108, 97,115,115, 32,116,104,101,110, 10, 9,105,102, 32, + 111,117,116, 32,116,104,101,110, 10, 9, 9,111,117,116,112, + 117,116, 40,115,101,108,102, 46,110, 97,109,101, 44, 39, 40, + 39, 41, 10, 9,101,108,115,101, 10, 9, 32, 32,105,102, 32, + 115,101,108,102, 46, 99, 97,115,116, 95,111,112,101,114, 97, + 116,111,114, 32,116,104,101,110, 10, 9, 32, 32, 9, 45, 45, + 111,117,116,112,117,116, 40, 39,115,116, 97,116,105, 99, 95, + 99, 97,115,116, 60, 39, 44,115,101,108,102, 46,109,111,100, + 44,115,101,108,102, 46,116,121,112,101, 44,115,101,108,102, + 46,112,116,114, 44, 39, 62, 40, 42,115,101,108,102, 39, 41, + 10, 9, 9,111,117,116,112,117,116, 40, 39,115,101,108,102, + 45, 62,111,112,101,114, 97,116,111,114, 32, 39, 44,115,101, + 108,102, 46,109,111,100, 44,115,101,108,102, 46,116,121,112, + 101, 44, 39, 40, 39, 41, 10, 9, 32, 32,101,108,115,101, 10, + 9, 9,111,117,116,112,117,116, 40, 39,115,101,108,102, 45, + 62, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 44, 39, + 40, 39, 41, 10, 9, 32, 32,101,110,100, 10, 9,101,110,100, + 10, 32, 32,101,108,115,101, 10, 32, 32, 32,111,117,116,112, + 117,116, 40,115,101,108,102, 46,110, 97,109,101, 44, 39, 40, + 39, 41, 10, 32, 32,101,110,100, 10, 10, 32, 32,105,102, 32, + 111,117,116, 32, 97,110,100, 32,110,111,116, 32,115,116, 97, + 116,105, 99, 32,116,104,101,110, 10, 32, 32, 9,111,117,116, + 112,117,116, 40, 39,115,101,108,102, 39, 41, 10, 9,105,102, + 32,115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 32, 97, + 110,100, 32,115,101,108,102, 46, 97,114,103,115, 91, 49, 93, + 46,110, 97,109,101, 32,126, 61, 32, 39, 39, 32,116,104,101, + 110, 10, 9, 9,111,117,116,112,117,116, 40, 39, 44, 39, 41, + 10, 9,101,110,100, 10, 32, 32,101,110,100, 10, 32, 32, 45, + 45, 32,119,114,105,116,101, 32,112, 97,114, 97,109,101,116, + 101,114,115, 10, 32, 32,108,111, 99, 97,108, 32,105, 61, 49, + 10, 32, 32,119,104,105,108,101, 32,115,101,108,102, 46, 97, + 114,103,115, 91,105, 93, 32,100,111, 10, 32, 32, 32,115,101, + 108,102, 46, 97,114,103,115, 91,105, 93, 58,112, 97,115,115, + 112, 97,114, 40, 41, 10, 32, 32, 32,105, 32, 61, 32,105, 43, + 49, 10, 32, 32, 32,105,102, 32,115,101,108,102, 46, 97,114, + 103,115, 91,105, 93, 32,116,104,101,110, 10, 32, 32, 32, 32, + 111,117,116,112,117,116, 40, 39, 44, 39, 41, 10, 32, 32, 32, + 101,110,100, 10, 32, 32,101,110,100, 10, 10, 32, 32,105,102, + 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,101,108,102, + 46,110, 97,109,101, 32, 61, 61, 32, 39,111,112,101,114, 97, + 116,111,114, 91, 93, 39, 32, 97,110,100, 32,102,108, 97,103, + 115, 91, 39, 49, 39, 93, 32,116,104,101,110, 10, 9,111,117, + 116,112,117,116, 40, 39, 45, 49, 41, 59, 39, 41, 10, 32, 32, + 101,108,115,101, 10, 9,105,102, 32, 99,108, 97,115,115, 32, + 97,110,100, 32,115,101,108,102, 46,110, 97,109,101, 61, 61, + 39,110,101,119, 39, 32,116,104,101,110, 10, 9, 9,111,117, + 116,112,117,116, 40, 39, 41, 41, 59, 39, 41, 32, 45, 45, 32, + 99,108,111,115,101, 32, 77,116,111,108,117, 97, 95,110,101, + 119, 40, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,112, + 117,116, 40, 39, 41, 59, 39, 41, 10, 9,101,110,100, 10, 32, + 32,101,110,100, 10, 10, 32, 32, 45, 45, 32,114,101,116,117, + 114,110, 32,118, 97,108,117,101,115, 10, 32, 32,105,102, 32, + 115,101,108,102, 46,116,121,112,101, 32,126, 61, 32, 39, 39, + 32, 97,110,100, 32,115,101,108,102, 46,116,121,112,101, 32, + 126, 61, 32, 39,118,111,105,100, 39, 32,116,104,101,110, 10, + 32, 32, 32,110,114,101,116, 32, 61, 32,110,114,101,116, 32, + 43, 32, 49, 10, 32, 32, 32,108,111, 99, 97,108, 32,116, 44, + 99,116, 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101, + 108,102, 46,116,121,112,101, 41, 10, 32, 32, 32,105,102, 32, + 116, 32,116,104,101,110, 10, 32, 32, 32, 9,105,102, 32,115, + 101,108,102, 46, 99, 97,115,116, 95,111,112,101,114, 97,116, + 111,114, 32, 97,110,100, 32, 95, 98, 97,115,105, 99, 95,114, + 97,119, 95,112,117,115,104, 91,116, 93, 32,116,104,101,110, + 10, 9, 9,111,117,116,112,117,116, 40, 39, 32, 32, 32, 39, + 44, 95, 98, 97,115,105, 99, 95,114, 97,119, 95,112,117,115, + 104, 91,116, 93, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, + 40, 39, 44, 99,116, 44, 39, 41,116,111,108,117, 97, 95,114, + 101,116, 41, 59, 39, 41, 10, 32, 32, 32, 9,101,108,115,101, + 10, 9, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32, 32,116,111,108,117, 97, 95,112,117,115,104, 39, 46, 46, + 116, 46, 46, 39, 40,116,111,108,117, 97, 95, 83, 44, 40, 39, + 44, 99,116, 44, 39, 41,116,111,108,117, 97, 95,114,101,116, + 41, 59, 39, 41, 10, 9,101,110,100, 10, 32, 32, 32,101,108, + 115,101, 10, 9,116, 32, 61, 32,115,101,108,102, 46,116,121, + 112,101, 10, 9,110,101,119, 95,116, 32, 61, 32,115,116,114, + 105,110,103, 46,103,115,117, 98, 40,116, 44, 32, 34, 99,111, + 110,115,116, 37,115, 43, 34, 44, 32, 34, 34, 41, 10, 9,108, + 111, 99, 97,108, 32,111,119,110,101,100, 32, 61, 32,102, 97, + 108,115,101, 10, 9,105,102, 32,115,116,114,105,110,103, 46, + 102,105,110,100, 40,115,101,108,102, 46,109,111,100, 44, 32, + 34,116,111,108,117, 97, 95,111,119,110,101,100, 34, 41, 32, + 116,104,101,110, 10, 9, 9,111,119,110,101,100, 32, 61, 32, + 116,114,117,101, 10, 9,101,110,100, 10, 32, 32, 32, 32,108, + 111, 99, 97,108, 32,112,117,115,104, 95,102,117,110, 99, 32, + 61, 32,103,101,116, 95,112,117,115,104, 95,102,117,110, 99, + 116,105,111,110, 40,116, 41, 10, 32, 32, 32, 32,105,102, 32, + 115,101,108,102, 46,112,116,114, 32, 61, 61, 32, 39, 39, 32, + 116,104,101,110, 10, 32, 32, 32, 32, 32,111,117,116,112,117, + 116, 40, 39, 32, 32, 32,123, 39, 41, 10, 32, 32, 32, 32, 32, + 111,117,116,112,117,116, 40, 39, 35,105,102,100,101,102, 32, + 95, 95, 99,112,108,117,115,112,108,117,115, 92,110, 39, 41, + 10, 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32, 32, 32,118,111,105,100, 42, 32,116,111,108,117, 97, 95, + 111, 98,106, 32, 61, 32, 77,116,111,108,117, 97, 95,110,101, + 119, 40, 40, 39, 44,110,101,119, 95,116, 44, 39, 41, 40,116, + 111,108,117, 97, 95,114,101,116, 41, 41, 59, 39, 41, 10, 32, + 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, 32, + 32, 39, 44,112,117,115,104, 95,102,117,110, 99, 44, 39, 40, + 116,111,108,117, 97, 95, 83, 44,116,111,108,117, 97, 95,111, + 98,106, 44, 34, 39, 44,116, 44, 39, 34, 41, 59, 39, 41, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, + 32, 32,116,111,108,117, 97, 95,114,101,103,105,115,116,101, + 114, 95,103, 99, 40,116,111,108,117, 97, 95, 83, 44,108,117, + 97, 95,103,101,116,116,111,112, 40,116,111,108,117, 97, 95, + 83, 41, 41, 59, 39, 41, 10, 32, 32, 32, 32, 32,111,117,116, + 112,117,116, 40, 39, 35,101,108,115,101, 92,110, 39, 41, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, + 32, 32,118,111,105,100, 42, 32,116,111,108,117, 97, 95,111, + 98,106, 32, 61, 32,116,111,108,117, 97, 95, 99,111,112,121, + 40,116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, + 41, 38,116,111,108,117, 97, 95,114,101,116, 44,115,105,122, + 101,111,102, 40, 39, 44,116, 44, 39, 41, 41, 59, 39, 41, 10, + 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32, + 32, 32, 39, 44,112,117,115,104, 95,102,117,110, 99, 44, 39, + 40,116,111,108,117, 97, 95, 83, 44,116,111,108,117, 97, 95, + 111, 98,106, 44, 34, 39, 44,116, 44, 39, 34, 41, 59, 39, 41, + 10, 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, 32, + 32, 32, 32,116,111,108,117, 97, 95,114,101,103,105,115,116, + 101,114, 95,103, 99, 40,116,111,108,117, 97, 95, 83, 44,108, + 117, 97, 95,103,101,116,116,111,112, 40,116,111,108,117, 97, + 95, 83, 41, 41, 59, 39, 41, 10, 32, 32, 32, 32, 32,111,117, + 116,112,117,116, 40, 39, 35,101,110,100,105,102, 92,110, 39, + 41, 10, 32, 32, 32, 32, 32,111,117,116,112,117,116, 40, 39, + 32, 32, 32,125, 39, 41, 10, 32, 32, 32, 32,101,108,115,101, + 105,102, 32,115,101,108,102, 46,112,116,114, 32, 61, 61, 32, + 39, 38, 39, 32,116,104,101,110, 10, 32, 32, 32, 32, 32,111, + 117,116,112,117,116, 40, 39, 32, 32, 32, 39, 44,112,117,115, + 104, 95,102,117,110, 99, 44, 39, 40,116,111,108,117, 97, 95, + 83, 44, 40,118,111,105,100, 42, 41, 38,116,111,108,117, 97, + 95,114,101,116, 44, 34, 39, 44,116, 44, 39, 34, 41, 59, 39, + 41, 10, 32, 32, 32, 32,101,108,115,101, 10, 9, 32,111,117, + 116,112,117,116, 40, 39, 32, 32, 32, 39, 44,112,117,115,104, + 95,102,117,110, 99, 44, 39, 40,116,111,108,117, 97, 95, 83, + 44, 40,118,111,105,100, 42, 41,116,111,108,117, 97, 95,114, + 101,116, 44, 34, 39, 44,116, 44, 39, 34, 41, 59, 39, 41, 10, + 9, 32,105,102, 32,111,119,110,101,100, 32,111,114, 32,108, + 111, 99, 97,108, 95, 99,111,110,115,116,114,117, 99,116,111, + 114, 32,116,104,101,110, 10, 32, 32, 32, 32, 32, 32,111,117, + 116,112,117,116, 40, 39, 32, 32, 32, 32,116,111,108,117, 97, + 95,114,101,103,105,115,116,101,114, 95,103, 99, 40,116,111, + 108,117, 97, 95, 83, 44,108,117, 97, 95,103,101,116,116,111, + 112, 40,116,111,108,117, 97, 95, 83, 41, 41, 59, 39, 41, 10, + 9, 32,101,110,100, 10, 32, 32, 32, 32,101,110,100, 10, 32, + 32, 32,101,110,100, 10, 32, 32,101,110,100, 10, 32, 32,108, + 111, 99, 97,108, 32,105, 61, 49, 10, 32, 32,119,104,105,108, + 101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32, + 100,111, 10, 32, 32, 32,110,114,101,116, 32, 61, 32,110,114, + 101,116, 32, 43, 32,115,101,108,102, 46, 97,114,103,115, 91, + 105, 93, 58,114,101,116,118, 97,108,117,101, 40, 41, 10, 32, + 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32, 32,101,110,100, + 10, 32, 32,111,117,116,112,117,116, 40, 39, 32, 32,125, 39, + 41, 10, 10, 32, 32, 45, 45, 32,115,101,116, 32, 97,114,114, + 97,121, 32,101,108,101,109,101,110,116, 32,118, 97,108,117, + 101,115, 10, 32, 32,105,102, 32, 99,108, 97,115,115, 32,116, + 104,101,110, 32,110, 97,114,103, 61, 50, 32,101,108,115,101, + 32,110, 97,114,103, 61, 49, 32,101,110,100, 10, 32, 32,105, + 102, 32,115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46, + 116,121,112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32, + 116,104,101,110, 10, 32, 32, 32,108,111, 99, 97,108, 32,105, + 61, 49, 10, 32, 32, 32,119,104,105,108,101, 32,115,101,108, + 102, 46, 97,114,103,115, 91,105, 93, 32,100,111, 10, 32, 32, + 32, 32,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 58, + 115,101,116, 97,114,114, 97,121, 40,110, 97,114,103, 41, 10, + 32, 32, 32, 32,110, 97,114,103, 32, 61, 32,110, 97,114,103, + 43, 49, 10, 32, 32, 32, 32,105, 32, 61, 32,105, 43, 49, 10, + 32, 32, 32,101,110,100, 10, 32, 32,101,110,100, 10, 10, 32, + 32, 45, 45, 32,102,114,101,101, 32,100,121,110, 97,109,105, + 99, 97,108,108,121, 32, 97,108,108,111, 99, 97,116,101,100, + 32, 97,114,114, 97,121, 10, 32, 32,105,102, 32,115,101,108, + 102, 46, 97,114,103,115, 91, 49, 93, 46,116,121,112,101, 32, + 126, 61, 32, 39,118,111,105,100, 39, 32,116,104,101,110, 10, + 32, 32, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32, 32, + 32,119,104,105,108,101, 32,115,101,108,102, 46, 97,114,103, + 115, 91,105, 93, 32,100,111, 10, 32, 32, 32, 32,115,101,108, + 102, 46, 97,114,103,115, 91,105, 93, 58,102,114,101,101, 97, + 114,114, 97,121, 40, 41, 10, 32, 32, 32, 32,105, 32, 61, 32, + 105, 43, 49, 10, 32, 32, 32,101,110,100, 10, 32, 32,101,110, + 100, 10, 32,101,110,100, 10, 10, 32,111,117,116,112,117,116, + 40, 39, 32,125, 39, 41, 10, 32,111,117,116,112,117,116, 40, + 39, 32,114,101,116,117,114,110, 32, 39, 46, 46,110,114,101, + 116, 46, 46, 39, 59, 39, 41, 10, 10, 32, 45, 45, 32, 99, 97, + 108,108, 32,111,118,101,114,108,111, 97,100,101,100, 32,102, + 117,110, 99,116,105,111,110, 32,111,114, 32,103,101,110,101, + 114, 97,116,101, 32,101,114,114,111,114, 10, 9,105,102, 32, + 111,118,101,114,108,111, 97,100, 32, 60, 32, 48, 32,116,104, + 101,110, 10, 10, 9, 9,111,117,116,112,117,116, 40, 39, 35, + 105,102,110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 82, 69, + 76, 69, 65, 83, 69, 92,110, 39, 41, 10, 9, 9,111,117,116, + 112,117,116, 40, 39,116,111,108,117, 97, 95,108,101,114,114, + 111,114, 58, 92,110, 39, 41, 10, 9, 9,111,117,116,112,117, + 116, 40, 39, 32,116,111,108,117, 97, 95,101,114,114,111,114, + 40,116,111,108,117, 97, 95, 83, 44, 34, 35,102,101,114,114, + 111,114, 32,105,110, 32,102,117,110, 99,116,105,111,110, 32, + 92, 39, 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, + 46, 46, 39, 92, 39, 46, 34, 44, 38,116,111,108,117, 97, 95, + 101,114,114, 41, 59, 39, 41, 10, 9, 9,111,117,116,112,117, + 116, 40, 39, 32,114,101,116,117,114,110, 32, 48, 59, 39, 41, + 10, 9, 9,111,117,116,112,117,116, 40, 39, 35,101,110,100, + 105,102, 92,110, 39, 41, 10, 9,101,108,115,101, 10, 9, 9, + 108,111, 99, 97,108, 32, 95,108,111, 99, 97,108, 32, 61, 32, + 34, 34, 10, 9, 9,105,102, 32,108,111, 99, 97,108, 95, 99, + 111,110,115,116,114,117, 99,116,111,114, 32,116,104,101,110, + 10, 9, 9, 9, 95,108,111, 99, 97,108, 32, 61, 32, 34, 95, + 108,111, 99, 97,108, 34, 10, 9, 9,101,110,100, 10, 9, 9, + 111,117,116,112,117,116, 40, 39,116,111,108,117, 97, 95,108, + 101,114,114,111,114, 58, 92,110, 39, 41, 10, 9, 9,111,117, + 116,112,117,116, 40, 39, 32,114,101,116,117,114,110, 32, 39, + 46, 46,115,116,114,115,117, 98, 40,115,101,108,102, 46, 99, + 110, 97,109,101, 44, 49, 44, 45, 51, 41, 46, 46,102,111,114, + 109, 97,116, 40, 34, 37, 48, 50,100, 34, 44,111,118,101,114, + 108,111, 97,100, 41, 46, 46, 95,108,111, 99, 97,108, 46, 46, + 39, 40,116,111,108,117, 97, 95, 83, 41, 59, 39, 41, 10, 9, + 101,110,100, 10, 32,111,117,116,112,117,116, 40, 39,125, 39, + 41, 10, 32,111,117,116,112,117,116, 40, 39, 35,101,110,100, + 105,102, 32, 47, 47, 35,105,102,110,100,101,102, 32, 84, 79, + 76, 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, 92,110, 39, 41, + 10, 32,111,117,116,112,117,116, 40, 39, 92,110, 39, 41, 10, + 10, 9, 45, 45, 32,114,101, 99,117,114,115,105,118,101, 32, + 99, 97,108,108, 32,116,111, 32,119,114,105,116,101, 32,108, + 111, 99, 97,108, 32, 99,111,110,115,116,114,117, 99,116,111, + 114, 10, 9,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, + 32,115,101,108,102, 46,110, 97,109,101, 61, 61, 39,110,101, + 119, 39, 32, 97,110,100, 32,110,111,116, 32,108,111, 99, 97, + 108, 95, 99,111,110,115,116,114,117, 99,116,111,114, 32,116, + 104,101,110, 10, 10, 9, 9,115,101,108,102, 58,115,117,112, + 99,111,100,101, 40, 49, 41, 10, 9,101,110,100, 10, 10,101, + 110,100, 10, 10, 10, 45, 45, 32,114,101,103,105,115,116,101, + 114, 32,102,117,110, 99,116,105,111,110, 10,102,117,110, 99, + 116,105,111,110, 32, 99,108, 97,115,115, 70,117,110, 99,116, + 105,111,110, 58,114,101,103,105,115,116,101,114, 32, 40,112, + 114,101, 41, 10, 10, 9,105,102, 32,110,111,116, 32,115,101, + 108,102, 58, 99,104,101, 99,107, 95,112,117, 98,108,105, 99, + 95, 97, 99, 99,101,115,115, 40, 41, 32,116,104,101,110, 10, + 9, 9,114,101,116,117,114,110, 10, 9,101,110,100, 10, 10, + 32, 9,105,102, 32,115,101,108,102, 46,110, 97,109,101, 32, + 61, 61, 32, 39,110,101,119, 39, 32, 97,110,100, 32,115,101, + 108,102, 46,112, 97,114,101,110,116, 46,102,108, 97,103,115, + 46,112,117,114,101, 95,118,105,114,116,117, 97,108, 32,116, + 104,101,110, 10, 32, 9, 9, 45, 45, 32,110,111, 32, 99,111, + 110,115,116,114,117, 99,116,111,114, 32,102,111,114, 32, 99, + 108, 97,115,115,101,115, 32,119,105,116,104, 32,112,117,114, + 101, 32,118,105,114,116,117, 97,108, 32,109,101,116,104,111, + 100,115, 10, 32, 9, 9,114,101,116,117,114,110, 10, 32, 9, + 101,110,100, 10, 10, 32,111,117,116,112,117,116, 40,112,114, + 101, 46, 46, 39,116,111,108,117, 97, 95,102,117,110, 99,116, + 105,111,110, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, + 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, + 44, 39, 46, 46,115,101,108,102, 46, 99,110, 97,109,101, 46, + 46, 39, 41, 59, 39, 41, 10, 32, 32,105,102, 32,115,101,108, + 102, 46,110, 97,109,101, 32, 61, 61, 32, 39,110,101,119, 39, + 32,116,104,101,110, 10, 9, 32, 32,111,117,116,112,117,116, + 40,112,114,101, 46, 46, 39,116,111,108,117, 97, 95,102,117, + 110, 99,116,105,111,110, 40,116,111,108,117, 97, 95, 83, 44, + 34,110,101,119, 95,108,111, 99, 97,108, 34, 44, 39, 46, 46, + 115,101,108,102, 46, 99,110, 97,109,101, 46, 46, 39, 95,108, + 111, 99, 97,108, 41, 59, 39, 41, 10, 9, 32, 32,111,117,116, + 112,117,116, 40,112,114,101, 46, 46, 39,116,111,108,117, 97, + 95,102,117,110, 99,116,105,111,110, 40,116,111,108,117, 97, + 95, 83, 44, 34, 46, 99, 97,108,108, 34, 44, 39, 46, 46,115, + 101,108,102, 46, 99,110, 97,109,101, 46, 46, 39, 95,108,111, + 99, 97,108, 41, 59, 39, 41, 10, 9, 32, 32, 45, 45,111,117, + 116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,115,101, + 116, 95, 99, 97,108,108, 95,101,118,101,110,116, 40,116,111, + 108,117, 97, 95, 83, 44, 39, 46, 46,115,101,108,102, 46, 99, + 110, 97,109,101, 46, 46, 39, 95,108,111, 99, 97,108, 44, 32, + 34, 39, 46, 46,115,101,108,102, 46,112, 97,114,101,110,116, + 46,116,121,112,101, 46, 46, 39, 34, 41, 59, 39, 41, 10, 32, + 32,101,110,100, 10,101,110,100, 10, 10, 45, 45, 32, 80,114, + 105,110,116, 32,109,101,116,104,111,100, 10,102,117,110, 99, + 116,105,111,110, 32, 99,108, 97,115,115, 70,117,110, 99,116, + 105,111,110, 58,112,114,105,110,116, 32, 40,105,100,101,110, + 116, 44, 99,108,111,115,101, 41, 10, 32,112,114,105,110,116, + 40,105,100,101,110,116, 46, 46, 34, 70,117,110, 99,116,105, + 111,110,123, 34, 41, 10, 32,112,114,105,110,116, 40,105,100, + 101,110,116, 46, 46, 34, 32,109,111,100, 32, 32, 61, 32, 39, + 34, 46, 46,115,101,108,102, 46,109,111,100, 46, 46, 34, 39, + 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110, + 116, 46, 46, 34, 32,116,121,112,101, 32, 61, 32, 39, 34, 46, + 46,115,101,108,102, 46,116,121,112,101, 46, 46, 34, 39, 44, + 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, + 46, 46, 34, 32,112,116,114, 32, 32, 61, 32, 39, 34, 46, 46, + 115,101,108,102, 46,112,116,114, 46, 46, 34, 39, 44, 34, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34, 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101, + 108,102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,108,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101, + 108,102, 46,108,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34, 32, 99,111,110,115,116, 32, 61, 32, 39, 34, 46, 46,115, + 101,108,102, 46, 99,111,110,115,116, 46, 46, 34, 39, 44, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32, 99,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46, + 115,101,108,102, 46, 99,110, 97,109,101, 46, 46, 34, 39, 44, + 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, + 46, 46, 34, 32,108,110, 97,109,101, 32, 61, 32, 39, 34, 46, + 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 34, 39, + 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110, + 116, 46, 46, 34, 32, 97,114,103,115, 32, 61, 32,123, 34, 41, + 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104, + 105,108,101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, + 93, 32,100,111, 10, 32, 32,115,101,108,102, 46, 97,114,103, + 115, 91,105, 93, 58,112,114,105,110,116, 40,105,100,101,110, + 116, 46, 46, 34, 32, 32, 34, 44, 34, 44, 34, 41, 10, 32, 32, + 105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 32,112, + 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,125, + 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, + 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101, + 110,100, 10, 10, 45, 45, 32, 99,104,101, 99,107, 32,105,102, + 32,105,116, 32,114,101,116,117,114,110,115, 32, 97,110, 32, + 111, 98,106,101, 99,116, 32, 98,121, 32,118, 97,108,117,101, + 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, + 70,117,110, 99,116,105,111,110, 58,114,101,113,117,105,114, + 101, 99,111,108,108,101, 99,116,105,111,110, 32, 40,116, 41, + 10, 9,108,111, 99, 97,108, 32,114, 32, 61, 32,102, 97,108, + 115,101, 10, 9,105,102, 32,115,101,108,102, 46,116,121,112, + 101, 32,126, 61, 32, 39, 39, 32, 97,110,100, 32,110,111,116, + 32,105,115, 98, 97,115,105, 99, 40,115,101,108,102, 46,116, + 121,112,101, 41, 32, 97,110,100, 32,115,101,108,102, 46,112, + 116,114, 61, 61, 39, 39, 32,116,104,101,110, 10, 9, 9,108, + 111, 99, 97,108, 32,116,121,112,101, 32, 61, 32,103,115,117, + 98, 40,115,101,108,102, 46,116,121,112,101, 44, 34, 37,115, + 42, 99,111,110,115,116, 37,115, 43, 34, 44, 34, 34, 41, 10, + 9, 32,116, 91,116,121,112,101, 93, 32, 61, 32, 34,116,111, + 108,117, 97, 95, 99,111,108,108,101, 99,116, 95, 34, 32, 46, + 46, 32, 99,108,101, 97,110, 95,116,101,109,112,108, 97,116, + 101, 40,116,121,112,101, 41, 10, 9, 32,114, 32, 61, 32,116, + 114,117,101, 10, 9,101,110,100, 10, 9,108,111, 99, 97,108, + 32,105, 61, 49, 10, 9,119,104,105,108,101, 32,115,101,108, + 102, 46, 97,114,103,115, 91,105, 93, 32,100,111, 10, 9, 9, + 114, 32, 61, 32,115,101,108,102, 46, 97,114,103,115, 91,105, + 93, 58,114,101,113,117,105,114,101, 99,111,108,108,101, 99, + 116,105,111,110, 40,116, 41, 32,111,114, 32,114, 10, 9, 9, + 105, 32, 61, 32,105, 43, 49, 10, 9,101,110,100, 10, 9,114, + 101,116,117,114,110, 32,114, 10,101,110,100, 10, 10, 45, 45, + 32,100,101,116,101,114,109,105,110,101, 32,108,117, 97, 32, + 102,117,110, 99,116,105,111,110, 32,110, 97,109,101, 32,111, + 118,101,114,108,111, 97,100, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, + 58,111,118,101,114,108,111, 97,100, 32, 40, 41, 10, 32,114, + 101,116,117,114,110, 32,115,101,108,102, 46,112, 97,114,101, + 110,116, 58,111,118,101,114,108,111, 97,100, 40,115,101,108, + 102, 46,108,110, 97,109,101, 41, 10,101,110,100, 10, 10, 10, + 102,117,110, 99,116,105,111,110, 32,112, 97,114, 97,109, 95, + 111, 98,106,101, 99,116, 40,112, 97,114, 41, 32, 45, 45, 32, + 114,101,116,117,114,110,115, 32,116,114,117,101, 32,105,102, + 32,116,104,101, 32,112, 97,114, 97,109,101,116,101,114, 32, + 104, 97,115, 32, 97,110, 32,111, 98,106,101, 99,116, 32, 97, + 115, 32,105,116,115, 32,100,101,102, 97,117,108,116, 32,118, + 97,108,117,101, 10, 10, 9,105,102, 32,110,111,116, 32,115, + 116,114,105,110,103, 46,102,105,110,100, 40,112, 97,114, 44, + 32, 39, 61, 39, 41, 32,116,104,101,110, 32,114,101,116,117, + 114,110, 32,102, 97,108,115,101, 32,101,110,100, 32, 45, 45, + 32,105,116, 32,104, 97,115, 32,110,111, 32,100,101,102, 97, + 117,108,116, 32,118, 97,108,117,101, 10, 10, 9,108,111, 99, + 97,108, 32, 95, 44, 95, 44,100,101,102, 32, 61, 32,115,116, + 114,105,110,103, 46,102,105,110,100, 40,112, 97,114, 44, 32, + 34, 61, 40, 46, 42, 41, 36, 34, 41, 10, 10, 9,105,102, 32, + 115,116,114,105,110,103, 46,102,105,110,100, 40,112, 97,114, + 44, 32, 34,124, 34, 41, 32,116,104,101,110, 32, 45, 45, 32, + 97, 32,108,105,115,116, 32,111,102, 32,102,108, 97,103,115, + 10, 10, 9, 9,114,101,116,117,114,110, 32,116,114,117,101, + 10, 9,101,110,100, 10, 10, 9,105,102, 32,115,116,114,105, + 110,103, 46,102,105,110,100, 40,112, 97,114, 44, 32, 34, 37, + 42, 34, 41, 32,116,104,101,110, 32, 45, 45, 32,105,116, 39, + 115, 32, 97, 32,112,111,105,110,116,101,114, 32,119,105,116, + 104, 32, 97, 32,100,101,102, 97,117,108,116, 32,118, 97,108, + 117,101, 10, 10, 9, 9,105,102, 32,115,116,114,105,110,103, + 46,102,105,110,100, 40,112, 97,114, 44, 32, 39, 61, 37,115, + 42,110,101,119, 39, 41, 32,111,114, 32,115,116,114,105,110, + 103, 46,102,105,110,100, 40,112, 97,114, 44, 32, 34, 37, 40, + 34, 41, 32,116,104,101,110, 32, 45, 45, 32,105,116, 39,115, + 32, 97, 32,112,111,105,110,116,101,114, 32,119,105,116,104, + 32, 97,110, 32,105,110,115,116, 97,110, 99,101, 32, 97,115, + 32,100,101,102, 97,117,108,116, 32,112, 97,114, 97,109,101, + 116,101,114, 46, 46, 32,105,115, 32,116,104, 97,116, 32,118, + 97,108,105,100, 63, 10, 9, 9, 9,114,101,116,117,114,110, + 32,116,114,117,101, 10, 9, 9,101,110,100, 10, 9, 9,114, + 101,116,117,114,110, 32,102, 97,108,115,101, 32, 45, 45, 32, + 100,101,102, 97,117,108,116, 32,118, 97,108,117,101, 32,105, + 115, 32, 39, 78, 85, 76, 76, 39, 32,111,114, 32,115,111,109, + 101,116,104,105,110,103, 10, 9,101,110,100, 10, 10, 10, 9, + 105,102, 32,115,116,114,105,110,103, 46,102,105,110,100, 40, + 112, 97,114, 44, 32, 34, 91, 37, 40, 38, 93, 34, 41, 32,116, + 104,101,110, 10, 9, 9,114,101,116,117,114,110, 32,116,114, + 117,101, 10, 9,101,110,100, 32, 45, 45, 32,100,101,102, 97, + 117,108,116, 32,118, 97,108,117,101, 32,105,115, 32, 97, 32, + 99,111,110,115,116,114,117, 99,116,111,114, 32, 99, 97,108, + 108, 32, 40,109,111,115,116, 32,108,105,107,101,108,121, 32, + 102,111,114, 32, 97, 32, 99,111,110,115,116, 32,114,101,102, + 101,114,101,110, 99,101, 41, 10, 10, 9, 45, 45,105,102, 32, + 115,116,114,105,110,103, 46,102,105,110,100, 40,112, 97,114, + 44, 32, 34, 38, 34, 41, 32,116,104,101,110, 10, 10, 9, 45, + 45, 9,105,102, 32,115,116,114,105,110,103, 46,102,105,110, + 100, 40,100,101,102, 44, 32, 34, 58, 34, 41, 32,111,114, 32, + 115,116,114,105,110,103, 46,102,105,110,100, 40,100,101,102, + 44, 32, 34, 94, 37,115, 42,110,101,119, 37,115, 43, 34, 41, + 32,116,104,101,110, 10, 10, 9, 45, 45, 9, 9, 45, 45, 32, + 105,116, 39,115, 32, 97, 32,114,101,102,101,114,101,110, 99, + 101, 32,119,105,116,104, 32,100,101,102, 97,117,108,116, 32, + 116,111, 32,115,111,109,101,116,104,105,110,103, 32,108,105, + 107,101, 32, 67,108, 97,115,115, 58, 58,109,101,109, 98,101, + 114, 44, 32,111,114, 32, 39,110,101,119, 32, 67,108, 97,115, + 115, 39, 10, 9, 45, 45, 9, 9,114,101,116,117,114,110, 32, + 116,114,117,101, 10, 9, 45, 45, 9,101,110,100, 10, 9, 45, + 45,101,110,100, 10, 10, 9,114,101,116,117,114,110, 32,102, + 97,108,115,101, 32, 45, 45, 32, 63, 10,101,110,100, 10, 10, + 102,117,110, 99,116,105,111,110, 32,115,116,114,105,112, 95, + 108, 97,115,116, 95, 97,114,103, 40, 97,108,108, 95, 97,114, + 103,115, 44, 32,108, 97,115,116, 95, 97,114,103, 41, 32, 45, + 45, 32,115,116,114,105,112,115, 32,116,104,101, 32,100,101, + 102, 97,117,108,116, 32,118, 97,108,117,101, 32,102,114,111, + 109, 32,116,104,101, 32,108, 97,115,116, 32, 97,114,103,117, + 109,101,110,116, 10, 10, 9,108,111, 99, 97,108, 32, 95, 44, + 95, 44,115, 95, 97,114,103, 32, 61, 32,115,116,114,105,110, + 103, 46,102,105,110,100, 40,108, 97,115,116, 95, 97,114,103, + 44, 32, 34, 94, 40, 91, 94, 61, 93, 43, 41, 34, 41, 10, 9, + 108, 97,115,116, 95, 97,114,103, 32, 61, 32,115,116,114,105, + 110,103, 46,103,115,117, 98, 40,108, 97,115,116, 95, 97,114, + 103, 44, 32, 34, 40, 91, 37, 37, 37, 40, 37, 41, 93, 41, 34, + 44, 32, 34, 37, 37, 37, 49, 34, 41, 59, 10, 9, 97,108,108, + 95, 97,114,103,115, 32, 61, 32,115,116,114,105,110,103, 46, + 103,115,117, 98, 40, 97,108,108, 95, 97,114,103,115, 44, 32, + 34, 37,115, 42, 44, 37,115, 42, 34, 46, 46,108, 97,115,116, + 95, 97,114,103, 46, 46, 34, 37,115, 42, 37, 41, 37,115, 42, + 36, 34, 44, 32, 34, 41, 34, 41, 10, 9,114,101,116,117,114, + 110, 32, 97,108,108, 95, 97,114,103,115, 44, 32,115, 95, 97, + 114,103, 10,101,110,100, 10, 10, 10, 10, 45, 45, 32, 73,110, + 116,101,114,110, 97,108, 32, 99,111,110,115,116,114,117, 99, + 116,111,114, 10,102,117,110, 99,116,105,111,110, 32, 95, 70, + 117,110, 99,116,105,111,110, 32, 40,116, 41, 10, 32,115,101, + 116,109,101,116, 97,116, 97, 98,108,101, 40,116, 44, 99,108, + 97,115,115, 70,117,110, 99,116,105,111,110, 41, 10, 10, 32, + 105,102, 32,116, 46, 99,111,110,115,116, 32,126, 61, 32, 39, + 99,111,110,115,116, 39, 32, 97,110,100, 32,116, 46, 99,111, + 110,115,116, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 10, + 32, 32,101,114,114,111,114, 40, 34, 35,105,110,118, 97,108, + 105,100, 32, 39, 99,111,110,115,116, 39, 32,115,112,101, 99, + 105,102,105, 99, 97,116,105,111,110, 34, 41, 10, 32,101,110, + 100, 10, 10, 32, 97,112,112,101,110,100, 40,116, 41, 10, 32, + 105,102, 32,116, 58,105,110, 99,108, 97,115,115, 40, 41, 32, + 116,104,101,110, 10, 32, 45, 45,112,114,105,110,116, 32, 40, + 39,116, 46,110, 97,109,101, 32,105,115, 32, 39, 46, 46,116, + 46,110, 97,109,101, 46, 46, 39, 44, 32,112, 97,114,101,110, + 116, 46,110, 97,109,101, 32,105,115, 32, 39, 46, 46,116, 46, + 112, 97,114,101,110,116, 46,110, 97,109,101, 41, 10, 32, 32, + 105,102, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40, + 116, 46,110, 97,109,101, 44, 32, 34, 37, 98, 60, 62, 34, 44, + 32, 34, 34, 41, 32, 61, 61, 32,115,116,114,105,110,103, 46, + 103,115,117, 98, 40,116, 46,112, 97,114,101,110,116, 46,111, + 114,105,103,105,110, 97,108, 95,110, 97,109,101, 32,111,114, + 32,116, 46,112, 97,114,101,110,116, 46,110, 97,109,101, 44, + 32, 34, 37, 98, 60, 62, 34, 44, 32, 34, 34, 41, 32,116,104, + 101,110, 10, 32, 32, 32,116, 46,110, 97,109,101, 32, 61, 32, + 39,110,101,119, 39, 10, 32, 32, 32,116, 46,108,110, 97,109, + 101, 32, 61, 32, 39,110,101,119, 39, 10, 32, 32, 32,116, 46, + 112, 97,114,101,110,116, 46, 95,110,101,119, 32, 61, 32,116, + 114,117,101, 10, 32, 32, 32,116, 46,116,121,112,101, 32, 61, + 32,116, 46,112, 97,114,101,110,116, 46,110, 97,109,101, 10, + 32, 32, 32,116, 46,112,116,114, 32, 61, 32, 39, 42, 39, 10, + 32, 32,101,108,115,101,105,102, 32,115,116,114,105,110,103, + 46,103,115,117, 98, 40,116, 46,110, 97,109,101, 44, 32, 34, + 37, 98, 60, 62, 34, 44, 32, 34, 34, 41, 32, 61, 61, 32, 39, + 126, 39, 46, 46,115,116,114,105,110,103, 46,103,115,117, 98, + 40,116, 46,112, 97,114,101,110,116, 46,111,114,105,103,105, + 110, 97,108, 95,110, 97,109,101, 32,111,114, 32,116, 46,112, + 97,114,101,110,116, 46,110, 97,109,101, 44, 32, 34, 37, 98, + 60, 62, 34, 44, 32, 34, 34, 41, 32,116,104,101,110, 10, 32, + 32, 32,116, 46,110, 97,109,101, 32, 61, 32, 39,100,101,108, + 101,116,101, 39, 10, 32, 32, 32,116, 46,108,110, 97,109,101, + 32, 61, 32, 39,100,101,108,101,116,101, 39, 10, 32, 32, 32, + 116, 46,112, 97,114,101,110,116, 46, 95,100,101,108,101,116, + 101, 32, 61, 32,116,114,117,101, 10, 32, 32,101,110,100, 10, + 32,101,110,100, 10, 32,116, 46, 99,110, 97,109,101, 32, 61, + 32,116, 58, 99,102,117,110, 99,110, 97,109,101, 40, 34,116, + 111,108,117, 97, 34, 41, 46, 46,116, 58,111,118,101,114,108, + 111, 97,100, 40,116, 41, 10, 32,114,101,116,117,114,110, 32, + 116, 10,101,110,100, 10, 10, 45, 45, 32, 67,111,110,115,116, + 114,117, 99,116,111,114, 10, 45, 45, 32, 69,120,112,101, 99, + 116,115, 32,116,104,114,101,101, 32,115,116,114,105,110,103, + 115, 58, 32,111,110,101, 32,114,101,112,114,101,115,101,110, + 116,105,110,103, 32,116,104,101, 32,102,117,110, 99,116,105, + 111,110, 32,100,101, 99,108, 97,114, 97,116,105,111,110, 44, + 10, 45, 45, 32, 97,110,111,116,104,101,114, 32,114,101,112, + 114,101,115,101,110,116,105,110,103, 32,116,104,101, 32, 97, + 114,103,117,109,101,110,116, 32,108,105,115,116, 44, 32, 97, + 110,100, 32,116,104,101, 32,116,104,105,114,100, 32,114,101, + 112,114,101,115,101,110,116,105,110,103, 10, 45, 45, 32,116, + 104,101, 32, 34, 99,111,110,115,116, 34, 32,111,114, 32,101, + 109,112,116,121, 32,115,116,114,105,110,103, 46, 10,102,117, + 110, 99,116,105,111,110, 32, 70,117,110, 99,116,105,111,110, + 32, 40,100, 44, 97, 44, 99, 41, 10, 32, 45, 45,108,111, 99, + 97,108, 32,116, 32, 61, 32,115,112,108,105,116, 40,115,116, + 114,115,117, 98, 40, 97, 44, 50, 44, 45, 50, 41, 44, 39, 44, + 39, 41, 32, 45, 45, 32,101,108,105,109,105,110, 97,116,101, + 32, 98,114, 97, 99,101,115, 10, 32, 45, 45,108,111, 99, 97, + 108, 32,116, 32, 61, 32,115,112,108,105,116, 95,112, 97,114, + 97,109,115, 40,115,116,114,115,117, 98, 40, 97, 44, 50, 44, + 45, 50, 41, 41, 10, 10, 9,105,102, 32,110,111,116, 32,102, + 108, 97,103,115, 91, 39, 87, 39, 93, 32, 97,110,100, 32,115, + 116,114,105,110,103, 46,102,105,110,100, 40, 97, 44, 32, 34, + 37, 46, 37, 46, 37, 46, 37,115, 42, 37, 41, 34, 41, 32,116, + 104,101,110, 10, 10, 9, 9,119, 97,114,110,105,110,103, 40, + 34, 70,117,110, 99,116,105,111,110,115, 32,119,105,116,104, + 32,118, 97,114,105, 97, 98,108,101, 32, 97,114,103,117,109, + 101,110,116,115, 32, 40, 96, 46, 46, 46, 39, 41, 32, 97,114, + 101, 32,110,111,116, 32,115,117,112,112,111,114,116,101,100, + 46, 32, 73,103,110,111,114,105,110,103, 32, 34, 46, 46,100, + 46, 46, 97, 46, 46, 99, 41, 10, 9, 9,114,101,116,117,114, + 110, 32,110,105,108, 10, 9,101,110,100, 10, 10, 10, 32,108, + 111, 99, 97,108, 32,105, 61, 49, 10, 32,108,111, 99, 97,108, + 32,108, 32, 61, 32,123,110, 61, 48,125, 10, 10, 32, 9, 97, + 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40, + 97, 44, 32, 34, 37,115, 42, 40, 91, 37, 40, 37, 41, 93, 41, + 37,115, 42, 34, 44, 32, 34, 37, 49, 34, 41, 10, 9,108,111, + 99, 97,108, 32,116, 44,115,116,114,105,112, 44,108, 97,115, + 116, 32, 61, 32,115,116,114,105,112, 95,112, 97,114,115, 40, + 115,116,114,115,117, 98, 40, 97, 44, 50, 44, 45, 50, 41, 41, + 59, 10, 9,105,102, 32,115,116,114,105,112, 32,116,104,101, + 110, 10, 9, 9, 45, 45,108,111, 99, 97,108, 32,110,115, 32, + 61, 32,115,116,114,105,110,103, 46,115,117, 98, 40,115,116, + 114,115,117, 98, 40, 97, 44, 49, 44, 45, 50, 41, 44, 32, 49, + 44, 32, 45, 40,115,116,114,105,110,103, 46,108,101,110, 40, + 108, 97,115,116, 41, 43, 49, 41, 41, 10, 9, 9,108,111, 99, + 97,108, 32,110,115, 32, 61, 32,106,111,105,110, 40,116, 44, + 32, 34, 44, 34, 44, 32, 49, 44, 32,108, 97,115,116, 45, 49, + 41, 10, 10, 9, 9,110,115, 32, 61, 32, 34, 40, 34, 46, 46, + 115,116,114,105,110,103, 46,103,115,117, 98, 40,110,115, 44, + 32, 34, 37,115, 42, 44, 37,115, 42, 36, 34, 44, 32, 34, 34, + 41, 46, 46, 39, 41, 39, 10, 9, 9, 45, 45,110,115, 32, 61, + 32,115,116,114,105,112, 95,100,101,102, 97,117,108,116,115, + 40,110,115, 41, 10, 10, 9, 9, 70,117,110, 99,116,105,111, + 110, 40,100, 44, 32,110,115, 44, 32, 99, 41, 10, 9, 9,102, + 111,114, 32,105, 61, 49, 44,108, 97,115,116, 32,100,111, 10, + 9, 9, 9,116, 91,105, 93, 32, 61, 32,115,116,114,105,110, + 103, 46,103,115,117, 98, 40,116, 91,105, 93, 44, 32, 34, 61, + 46, 42, 36, 34, 44, 32, 34, 34, 41, 10, 9, 9,101,110,100, + 10, 9,101,110,100, 10, 10, 32,119,104,105,108,101, 32,116, + 91,105, 93, 32,100,111, 10, 32, 32,108, 46,110, 32, 61, 32, + 108, 46,110, 43, 49, 10, 32, 32,108, 91,108, 46,110, 93, 32, + 61, 32, 68,101, 99,108, 97,114, 97,116,105,111,110, 40,116, + 91,105, 93, 44, 39,118, 97,114, 39, 44,116,114,117,101, 41, + 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, + 10, 32,108,111, 99, 97,108, 32,102, 32, 61, 32, 68,101, 99, + 108, 97,114, 97,116,105,111,110, 40,100, 44, 39,102,117,110, + 99, 39, 41, 10, 32,102, 46, 97,114,103,115, 32, 61, 32,108, + 10, 32,102, 46, 99,111,110,115,116, 32, 61, 32, 99, 10, 32, + 114,101,116,117,114,110, 32, 95, 70,117,110, 99,116,105,111, + 110, 40,102, 41, 10,101,110,100, 10, 10,102,117,110, 99,116, + 105,111,110, 32,106,111,105,110, 40,116, 44, 32,115,101,112, + 44, 32,102,105,114,115,116, 44, 32,108, 97,115,116, 41, 10, + 10, 9,102,105,114,115,116, 32, 61, 32,102,105,114,115,116, + 32,111,114, 32, 49, 10, 9,108, 97,115,116, 32, 61, 32,108, + 97,115,116, 32,111,114, 32,116, 97, 98,108,101, 46,103,101, + 116,110, 40,116, 41, 10, 9,108,111, 99, 97,108, 32,108,115, + 101,112, 32, 61, 32, 34, 34, 10, 9,108,111, 99, 97,108, 32, + 114,101,116, 32, 61, 32, 34, 34, 10, 9,108,111, 99, 97,108, + 32,108,111,111,112, 32, 61, 32,102, 97,108,115,101, 10, 9, + 102,111,114, 32,105, 32, 61, 32,102,105,114,115,116, 44,108, + 97,115,116, 32,100,111, 10, 10, 9, 9,114,101,116, 32, 61, + 32,114,101,116, 46, 46,108,115,101,112, 46, 46,116, 91,105, + 93, 10, 9, 9,108,115,101,112, 32, 61, 32,115,101,112, 10, + 9, 9,108,111,111,112, 32, 61, 32,116,114,117,101, 10, 9, + 101,110,100, 10, 9,105,102, 32,110,111,116, 32,108,111,111, + 112, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114,110, + 32, 34, 34, 10, 9,101,110,100, 10, 10, 9,114,101,116,117, + 114,110, 32,114,101,116, 10,101,110,100, 10, 10,102,117,110, + 99,116,105,111,110, 32,115,116,114,105,112, 95,112, 97,114, + 115, 40,115, 41, 10, 10, 9,108,111, 99, 97,108, 32,116, 32, + 61, 32,115,112,108,105,116, 95, 99, 95,116,111,107,101,110, + 115, 40,115, 44, 32, 39, 44, 39, 41, 10, 9,108,111, 99, 97, + 108, 32,115,116,114,105,112, 32, 61, 32,102, 97,108,115,101, + 10, 9,108,111, 99, 97,108, 32,108, 97,115,116, 10, 10, 9, + 102,111,114, 32,105, 61,116, 46,110, 44, 49, 44, 45, 49, 32, + 100,111, 10, 10, 9, 9,105,102, 32,110,111,116, 32,115,116, + 114,105,112, 32, 97,110,100, 32,112, 97,114, 97,109, 95,111, + 98,106,101, 99,116, 40,116, 91,105, 93, 41, 32,116,104,101, + 110, 10, 9, 9, 9,108, 97,115,116, 32, 61, 32,105, 10, 9, + 9, 9,115,116,114,105,112, 32, 61, 32,116,114,117,101, 10, + 9, 9,101,110,100, 10, 9, 9, 45, 45,105,102, 32,115,116, + 114,105,112, 32,116,104,101,110, 10, 9, 9, 45, 45, 9,116, + 91,105, 93, 32, 61, 32,115,116,114,105,110,103, 46,103,115, + 117, 98, 40,116, 91,105, 93, 44, 32, 34, 61, 46, 42, 36, 34, + 44, 32, 34, 34, 41, 10, 9, 9, 45, 45,101,110,100, 10, 9, + 101,110,100, 10, 10, 9,114,101,116,117,114,110, 32,116, 44, + 115,116,114,105,112, 44,108, 97,115,116, 10, 10,101,110,100, + 10, 10,102,117,110, 99,116,105,111,110, 32,115,116,114,105, + 112, 95,100,101,102, 97,117,108,116,115, 40,115, 41, 10, 10, + 9,115, 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, + 98, 40,115, 44, 32, 34, 94, 37, 40, 34, 44, 32, 34, 34, 41, + 10, 9,115, 32, 61, 32,115,116,114,105,110,103, 46,103,115, + 117, 98, 40,115, 44, 32, 34, 37, 41, 36, 34, 44, 32, 34, 34, + 41, 10, 10, 9,108,111, 99, 97,108, 32,116, 32, 61, 32,115, + 112,108,105,116, 95, 99, 95,116,111,107,101,110,115, 40,115, + 44, 32, 34, 44, 34, 41, 10, 9,108,111, 99, 97,108, 32,115, + 101,112, 44, 32,114,101,116, 32, 61, 32, 34, 34, 44, 34, 34, + 10, 9,102,111,114, 32,105, 61, 49, 44,116, 46,110, 32,100, + 111, 10, 9, 9,116, 91,105, 93, 32, 61, 32,115,116,114,105, + 110,103, 46,103,115,117, 98, 40,116, 91,105, 93, 44, 32, 34, + 61, 46, 42, 36, 34, 44, 32, 34, 34, 41, 10, 9, 9,114,101, + 116, 32, 61, 32,114,101,116, 46, 46,115,101,112, 46, 46,116, + 91,105, 93, 10, 9, 9,115,101,112, 32, 61, 32, 34, 44, 34, + 10, 9,101,110,100, 10, 10, 9,114,101,116,117,114,110, 32, + 34, 40, 34, 46, 46,114,101,116, 46, 46, 34, 41, 34, 10,101, + 110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/function.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32,111,112,101,114, 97, + 116,111,114, 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114, + 105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, + 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, + 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, + 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73, + 100, 58, 32, 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99, + 111,100,101, 32,105,115, 32,102,114,101,101, 32,115,111,102, + 116,119, 97,114,101, 59, 32,121,111,117, 32, 99, 97,110, 32, + 114,101,100,105,115,116,114,105, 98,117,116,101, 32,105,116, + 32, 97,110,100, 47,111,114, 32,109,111,100,105,102,121, 32, + 105,116, 46, 10, 45, 45, 32, 84,104,101, 32,115,111,102,116, + 119, 97,114,101, 32,112,114,111,118,105,100,101,100, 32,104, + 101,114,101,117,110,100,101,114, 32,105,115, 32,111,110, 32, + 97,110, 32, 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105, + 115, 44, 32, 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97, + 117,116,104,111,114, 32,104, 97,115, 32,110,111, 32,111, 98, + 108,105,103, 97,116,105,111,110, 32,116,111, 32,112,114,111, + 118,105,100,101, 32,109, 97,105,110,116,101,110, 97,110, 99, + 101, 44, 32,115,117,112,112,111,114,116, 44, 32,117,112,100, + 97,116,101,115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99, + 101,109,101,110,116,115, 44, 32,111,114, 32,109,111,100,105, + 102,105, 99, 97,116,105,111,110,115, 46, 10, 10, 10, 45, 45, + 32, 79,112,101,114, 97,116,111,114, 32, 99,108, 97,115,115, + 10, 45, 45, 32, 82,101,112,114,101,115,101,110,116,115, 32, + 97,110, 32,111,112,101,114, 97,116,111,114, 32,102,117,110, + 99,116,105,111,110, 32,111,114, 32, 97, 32, 99,108, 97,115, + 115, 32,111,112,101,114, 97,116,111,114, 32,109,101,116,104, + 111,100, 46, 10, 45, 45, 32, 73,116, 32,115,116,111,114,101, + 115, 32,116,104,101, 32,115, 97,109,101, 32,102,105,101,108, + 100,115, 32, 97,115, 32,102,117,110, 99,116,105,111,110,115, + 32,100,111, 32,112,108,117,115, 58, 10, 45, 45, 32, 32,107, + 105,110,100, 32, 61, 32,115,101,116, 32,111,102, 32, 99,104, + 97,114, 97, 99,116,101,114, 32,114,101,112,114,101,115,101, + 110,116,105,110,103, 32,116,104,101, 32,111,112,101,114, 97, + 116,111,114, 32, 40, 97,115, 32,105,116, 32, 97,112,112,101, + 114,115, 32,105,110, 32, 67, 43, 43, 32, 99,111,100,101, 41, + 10, 99,108, 97,115,115, 79,112,101,114, 97,116,111,114, 32, + 61, 32,123, 10, 32,107,105,110,100, 32, 61, 32, 39, 39, 44, + 10,125, 10, 99,108, 97,115,115, 79,112,101,114, 97,116,111, + 114, 46, 95, 95,105,110,100,101,120, 32, 61, 32, 99,108, 97, + 115,115, 79,112,101,114, 97,116,111,114, 10,115,101,116,109, + 101,116, 97,116, 97, 98,108,101, 40, 99,108, 97,115,115, 79, + 112,101,114, 97,116,111,114, 44, 99,108, 97,115,115, 70,117, + 110, 99,116,105,111,110, 41, 10, 10, 45, 45, 32,116, 97, 98, + 108,101, 32,116,111, 32,116,114, 97,110,115,102,111,114,109, + 32,111,112,101,114, 97,116,111,114, 32,107,105,110,100, 32, + 105,110,116,111, 32,116,104,101, 32, 97,112,112,114,111,112, + 114,105, 97,116,101, 32,116, 97,103, 32,109,101,116,104,111, + 100, 32,110, 97,109,101, 10, 95, 84, 77, 32, 61, 32,123, 91, + 39, 43, 39, 93, 32, 61, 32, 39, 97,100,100, 39, 44, 10, 32, + 32, 32, 32, 32, 32, 32, 91, 39, 45, 39, 93, 32, 61, 32, 39, + 115,117, 98, 39, 44, 10, 32, 32, 32, 32, 32, 32, 32, 91, 39, + 42, 39, 93, 32, 61, 32, 39,109,117,108, 39, 44, 10, 32, 32, + 32, 32, 32, 32, 32, 91, 39, 47, 39, 93, 32, 61, 32, 39,100, + 105,118, 39, 44, 10, 32, 32, 32, 32, 32, 32, 32, 91, 39, 60, + 39, 93, 32, 61, 32, 39,108,116, 39, 44, 10, 32, 32, 32, 32, + 32, 32, 32, 91, 39, 60, 61, 39, 93, 32, 61, 32, 39,108,101, + 39, 44, 10, 32, 32, 32, 32, 32, 32, 32, 91, 39, 61, 61, 39, + 93, 32, 61, 32, 39,101,113, 39, 44, 10, 32, 32, 32, 32, 32, + 32, 32, 91, 39, 91, 93, 39, 93, 32, 61, 32, 39,103,101,116, + 105, 39, 44, 10, 32, 32, 32, 32, 32, 32, 32, 91, 39, 38, 91, + 93, 39, 93, 32, 61, 32, 39,115,101,116,105, 39, 44, 10, 32, + 32, 32, 32, 32, 32, 32, 45, 45, 91, 39, 45, 62, 39, 93, 32, + 61, 32, 39,102,108,101, 99,104,105,116, 97, 39, 44, 10, 32, + 32, 32, 32, 32, 32,125, 10, 10, 10, 45, 45, 32, 80,114,105, + 110,116, 32,109,101,116,104,111,100, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 79,112,101,114, 97,116, + 111,114, 58,112,114,105,110,116, 32, 40,105,100,101,110,116, + 44, 99,108,111,115,101, 41, 10, 32,112,114,105,110,116, 40, + 105,100,101,110,116, 46, 46, 34, 79,112,101,114, 97,116,111, + 114,123, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 32,107,105,110,100, 32, 32, 61, 32, 39, + 34, 46, 46,115,101,108,102, 46,107,105,110,100, 46, 46, 34, + 39, 44, 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101, + 110,116, 46, 46, 34, 32,109,111,100, 32, 32, 61, 32, 39, 34, + 46, 46,115,101,108,102, 46,109,111,100, 46, 46, 34, 39, 44, + 34, 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, + 46, 46, 34, 32,116,121,112,101, 32, 61, 32, 39, 34, 46, 46, + 115,101,108,102, 46,116,121,112,101, 46, 46, 34, 39, 44, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32,112,116,114, 32, 32, 61, 32, 39, 34, 46, 46,115, + 101,108,102, 46,112,116,114, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 99,111,110,115,116, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46, 99,111,110,115,116, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32, 99,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101, + 108,102, 46, 99,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34, 32,108,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115, + 101,108,102, 46,108,110, 97,109,101, 46, 46, 34, 39, 44, 34, + 41, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32, 97,114,103,115, 32, 61, 32,123, 34, 41, 10, 32, + 108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104,105,108, + 101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32, + 100,111, 10, 32, 32,115,101,108,102, 46, 97,114,103,115, 91, + 105, 93, 58,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34, 32, 32, 34, 44, 34, 44, 34, 41, 10, 32, 32,105, 32, + 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 32,112,114,105, + 110,116, 40,105,100,101,110,116, 46, 46, 34, 32,125, 34, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, + 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, + 115, 79,112,101,114, 97,116,111,114, 58,115,117,112, 99,111, + 100,101, 95,116,109,112, 40, 41, 10, 10, 9,105,102, 32,110, + 111,116, 32, 95, 84, 77, 91,115,101,108,102, 46,107,105,110, + 100, 93, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114, + 110, 32, 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, + 46,115,117,112, 99,111,100,101, 40,115,101,108,102, 41, 10, + 9,101,110,100, 10, 10, 9, 45, 45, 32,110,111, 32,111,118, + 101,114,108,111, 97,100, 44, 32,110,111, 32,112, 97,114, 97, + 109,101,116,101,114,115, 44, 32, 97,108,119, 97,121,115, 32, + 105,110, 99,108, 97,115,115, 10, 9,111,117,116,112,117,116, + 40, 34, 47, 42, 32,109,101,116,104,111,100, 58, 34, 44,115, + 101,108,102, 46,110, 97,109,101, 44, 34, 32,111,102, 32, 99, + 108, 97,115,115, 32, 34, 44,115,101,108,102, 58,105,110, 99, + 108, 97,115,115, 40, 41, 44, 34, 32, 42, 47, 34, 41, 10, 10, + 9,111,117,116,112,117,116, 40, 34, 35,105,102,110,100,101, + 102, 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, 66, 76, 69, + 95, 34, 46, 46,115,101,108,102, 46, 99,110, 97,109,101, 41, + 10, 9,111,117,116,112,117,116, 40, 34, 92,110,115,116, 97, + 116,105, 99, 32,105,110,116, 34, 44,115,101,108,102, 46, 99, + 110, 97,109,101, 44, 34, 40,108,117, 97, 95, 83,116, 97,116, + 101, 42, 32,116,111,108,117, 97, 95, 83, 41, 34, 41, 10, 10, + 9,105,102, 32,111,118,101,114,108,111, 97,100, 32, 60, 32, + 48, 32,116,104,101,110, 10, 9, 32,111,117,116,112,117,116, + 40, 39, 35,105,102,110,100,101,102, 32, 84, 79, 76, 85, 65, + 95, 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, 10, 9,101, + 110,100, 10, 9,111,117,116,112,117,116, 40, 39, 32,116,111, + 108,117, 97, 95, 69,114,114,111,114, 32,116,111,108,117, 97, + 95,101,114,114, 59, 39, 41, 10, 9,111,117,116,112,117,116, + 40, 39, 32,105,102, 32, 40, 92,110, 39, 41, 10, 9, 45, 45, + 32, 99,104,101, 99,107, 32,115,101,108,102, 10, 9,108,111, + 99, 97,108, 32,105,115, 95,102,117,110, 99, 32, 61, 32,103, + 101,116, 95,105,115, 95,102,117,110, 99,116,105,111,110, 40, + 115,101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112, + 101, 41, 10, 9,111,117,116,112,117,116, 40, 39, 32, 32, 32, + 32, 32, 33, 39, 46, 46,105,115, 95,102,117,110, 99, 46, 46, + 39, 40,116,111,108,117, 97, 95, 83, 44, 49, 44, 34, 39, 46, + 46,115,101,108,102, 46,112, 97,114,101,110,116, 46,116,121, + 112,101, 46, 46, 39, 34, 44, 48, 44, 38,116,111,108,117, 97, + 95,101,114,114, 41, 32,124,124, 92,110, 39, 41, 10, 9,111, + 117,116,112,117,116, 40, 39, 32, 32, 32, 32, 32, 33,116,111, + 108,117, 97, 95,105,115,110,111,111, 98,106, 40,116,111,108, + 117, 97, 95, 83, 44, 50, 44, 38,116,111,108,117, 97, 95,101, + 114,114, 41, 92,110, 32, 41, 39, 41, 10, 9,111,117,116,112, + 117,116, 40, 39, 32, 32,103,111,116,111, 32,116,111,108,117, + 97, 95,108,101,114,114,111,114, 59, 39, 41, 10, 10, 9,111, + 117,116,112,117,116, 40, 39, 32,101,108,115,101, 92,110, 39, + 41, 10, 9,111,117,116,112,117,116, 40, 39, 35,101,110,100, + 105,102, 92,110, 39, 41, 32, 45, 45, 32,116,111,108,117, 97, + 95,114,101,108,101, 97,115,101, 10, 9,111,117,116,112,117, + 116, 40, 39, 32,123, 39, 41, 10, 10, 9, 45, 45, 32,100,101, + 99,108, 97,114,101, 32,115,101,108,102, 10, 9,111,117,116, + 112,117,116, 40, 39, 32, 39, 44,115,101,108,102, 46, 99,111, + 110,115,116, 44,115,101,108,102, 46,112, 97,114,101,110,116, + 46,116,121,112,101, 44, 39, 42, 39, 44, 39,115,101,108,102, + 32, 61, 32, 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, + 40, 39, 44,115,101,108,102, 46, 99,111,110,115,116, 44,115, + 101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112,101, + 44, 39, 42, 41, 32, 39, 41, 10, 9,108,111, 99, 97,108, 32, + 116,111, 95,102,117,110, 99, 32, 61, 32,103,101,116, 95,116, + 111, 95,102,117,110, 99, 40,115,101,108,102, 46,112, 97,114, + 101,110,116, 46,116,121,112,101, 41, 10, 9,111,117,116,112, + 117,116, 40,116,111, 95,102,117,110, 99, 44, 39, 40,116,111, + 108,117, 97, 95, 83, 44, 49, 44, 48, 41, 59, 39, 41, 10, 10, + 9, 45, 45, 32, 99,104,101, 99,107, 32,115,101,108,102, 10, + 9,111,117,116,112,117,116, 40, 39, 35,105,102,110,100,101, + 102, 32, 84, 79, 76, 85, 65, 95, 82, 69, 76, 69, 65, 83, 69, + 92,110, 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, 32, + 32,105,102, 32, 40, 33,115,101,108,102, 41, 32,116,111,108, + 117, 97, 95,101,114,114,111,114, 40,116,111,108,117, 97, 95, + 83, 44, 34,105,110,118, 97,108,105,100, 32, 92, 39,115,101, + 108,102, 92, 39, 32,105,110, 32,102,117,110, 99,116,105,111, + 110, 32, 92, 39, 39, 46, 46,115,101,108,102, 46,110, 97,109, + 101, 46, 46, 39, 92, 39, 34, 44, 78, 85, 76, 76, 41, 59, 39, + 41, 59, 10, 9,111,117,116,112,117,116, 40, 39, 35,101,110, + 100,105,102, 92,110, 39, 41, 10, 10, 9, 45, 45, 32, 99, 97, + 115,116, 32,115,101,108,102, 10, 9,111,117,116,112,117,116, + 40, 39, 32, 32, 39, 44,115,101,108,102, 46,109,111,100, 44, + 115,101,108,102, 46,116,121,112,101, 44,115,101,108,102, 46, + 112,116,114, 44, 39,116,111,108,117, 97, 95,114,101,116, 32, + 61, 32, 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, 40, + 39, 44,115,101,108,102, 46,109,111,100, 44,115,101,108,102, + 46,116,121,112,101, 44,115,101,108,102, 46,112,116,114, 44, + 39, 41, 40, 42,115,101,108,102, 41, 59, 39, 41, 10, 10, 9, + 45, 45, 32,114,101,116,117,114,110, 32,118, 97,108,117,101, + 10, 9,108,111, 99, 97,108, 32,116, 44, 99,116, 32, 61, 32, + 105,115, 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121, + 112,101, 41, 10, 9,105,102, 32,116, 32,116,104,101,110, 10, + 9, 9,111,117,116,112,117,116, 40, 39, 32, 32, 32,116,111, + 108,117, 97, 95,112,117,115,104, 39, 46, 46,116, 46, 46, 39, + 40,116,111,108,117, 97, 95, 83, 44, 40, 39, 44, 99,116, 44, + 39, 41,116,111,108,117, 97, 95,114,101,116, 41, 59, 39, 41, + 10, 9,101,108,115,101, 10, 9, 9,116, 32, 61, 32,115,101, + 108,102, 46,116,121,112,101, 10, 9, 9,108,111, 99, 97,108, + 32,112,117,115,104, 95,102,117,110, 99, 32, 61, 32,103,101, + 116, 95,112,117,115,104, 95,102,117,110, 99,116,105,111,110, + 40,116, 41, 10, 9, 9,110,101,119, 95,116, 32, 61, 32,115, + 116,114,105,110,103, 46,103,115,117, 98, 40,116, 44, 32, 34, + 99,111,110,115,116, 37,115, 43, 34, 44, 32, 34, 34, 41, 10, + 9, 9,105,102, 32,115,101,108,102, 46,112,116,114, 32, 61, + 61, 32, 39, 39, 32,116,104,101,110, 10, 9, 9, 9,111,117, + 116,112,117,116, 40, 39, 32, 32, 32,123, 39, 41, 10, 9, 9, + 9,111,117,116,112,117,116, 40, 39, 35,105,102,100,101,102, + 32, 95, 95, 99,112,108,117,115,112,108,117,115, 92,110, 39, + 41, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, 32, + 32, 32,118,111,105,100, 42, 32,116,111,108,117, 97, 95,111, + 98,106, 32, 61, 32, 77,116,111,108,117, 97, 95,110,101,119, + 40, 40, 39, 44,110,101,119, 95,116, 44, 39, 41, 40,116,111, + 108,117, 97, 95,114,101,116, 41, 41, 59, 39, 41, 10, 9, 9, + 9,111,117,116,112,117,116, 40, 39, 32, 32, 32, 32, 39, 44, + 112,117,115,104, 95,102,117,110, 99, 44, 39, 40,116,111,108, + 117, 97, 95, 83, 44,116,111,108,117, 97, 95,111, 98,106, 44, + 34, 39, 44,116, 44, 39, 34, 41, 59, 39, 41, 10, 9, 9, 9, + 111,117,116,112,117,116, 40, 39, 32, 32, 32, 32,116,111,108, + 117, 97, 95,114,101,103,105,115,116,101,114, 95,103, 99, 40, + 116,111,108,117, 97, 95, 83, 44,108,117, 97, 95,103,101,116, + 116,111,112, 40,116,111,108,117, 97, 95, 83, 41, 41, 59, 39, + 41, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, 35,101, + 108,115,101, 92,110, 39, 41, 10, 9, 9, 9,111,117,116,112, + 117,116, 40, 39, 32, 32, 32, 32,118,111,105,100, 42, 32,116, + 111,108,117, 97, 95,111, 98,106, 32, 61, 32,116,111,108,117, + 97, 95, 99,111,112,121, 40,116,111,108,117, 97, 95, 83, 44, + 40,118,111,105,100, 42, 41, 38,116,111,108,117, 97, 95,114, + 101,116, 44,115,105,122,101,111,102, 40, 39, 44,116, 44, 39, + 41, 41, 59, 39, 41, 10, 9, 9, 9,111,117,116,112,117,116, + 40, 39, 32, 32, 32, 32, 39, 44,112,117,115,104, 95,102,117, + 110, 99, 44, 39, 40,116,111,108,117, 97, 95, 83, 44,116,111, + 108,117, 97, 95,111, 98,106, 44, 34, 39, 44,116, 44, 39, 34, + 41, 59, 39, 41, 10, 9, 9, 9,111,117,116,112,117,116, 40, + 39, 32, 32, 32, 32,116,111,108,117, 97, 95,114,101,103,105, + 115,116,101,114, 95,103, 99, 40,116,111,108,117, 97, 95, 83, + 44,108,117, 97, 95,103,101,116,116,111,112, 40,116,111,108, + 117, 97, 95, 83, 41, 41, 59, 39, 41, 10, 9, 9, 9,111,117, + 116,112,117,116, 40, 39, 35,101,110,100,105,102, 92,110, 39, + 41, 10, 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, 32, + 32,125, 39, 41, 10, 9, 9,101,108,115,101,105,102, 32,115, + 101,108,102, 46,112,116,114, 32, 61, 61, 32, 39, 38, 39, 32, + 116,104,101,110, 10, 9, 9, 9,111,117,116,112,117,116, 40, + 39, 32, 32, 32, 39, 44,112,117,115,104, 95,102,117,110, 99, + 44, 39, 40,116,111,108,117, 97, 95, 83, 44, 40,118,111,105, + 100, 42, 41, 38,116,111,108,117, 97, 95,114,101,116, 44, 34, + 39, 44,116, 44, 39, 34, 41, 59, 39, 41, 10, 9, 9,101,108, + 115,101, 10, 9, 9, 9,105,102, 32,108,111, 99, 97,108, 95, + 99,111,110,115,116,114,117, 99,116,111,114, 32,116,104,101, + 110, 10, 9, 9, 9, 9,111,117,116,112,117,116, 40, 39, 32, + 32, 32, 39, 44,112,117,115,104, 95,102,117,110, 99, 44, 39, + 40,116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, 32, + 42, 41,116,111,108,117, 97, 95,114,101,116, 44, 34, 39, 44, + 116, 44, 39, 34, 41, 59, 39, 41, 10, 9, 9, 9, 9,111,117, + 116,112,117,116, 40, 39, 32, 32, 32, 32,116,111,108,117, 97, + 95,114,101,103,105,115,116,101,114, 95,103, 99, 40,116,111, + 108,117, 97, 95, 83, 44,108,117, 97, 95,103,101,116,116,111, + 112, 40,116,111,108,117, 97, 95, 83, 41, 41, 59, 39, 41, 10, + 9, 9, 9,101,108,115,101, 10, 9, 9, 9, 9,111,117,116, + 112,117,116, 40, 39, 32, 32, 32, 39, 44,112,117,115,104, 95, + 102,117,110, 99, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, + 40,118,111,105,100, 42, 41,116,111,108,117, 97, 95,114,101, + 116, 44, 34, 39, 44,116, 44, 39, 34, 41, 59, 39, 41, 10, 9, + 9, 9,101,110,100, 10, 9, 9,101,110,100, 10, 9,101,110, + 100, 10, 10, 9,111,117,116,112,117,116, 40, 39, 32, 32,125, + 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, 32,114,101, + 116,117,114,110, 32, 49, 59, 39, 41, 10, 10, 9,111,117,116, + 112,117,116, 40, 39, 35,105,102,110,100,101,102, 32, 84, 79, + 76, 85, 65, 95, 82, 69, 76, 69, 65, 83, 69, 92,110, 39, 41, + 10, 9,111,117,116,112,117,116, 40, 39,116,111,108,117, 97, + 95,108,101,114,114,111,114, 58, 92,110, 39, 41, 10, 9,111, + 117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,101, + 114,114,111,114, 40,116,111,108,117, 97, 95, 83, 44, 34, 35, + 102,101,114,114,111,114, 32,105,110, 32,102,117,110, 99,116, + 105,111,110, 32, 92, 39, 39, 46, 46,115,101,108,102, 46,108, + 110, 97,109,101, 46, 46, 39, 92, 39, 46, 34, 44, 38,116,111, + 108,117, 97, 95,101,114,114, 41, 59, 39, 41, 10, 9,111,117, + 116,112,117,116, 40, 39, 32,114,101,116,117,114,110, 32, 48, + 59, 39, 41, 10, 9,111,117,116,112,117,116, 40, 39, 35,101, + 110,100,105,102, 92,110, 39, 41, 10, 10, 10, 9,111,117,116, + 112,117,116, 40, 39,125, 39, 41, 10, 9,111,117,116,112,117, + 116, 40, 39, 35,101,110,100,105,102, 32, 47, 47, 35,105,102, + 110,100,101,102, 32, 84, 79, 76, 85, 65, 95, 68, 73, 83, 65, + 66, 76, 69, 92,110, 39, 41, 10, 9,111,117,116,112,117,116, + 40, 39, 92,110, 39, 41, 10,101,110,100, 10, 10, 45, 45, 32, + 73,110,116,101,114,110, 97,108, 32, 99,111,110,115,116,114, + 117, 99,116,111,114, 10,102,117,110, 99,116,105,111,110, 32, + 95, 79,112,101,114, 97,116,111,114, 32, 40,116, 41, 10, 32, + 115,101,116,109,101,116, 97,116, 97, 98,108,101, 40,116, 44, + 99,108, 97,115,115, 79,112,101,114, 97,116,111,114, 41, 10, + 10, 32,105,102, 32,116, 46, 99,111,110,115,116, 32,126, 61, + 32, 39, 99,111,110,115,116, 39, 32, 97,110,100, 32,116, 46, + 99,111,110,115,116, 32,126, 61, 32, 39, 39, 32,116,104,101, + 110, 10, 32, 32,101,114,114,111,114, 40, 34, 35,105,110,118, + 97,108,105,100, 32, 39, 99,111,110,115,116, 39, 32,115,112, + 101, 99,105,102,105, 99, 97,116,105,111,110, 34, 41, 10, 32, + 101,110,100, 10, 10, 32, 97,112,112,101,110,100, 40,116, 41, + 10, 32,105,102, 32,110,111,116, 32,116, 58,105,110, 99,108, + 97,115,115, 40, 41, 32,116,104,101,110, 10, 32, 32,101,114, + 114,111,114, 40, 34, 35,111,112,101,114, 97,116,111,114, 32, + 99, 97,110, 32,111,110,108,121, 32, 98,101, 32,100,101,102, + 105,110,101,100, 32, 97,115, 32, 99,108, 97,115,115, 32,109, + 101,109, 98,101,114, 34, 41, 10, 32,101,110,100, 10, 10, 32, + 45, 45,116, 46,110, 97,109,101, 32, 61, 32,116, 46,110, 97, + 109,101, 32, 46, 46, 32, 34, 95, 34, 32, 46, 46, 32, 40, 95, + 84, 77, 91,116, 46,107,105,110,100, 93, 32,111,114, 32,116, + 46,107,105,110,100, 41, 10, 32,116, 46, 99,110, 97,109,101, + 32, 61, 32,116, 58, 99,102,117,110, 99,110, 97,109,101, 40, + 34,116,111,108,117, 97, 34, 41, 46, 46,116, 58,111,118,101, + 114,108,111, 97,100, 40,116, 41, 10, 32,116, 46,110, 97,109, + 101, 32, 61, 32, 34,111,112,101,114, 97,116,111,114, 34, 32, + 46, 46, 32,116, 46,107,105,110,100, 32, 32, 45, 45, 32,115, + 101,116, 32, 97,112,112,114,111,112,114,105, 97,116,101, 32, + 99, 97,108,108,105,110,103, 32,110, 97,109,101, 10, 32,114, + 101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 45, 45, + 32, 67,111,110,115,116,114,117, 99,116,111,114, 10,102,117, + 110, 99,116,105,111,110, 32, 79,112,101,114, 97,116,111,114, + 32, 40,100, 44,107, 44, 97, 44, 99, 41, 10, 10, 9,108,111, + 99, 97,108, 32,111,112, 95,107, 32, 61, 32,115,116,114,105, + 110,103, 46,103,115,117, 98, 40,107, 44, 32, 34, 94, 37,115, + 42, 34, 44, 32, 34, 34, 41, 10, 9,111,112, 95,107, 32, 61, + 32,115,116,114,105,110,103, 46,103,115,117, 98, 40,107, 44, + 32, 34, 37,115, 42, 36, 34, 44, 32, 34, 34, 41, 10, 9, 45, + 45,105,102, 32,115,116,114,105,110,103, 46,102,105,110,100, + 40,107, 44, 32, 34, 94, 91, 37,119, 95, 58, 37,100, 60, 62, + 37, 42, 37, 38, 93, 43, 36, 34, 41, 32,116,104,101,110, 10, + 9,105,102, 32,100, 32, 61, 61, 32, 34,111,112,101,114, 97, + 116,111,114, 34, 32, 97,110,100, 32,107, 32,126, 61, 32, 39, + 39, 32,116,104,101,110, 10, 10, 9, 9,100, 32, 61, 32,107, + 46, 46, 34, 32,111,112,101,114, 97,116,111,114, 34, 10, 9, + 101,108,115,101,105,102, 32,110,111,116, 32, 95, 84, 77, 91, + 111,112, 95,107, 93, 32,116,104,101,110, 10, 10, 9, 9,105, + 102, 32,102,108, 97,103,115, 91, 39, 87, 39, 93, 32,116,104, + 101,110, 10, 9, 9, 9,101,114,114,111,114, 40, 34,116,111, + 108,117, 97, 58, 32,110,111, 32,115,117,112,112,111,114,116, + 32,102,111,114, 32,111,112,101,114, 97,116,111,114, 34, 32, + 46, 46, 32,102, 46,107,105,110,100, 41, 10, 9, 9,101,108, + 115,101, 10, 9, 9, 9,119, 97,114,110,105,110,103, 40, 34, + 78,111, 32,115,117,112,112,111,114,116, 32,102,111,114, 32, + 111,112,101,114, 97,116,111,114, 32, 34, 46, 46,111,112, 95, + 107, 46, 46, 34, 44, 32,105,103,110,111,114,105,110,103, 34, + 41, 10, 9, 9, 9,114,101,116,117,114,110, 32,110,105,108, + 10, 9, 9,101,110,100, 10, 9,101,110,100, 10, 10, 9,108, + 111, 99, 97,108, 32,114,101,102, 32, 61, 32, 39, 39, 10, 32, + 108,111, 99, 97,108, 32,116, 32, 61, 32,115,112,108,105,116, + 95, 99, 95,116,111,107,101,110,115, 40,115,116,114,115,117, + 98, 40, 97, 44, 50, 44,115,116,114,108,101,110, 40, 97, 41, + 45, 49, 41, 44, 39, 44, 39, 41, 32, 45, 45, 32,101,108,105, + 109,105,110, 97,116,101, 32, 98,114, 97, 99,101,115, 10, 32, + 108,111, 99, 97,108, 32,105, 61, 49, 10, 32,108,111, 99, 97, + 108, 32,108, 32, 61, 32,123,110, 61, 48,125, 10, 32,119,104, + 105,108,101, 32,116, 91,105, 93, 32,100,111, 10, 32, 32,108, + 46,110, 32, 61, 32,108, 46,110, 43, 49, 10, 32, 32,108, 91, + 108, 46,110, 93, 32, 61, 32, 68,101, 99,108, 97,114, 97,116, + 105,111,110, 40,116, 91,105, 93, 44, 39,118, 97,114, 39, 41, + 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, + 10, 32,105,102, 32,107, 32, 61, 61, 32, 39, 91, 93, 39, 32, + 116,104,101,110, 10, 9, 32,108,111, 99, 97,108, 32, 95, 10, + 9, 32, 95, 44, 32, 95, 44, 32,114,101,102, 32, 61, 32,115, + 116,114,102,105,110,100, 40,100, 44, 39, 40, 38, 41, 39, 41, + 10, 32, 32,100, 32, 61, 32,103,115,117, 98, 40,100, 44, 39, + 38, 39, 44, 39, 39, 41, 10, 32,101,108,115,101,105,102, 32, + 107, 61, 61, 39, 38, 91, 93, 39, 32,116,104,101,110, 10, 32, + 32,108, 46,110, 32, 61, 32,108, 46,110, 43, 49, 10, 32, 32, + 108, 91,108, 46,110, 93, 32, 61, 32, 68,101, 99,108, 97,114, + 97,116,105,111,110, 40,100, 44, 39,118, 97,114, 39, 41, 10, + 32, 32,108, 91,108, 46,110, 93, 46,110, 97,109,101, 32, 61, + 32, 39,116,111,108,117, 97, 95,118, 97,108,117,101, 39, 10, + 32,101,110,100, 10, 32,108,111, 99, 97,108, 32,102, 32, 61, + 32, 68,101, 99,108, 97,114, 97,116,105,111,110, 40,100, 44, + 39,102,117,110, 99, 39, 41, 10, 32,105,102, 32,107, 32, 61, + 61, 32, 39, 91, 93, 39, 32, 97,110,100, 32, 40,108, 91, 49, + 93, 61, 61,110,105,108, 32,111,114, 32,105,115, 98, 97,115, + 105, 99, 40,108, 91, 49, 93, 46,116,121,112,101, 41,126, 61, + 39,110,117,109, 98,101,114, 39, 41, 32,116,104,101,110, 10, + 32, 32,101,114,114,111,114, 40, 39,111,112,101,114, 97,116, + 111,114, 91, 93, 32, 99, 97,110, 32,111,110,108,121, 32, 98, + 101, 32,100,101,102,105,110,101,100, 32,102,111,114, 32,110, + 117,109,101,114,105, 99, 32,105,110,100,101,120, 46, 39, 41, + 10, 32,101,110,100, 10, 32,102, 46, 97,114,103,115, 32, 61, + 32,108, 10, 32,102, 46, 99,111,110,115,116, 32, 61, 32, 99, + 10, 32,102, 46,107,105,110,100, 32, 61, 32,111,112, 95,107, + 10, 32,102, 46,108,110, 97,109,101, 32, 61, 32, 34, 46, 34, + 46, 46, 40, 95, 84, 77, 91,102, 46,107,105,110,100, 93, 32, + 111,114, 32,102, 46,107,105,110,100, 41, 10, 32,105,102, 32, + 110,111,116, 32, 95, 84, 77, 91,102, 46,107,105,110,100, 93, + 32,116,104,101,110, 10, 32, 9,102, 46, 99, 97,115,116, 95, + 111,112,101,114, 97,116,111,114, 32, 61, 32,116,114,117,101, + 10, 32,101,110,100, 10, 32,105,102, 32,102, 46,107,105,110, + 100, 32, 61, 61, 32, 39, 91, 93, 39, 32, 97,110,100, 32,114, + 101,102, 61, 61, 39, 38, 39, 32, 97,110,100, 32,102, 46, 99, + 111,110,115,116,126, 61, 39, 99,111,110,115,116, 39, 32,116, + 104,101,110, 10, 32, 32, 79,112,101,114, 97,116,111,114, 40, + 100, 44, 39, 38, 39, 46, 46,107, 44, 97, 44, 99, 41, 32, 9, + 45, 45, 32, 99,114,101, 97,116,101, 32, 99,111,114,114,101, + 115,112,111,100,105,110,103, 32,115,101,116, 32,111,112,101, + 114, 97,116,111,114, 10, 32,101,110,100, 10, 32,114,101,116, + 117,114,110, 32, 95, 79,112,101,114, 97,116,111,114, 40,102, + 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/operator.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 10, 95,103,108,111, 98, 97,108, 95,116,101,109,112,108, 97, + 116,101,115, 32, 61, 32,123,125, 10, 10, 99,108, 97,115,115, + 84,101,109,112,108, 97,116,101, 67,108, 97,115,115, 32, 61, + 32,123, 10, 10, 9,110, 97,109,101, 32, 61, 32, 39, 39, 44, + 10, 9, 98,111,100,121, 32, 61, 32, 39, 39, 44, 10, 9,112, + 97,114,101,110,116,115, 32, 61, 32,123,125, 44, 10, 9, 97, + 114,103,115, 32, 61, 32,123,125, 44, 32, 45, 45, 32,116,104, + 101, 32,116,101,109,112,108, 97,116,101, 32, 97,114,103,117, + 109,101,110,116,115, 10,125, 10, 10, 99,108, 97,115,115, 84, + 101,109,112,108, 97,116,101, 67,108, 97,115,115, 46, 95, 95, + 105,110,100,101,120, 32, 61, 32, 99,108, 97,115,115, 84,101, + 109,112,108, 97,116,101, 67,108, 97,115,115, 10, 10, 10,102, + 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 84,101, + 109,112,108, 97,116,101, 67,108, 97,115,115, 58,116,104,114, + 111,119, 40,116,121,112,101,115, 44, 32,108,111, 99, 97,108, + 95,115, 99,111,112,101, 41, 10, 10, 9, 45, 45,105,102, 32, + 116, 97, 98,108,101, 46,103,101,116,110, 40,116,121,112,101, + 115, 41, 32,126, 61, 32,116, 97, 98,108,101, 46,103,101,116, + 110, 40,115,101,108,102, 46, 97,114,103,115, 41, 32,116,104, + 101,110, 10, 9, 45, 45, 9,101,114,114,111,114, 40, 34, 35, + 105,110,118, 97,108,105,100, 32,112, 97,114, 97,109,101,116, + 101,114, 32, 99,111,117,110,116, 34, 41, 10, 9, 45, 45,101, + 110,100, 10, 10, 9, 45, 45, 32,114,101,112,108, 97, 99,101, + 10, 9,102,111,114, 32,105, 32, 61, 49, 32, 44, 32,116,121, + 112,101,115, 46,110, 32,100,111, 10, 10, 9, 9,108,111, 99, + 97,108, 32, 73,108, 32, 61, 32,115,112,108,105,116, 95, 99, + 95,116,111,107,101,110,115, 40,116,121,112,101,115, 91,105, + 93, 44, 32, 34, 32, 34, 41, 10, 9, 9,105,102, 32,116, 97, + 98,108,101, 46,103,101,116,110, 40, 73,108, 41, 32,126, 61, + 32,116, 97, 98,108,101, 46,103,101,116,110, 40,115,101,108, + 102, 46, 97,114,103,115, 41, 32,116,104,101,110, 10, 9, 9, + 9,101,114,114,111,114, 40, 34, 35,105,110,118, 97,108,105, + 100, 32,112, 97,114, 97,109,101,116,101,114, 32, 99,111,117, + 110,116, 32,102,111,114, 32, 34, 46, 46,116,121,112,101,115, + 91,105, 93, 41, 10, 9, 9,101,110,100, 10, 9, 9,108,111, + 99, 97,108, 32, 98, 73, 32, 61, 32,115,101,108,102, 46, 98, + 111,100,121, 10, 9, 9,108,111, 99, 97,108, 32,112, 73, 32, + 61, 32,123,125, 10, 9, 9,102,111,114, 32,106, 32, 61, 32, + 49, 44,115,101,108,102, 46, 97,114,103,115, 46,110, 32,100, + 111, 10, 9, 9, 9, 45, 45, 84,108, 91,106, 93, 32, 61, 32, + 102,105,110,100,116,121,112,101, 40, 84,108, 91,106, 93, 41, + 32,111,114, 32, 84,108, 91,106, 93, 10, 9, 9, 9, 98, 73, + 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40, + 98, 73, 44, 32, 34, 40, 91, 94, 95, 37,119, 93, 41, 34, 46, + 46,115,101,108,102, 46, 97,114,103,115, 91,106, 93, 46, 46, + 34, 40, 91, 94, 95, 37,119, 93, 41, 34, 44, 32, 34, 37, 49, + 34, 46, 46, 73,108, 91,106, 93, 46, 46, 34, 37, 50, 34, 41, + 10, 9, 9, 9,105,102, 32,115,101,108,102, 46,112, 97,114, + 101,110,116,115, 32,116,104,101,110, 10, 9, 9, 9, 9,102, + 111,114, 32,105, 61, 49, 44,116, 97, 98,108,101, 46,103,101, + 116,110, 40,115,101,108,102, 46,112, 97,114,101,110,116,115, + 41, 32,100,111, 10, 9, 9, 9, 9, 9,112, 73, 91,105, 93, + 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40, + 115,101,108,102, 46,112, 97,114,101,110,116,115, 91,105, 93, + 44, 32, 34, 40, 91, 94, 95, 37,119, 93, 63, 41, 34, 46, 46, + 115,101,108,102, 46, 97,114,103,115, 91,106, 93, 46, 46, 34, + 40, 91, 94, 95, 37,119, 93, 63, 41, 34, 44, 32, 34, 37, 49, + 34, 46, 46, 73,108, 91,106, 93, 46, 46, 34, 37, 50, 34, 41, + 10, 9, 9, 9, 9,101,110,100, 10, 9, 9, 9,101,110,100, + 10, 9, 9,101,110,100, 10, 9, 9, 45, 45,108,111, 99, 97, + 108, 32, 97,112,112,101,110,100, 32, 61, 32, 34, 60, 34, 46, + 46,115,116,114,105,110,103, 46,103,115,117, 98, 40,116,121, + 112,101,115, 91,105, 93, 44, 32, 34, 37,115, 43, 34, 44, 32, + 34, 44, 34, 41, 46, 46, 34, 62, 34, 10, 9, 9,108,111, 99, + 97,108, 32, 97,112,112,101,110,100, 32, 61, 32, 34, 60, 34, + 46, 46, 99,111,110, 99, 97,116, 40, 73,108, 44, 32, 49, 44, + 32,116, 97, 98,108,101, 46,103,101,116,110, 40, 73,108, 41, + 44, 32, 34, 44, 34, 41, 46, 46, 34, 62, 34, 10, 9, 9, 97, + 112,112,101,110,100, 32, 61, 32,115,116,114,105,110,103, 46, + 103,115,117, 98, 40, 97,112,112,101,110,100, 44, 32, 34, 37, + 115, 42, 44, 37,115, 42, 34, 44, 32, 34, 44, 34, 41, 10, 9, + 9, 97,112,112,101,110,100, 32, 61, 32,115,116,114,105,110, + 103, 46,103,115,117, 98, 40, 97,112,112,101,110,100, 44, 32, + 34, 62, 62, 34, 44, 32, 34, 62, 32, 62, 34, 41, 10, 9, 9, + 102,111,114, 32,105, 61, 49, 44,116, 97, 98,108,101, 46,103, + 101,116,110, 40,112, 73, 41, 32,100,111, 10, 9, 9, 9, 45, + 45,112, 73, 91,105, 93, 32, 61, 32,115,116,114,105,110,103, + 46,103,115,117, 98, 40,112, 73, 91,105, 93, 44, 32, 34, 62, + 62, 34, 44, 32, 34, 62, 32, 62, 34, 41, 10, 9, 9, 9,112, + 73, 91,105, 93, 32, 61, 32,114,101,115,111,108,118,101, 95, + 116,101,109,112,108, 97,116,101, 95,116,121,112,101,115, 40, + 112, 73, 91,105, 93, 41, 10, 9, 9,101,110,100, 10, 9, 9, + 98, 73, 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, + 98, 40, 98, 73, 44, 32, 34, 62, 62, 34, 44, 32, 34, 62, 32, + 62, 34, 41, 10, 9, 9,108,111, 99, 97,108, 32,110, 32, 61, + 32,115,101,108,102, 46,110, 97,109,101, 10, 9, 9,105,102, + 32,108,111, 99, 97,108, 95,115, 99,111,112,101, 32,116,104, + 101,110, 10, 9, 9, 9,110, 32, 61, 32,115,101,108,102, 46, + 108,111, 99, 97,108, 95,110, 97,109,101, 10, 9, 9,101,110, + 100, 10, 10, 9, 9, 67,108, 97,115,115, 40,110, 46, 46, 97, + 112,112,101,110,100, 44, 32,112, 73, 44, 32, 98, 73, 41, 10, + 9,101,110,100, 10,101,110,100, 10, 10, 10,102,117,110, 99, + 116,105,111,110, 32, 84,101,109,112,108, 97,116,101, 67,108, + 97,115,115, 40,110, 97,109,101, 44, 32,112, 97,114,101,110, + 116,115, 44, 32, 98,111,100,121, 44, 32,112, 97,114, 97,109, + 101,116,101,114,115, 41, 10, 10, 9,108,111, 99, 97,108, 32, + 111, 32, 61, 32,123, 10, 9, 10, 9, 9,112, 97,114,101,110, + 116,115, 32, 61, 32,112, 97,114,101,110,116,115, 44, 10, 9, + 9, 98,111,100,121, 32, 61, 32, 98,111,100,121, 44, 10, 9, + 9, 97,114,103,115, 32, 61, 32,112, 97,114, 97,109,101,116, + 101,114,115, 44, 10, 9,125, 10, 9, 10, 9,108,111, 99, 97, + 108, 32,111,110, 97,109,101, 32, 61, 32,115,116,114,105,110, + 103, 46,103,115,117, 98, 40,110, 97,109,101, 44, 32, 34, 64, + 46, 42, 36, 34, 44, 32, 34, 34, 41, 10, 9,111,110, 97,109, + 101, 32, 61, 32,103,101,116,110, 97,109,101,115,112, 97, 99, + 101, 40, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101, + 114, 46, 99,117,114,114, 41, 46, 46,111,110, 97,109,101, 10, + 9,111, 46,110, 97,109,101, 32, 61, 32,111,110, 97,109,101, + 10, 10, 9,111, 46,108,111, 99, 97,108, 95,110, 97,109,101, + 32, 61, 32,110, 97,109,101, 10, 9, 10, 9,115,101,116,109, + 101,116, 97,116, 97, 98,108,101, 40,111, 44, 32, 99,108, 97, + 115,115, 84,101,109,112,108, 97,116,101, 67,108, 97,115,115, + 41, 10, 10, 9,105,102, 32, 95,103,108,111, 98, 97,108, 95, + 116,101,109,112,108, 97,116,101,115, 91,111,110, 97,109,101, + 93, 32,116,104,101,110, 10, 9, 9,119, 97,114,110,105,110, + 103, 40, 34, 68,117,112,108,105, 99, 97,116,101, 32,100,101, + 99,108, 97,114, 97,116,105,111,110, 32,111,102, 32,116,101, + 109,112,108, 97,116,101, 32, 34, 46, 46,111,110, 97,109,101, + 41, 10, 9,101,108,115,101, 10, 9, 9, 95,103,108,111, 98, + 97,108, 95,116,101,109,112,108, 97,116,101,115, 91,111,110, + 97,109,101, 93, 32, 61, 32,111, 10, 9,101,110,100, 10, 10, + 9,114,101,116,117,114,110, 32,111, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/template_class.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,116,111,108,117, 97, 58, 32, 99,108, 97,115,115, + 32, 99,108, 97,115,115, 10, 45, 45, 32, 87,114,105,116,116, + 101,110, 32, 98,121, 32, 87, 97,108,100,101,109, 97,114, 32, + 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, 71,114, 97, + 102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, 32, 74,117, + 108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 36, 73,100, 58, 32, + 36, 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111,100,101, + 32,105,115, 32,102,114,101,101, 32,115,111,102,116,119, 97, + 114,101, 59, 32,121,111,117, 32, 99, 97,110, 32,114,101,100, + 105,115,116,114,105, 98,117,116,101, 32,105,116, 32, 97,110, + 100, 47,111,114, 32,109,111,100,105,102,121, 32,105,116, 46, + 10, 45, 45, 32, 84,104,101, 32,115,111,102,116,119, 97,114, + 101, 32,112,114,111,118,105,100,101,100, 32,104,101,114,101, + 117,110,100,101,114, 32,105,115, 32,111,110, 32, 97,110, 32, + 34, 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, 44, 32, + 97,110,100, 10, 45, 45, 32,116,104,101, 32, 97,117,116,104, + 111,114, 32,104, 97,115, 32,110,111, 32,111, 98,108,105,103, + 97,116,105,111,110, 32,116,111, 32,112,114,111,118,105,100, + 101, 32,109, 97,105,110,116,101,110, 97,110, 99,101, 44, 32, + 115,117,112,112,111,114,116, 44, 32,117,112,100, 97,116,101, + 115, 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101,109,101, + 110,116,115, 44, 32,111,114, 32,109,111,100,105,102,105, 99, + 97,116,105,111,110,115, 46, 10, 10, 10, 45, 45, 32, 67,108, + 97,115,115, 32, 99,108, 97,115,115, 10, 45, 45, 32, 82,101, + 112,114,101,115,101,110,116,115, 32, 97, 32, 99,108, 97,115, + 115, 32,100,101,102,105,110,105,116,105,111,110, 46, 10, 45, + 45, 32, 83,116,111,114,101,115, 32,116,104,101, 32,102,111, + 108,108,111,119,105,110,103, 32,102,105,101,108,100,115, 58, + 10, 45, 45, 32, 32, 32, 32,110, 97,109,101, 32, 61, 32, 99, + 108, 97,115,115, 32,110, 97,109,101, 10, 45, 45, 32, 32, 32, + 32, 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 32, 98, + 97,115,101, 44, 32,105,102, 32, 97,110,121, 32, 40,111,110, + 108,121, 32,115,105,110,103,108,101, 32,105,110,104,101,114, + 105,116, 97,110, 99,101, 32,105,115, 32,115,117,112,112,111, + 114,116,101,100, 41, 10, 45, 45, 32, 32, 32, 32,123,105,125, + 32, 32, 61, 32,108,105,115,116, 32,111,102, 32,109,101,109, + 98,101,114,115, 10, 99,108, 97,115,115, 67,108, 97,115,115, + 32, 61, 32,123, 10, 32, 99,108, 97,115,115,116,121,112,101, + 32, 61, 32, 39, 99,108, 97,115,115, 39, 44, 10, 32,110, 97, + 109,101, 32, 61, 32, 39, 39, 44, 10, 32, 98, 97,115,101, 32, + 61, 32, 39, 39, 44, 10, 32,116,121,112,101, 32, 61, 32, 39, + 39, 44, 10, 32, 98,116,121,112,101, 32, 61, 32, 39, 39, 44, + 10, 32, 99,116,121,112,101, 32, 61, 32, 39, 39, 44, 10,125, + 10, 99,108, 97,115,115, 67,108, 97,115,115, 46, 95, 95,105, + 110,100,101,120, 32, 61, 32, 99,108, 97,115,115, 67,108, 97, + 115,115, 10,115,101,116,109,101,116, 97,116, 97, 98,108,101, + 40, 99,108, 97,115,115, 67,108, 97,115,115, 44, 99,108, 97, + 115,115, 67,111,110,116, 97,105,110,101,114, 41, 10, 10, 10, + 45, 45, 32,114,101,103,105,115,116,101,114, 32, 99,108, 97, + 115,115, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 67,108, 97,115,115, 58,114,101,103,105,115,116,101, + 114, 32, 40,112,114,101, 41, 10, 10, 9,105,102, 32,110,111, + 116, 32,115,101,108,102, 58, 99,104,101, 99,107, 95,112,117, + 98,108,105, 99, 95, 97, 99, 99,101,115,115, 40, 41, 32,116, + 104,101,110, 10, 9, 9,114,101,116,117,114,110, 10, 9,101, + 110,100, 10, 10, 32,112,114,101, 32, 61, 32,112,114,101, 32, + 111,114, 32, 39, 39, 10, 32,112,117,115,104, 40,115,101,108, + 102, 41, 10, 9,105,102, 32, 95, 99,111,108,108,101, 99,116, + 91,115,101,108,102, 46,116,121,112,101, 93, 32,116,104,101, + 110, 10, 9, 9,111,117,116,112,117,116, 40,112,114,101, 44, + 39, 35,105,102,100,101,102, 32, 95, 95, 99,112,108,117,115, + 112,108,117,115, 92,110, 39, 41, 10, 32, 32,111,117,116,112, + 117,116, 40,112,114,101, 46, 46, 39,116,111,108,117, 97, 95, + 99, 99,108, 97,115,115, 40,116,111,108,117, 97, 95, 83, 44, + 34, 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, + 46, 39, 34, 44, 34, 39, 46, 46,115,101,108,102, 46,116,121, + 112,101, 46, 46, 39, 34, 44, 34, 39, 46, 46,115,101,108,102, + 46, 98,116,121,112,101, 46, 46, 39, 34, 44, 39, 46, 46, 95, + 99,111,108,108,101, 99,116, 91,115,101,108,102, 46,116,121, + 112,101, 93, 46, 46, 39, 41, 59, 39, 41, 10, 9, 9,111,117, + 116,112,117,116, 40,112,114,101, 44, 39, 35,101,108,115,101, + 92,110, 39, 41, 10, 32, 32,111,117,116,112,117,116, 40,112, + 114,101, 46, 46, 39,116,111,108,117, 97, 95, 99, 99,108, 97, + 115,115, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46, + 115,101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, 44, + 34, 39, 46, 46,115,101,108,102, 46,116,121,112,101, 46, 46, + 39, 34, 44, 34, 39, 46, 46,115,101,108,102, 46, 98,116,121, + 112,101, 46, 46, 39, 34, 44, 78, 85, 76, 76, 41, 59, 39, 41, + 10, 9, 9,111,117,116,112,117,116, 40,112,114,101, 44, 39, + 35,101,110,100,105,102, 92,110, 39, 41, 10, 9,101,108,115, + 101, 10, 32, 32,111,117,116,112,117,116, 40,112,114,101, 46, + 46, 39,116,111,108,117, 97, 95, 99, 99,108, 97,115,115, 40, + 116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46,115,101,108, + 102, 46,108,110, 97,109,101, 46, 46, 39, 34, 44, 34, 39, 46, + 46,115,101,108,102, 46,116,121,112,101, 46, 46, 39, 34, 44, + 34, 39, 46, 46,115,101,108,102, 46, 98,116,121,112,101, 46, + 46, 39, 34, 44, 78, 85, 76, 76, 41, 59, 39, 41, 10, 9,101, + 110,100, 10, 9,105,102, 32,115,101,108,102, 46,101,120,116, + 114, 97, 95, 98, 97,115,101,115, 32,116,104,101,110, 10, 9, + 9,102,111,114, 32,107, 44, 98, 97,115,101, 32,105,110, 32, + 105,112, 97,105,114,115, 40,115,101,108,102, 46,101,120,116, + 114, 97, 95, 98, 97,115,101,115, 41, 32,100,111, 10, 9, 9, + 9, 45, 45, 32,110,111,116, 32,110,111,119, 10, 32, 32, 32, + 45, 45,111,117,116,112,117,116, 40,112,114,101, 46, 46, 39, + 32,116,111,108,117, 97, 95, 97,100,100, 98, 97,115,101, 40, + 116,111,108,117, 97, 95, 83, 44, 32, 34, 39, 46, 46,115,101, + 108,102, 46,116,121,112,101, 46, 46, 39, 34, 44, 32, 34, 39, + 46, 46, 98, 97,115,101, 46, 46, 39, 34, 41, 59, 39, 41, 10, + 9, 9,101,110,100, 10, 9,101,110,100, 10, 32,111,117,116, + 112,117,116, 40,112,114,101, 46, 46, 39,116,111,108,117, 97, + 95, 98,101,103,105,110,109,111,100,117,108,101, 40,116,111, + 108,117, 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46, + 108,110, 97,109,101, 46, 46, 39, 34, 41, 59, 39, 41, 10, 32, + 108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104,105,108, + 101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10, 32, 32, + 115,101,108,102, 91,105, 93, 58,114,101,103,105,115,116,101, + 114, 40,112,114,101, 46, 46, 39, 32, 39, 41, 10, 32, 32,105, + 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 32,111,117, + 116,112,117,116, 40,112,114,101, 46, 46, 39,116,111,108,117, + 97, 95,101,110,100,109,111,100,117,108,101, 40,116,111,108, + 117, 97, 95, 83, 41, 59, 39, 41, 10, 9,112,111,112, 40, 41, + 10,101,110,100, 10, 10, 45, 45, 32,114,101,116,117,114,110, + 32, 99,111,108,108,101, 99,116,105,111,110, 32,114,101,113, + 117,105,114,101,109,101,110,116, 10,102,117,110, 99,116,105, + 111,110, 32, 99,108, 97,115,115, 67,108, 97,115,115, 58,114, + 101,113,117,105,114,101, 99,111,108,108,101, 99,116,105,111, + 110, 32, 40,116, 41, 10, 9,105,102, 32,115,101,108,102, 46, + 102,108, 97,103,115, 46,112,114,111,116,101, 99,116,101,100, + 95,100,101,115,116,114,117, 99,116,111,114, 32,111,114, 32, + 40,110,111,116, 32,115,101,108,102, 58, 99,104,101, 99,107, + 95,112,117, 98,108,105, 99, 95, 97, 99, 99,101,115,115, 40, + 41, 41, 32,116,104,101,110, 10, 9, 9,114,101,116,117,114, + 110, 32,102, 97,108,115,101, 10, 9,101,110,100, 10, 32,112, + 117,115,104, 40,115,101,108,102, 41, 10, 9,108,111, 99, 97, + 108, 32,114, 32, 61, 32,102, 97,108,115,101, 10, 32,108,111, + 99, 97,108, 32,105, 61, 49, 10, 32,119,104,105,108,101, 32, + 115,101,108,102, 91,105, 93, 32,100,111, 10, 32, 32,114, 32, + 61, 32,115,101,108,102, 91,105, 93, 58,114,101,113,117,105, + 114,101, 99,111,108,108,101, 99,116,105,111,110, 40,116, 41, + 32,111,114, 32,114, 10, 32, 32,105, 32, 61, 32,105, 43, 49, + 10, 32,101,110,100, 10, 9,112,111,112, 40, 41, 10, 9, 45, + 45, 32,111,110,108,121, 32, 99,108, 97,115,115, 32,116,104, + 97,116, 32,101,120,112,111,114,116,115, 32,100,101,115,116, + 114,117, 99,116,111,114, 32, 99, 97,110, 32, 98,101, 32, 97, + 112,112,114,111,112,114,105, 97,116,101,108,121, 32, 99,111, + 108,108,101, 99,116,101,100, 10, 9, 45, 45, 32, 99,108, 97, + 115,115,101,115, 32,116,104, 97,116, 32,101,120,112,111,114, + 116, 32, 99,111,110,115,116,114,117, 99,116,111,114,115, 32, + 110,101,101,100, 32,116,111, 32,104, 97,118,101, 32, 97, 32, + 99,111,108,108,101, 99,116,111,114, 32, 40,111,118,101,114, + 114,105,100,101,100, 32, 98,121, 32, 45, 68, 32,102,108, 97, + 103, 32,111,110, 32, 99,111,109,109, 97,110,100, 32,108,105, + 110,101, 41, 10, 9,105,102, 32,115,101,108,102, 46, 95,100, + 101,108,101,116,101, 32,111,114, 32, 40, 40,110,111,116, 32, + 102,108, 97,103,115, 91, 39, 68, 39, 93, 41, 32, 97,110,100, + 32,115,101,108,102, 46, 95,110,101,119, 41, 32,116,104,101, + 110, 10, 9, 9, 45, 45,116, 91,115,101,108,102, 46,116,121, + 112,101, 93, 32, 61, 32, 34,116,111,108,117, 97, 95, 99,111, + 108,108,101, 99,116, 95, 34, 32, 46, 46, 32,103,115,117, 98, + 40,115,101,108,102, 46,116,121,112,101, 44, 34, 58, 58, 34, + 44, 34, 95, 34, 41, 10, 9, 9,116, 91,115,101,108,102, 46, + 116,121,112,101, 93, 32, 61, 32, 34,116,111,108,117, 97, 95, + 99,111,108,108,101, 99,116, 95, 34, 32, 46, 46, 32, 99,108, + 101, 97,110, 95,116,101,109,112,108, 97,116,101, 40,115,101, + 108,102, 46,116,121,112,101, 41, 10, 9, 9,114, 32, 61, 32, + 116,114,117,101, 10, 9,101,110,100, 10, 32,114,101,116,117, + 114,110, 32,114, 10,101,110,100, 10, 10, 45, 45, 32,111,117, + 116,112,117,116, 32,116, 97,103,115, 10,102,117,110, 99,116, + 105,111,110, 32, 99,108, 97,115,115, 67,108, 97,115,115, 58, + 100,101, 99,108,116,121,112,101, 32, 40, 41, 10, 32,112,117, + 115,104, 40,115,101,108,102, 41, 10, 9,115,101,108,102, 46, + 116,121,112,101, 32, 61, 32,114,101,103,116,121,112,101, 40, + 115,101,108,102, 46,111,114,105,103,105,110, 97,108, 95,110, + 97,109,101, 32,111,114, 32,115,101,108,102, 46,110, 97,109, + 101, 41, 10, 9,115,101,108,102, 46, 98,116,121,112,101, 32, + 61, 32,116,121,112,101,118, 97,114, 40,115,101,108,102, 46, + 98, 97,115,101, 41, 10, 9,115,101,108,102, 46, 99,116,121, + 112,101, 32, 61, 32, 39, 99,111,110,115,116, 32, 39, 46, 46, + 115,101,108,102, 46,116,121,112,101, 10, 9,105,102, 32,115, + 101,108,102, 46,101,120,116,114, 97, 95, 98, 97,115,101,115, + 32,116,104,101,110, 10, 9, 9,102,111,114, 32,105, 61, 49, + 44,116, 97, 98,108,101, 46,103,101,116,110, 40,115,101,108, + 102, 46,101,120,116,114, 97, 95, 98, 97,115,101,115, 41, 32, + 100,111, 10, 9, 9, 9,115,101,108,102, 46,101,120,116,114, + 97, 95, 98, 97,115,101,115, 91,105, 93, 32, 61, 32,116,121, + 112,101,118, 97,114, 40,115,101,108,102, 46,101,120,116,114, + 97, 95, 98, 97,115,101,115, 91,105, 93, 41, 10, 9, 9,101, + 110,100, 10, 9,101,110,100, 10, 32,108,111, 99, 97,108, 32, + 105, 61, 49, 10, 32,119,104,105,108,101, 32,115,101,108,102, + 91,105, 93, 32,100,111, 10, 32, 32,115,101,108,102, 91,105, + 93, 58,100,101, 99,108,116,121,112,101, 40, 41, 10, 32, 32, + 105, 32, 61, 32,105, 43, 49, 10, 32,101,110,100, 10, 9,112, + 111,112, 40, 41, 10,101,110,100, 10, 10, 10, 45, 45, 32, 80, + 114,105,110,116, 32,109,101,116,104,111,100, 10,102,117,110, + 99,116,105,111,110, 32, 99,108, 97,115,115, 67,108, 97,115, + 115, 58,112,114,105,110,116, 32, 40,105,100,101,110,116, 44, + 99,108,111,115,101, 41, 10, 32,112,114,105,110,116, 40,105, + 100,101,110,116, 46, 46, 34, 67,108, 97,115,115,123, 34, 41, + 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, + 34, 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101, + 108,102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32, 98, 97,115,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46, 98, 97,115,101, 46, 46, 34, 39, 59, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 108,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,108,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, 10, 32, + 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, + 98,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, + 102, 46, 98,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, 10, + 32,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, + 32, 99,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115,101, + 108,102, 46, 99,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, + 10, 32,108,111, 99, 97,108, 32,105, 61, 49, 10, 32,119,104, + 105,108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10, + 32, 32,115,101,108,102, 91,105, 93, 58,112,114,105,110,116, + 40,105,100,101,110,116, 46, 46, 34, 32, 34, 44, 34, 44, 34, + 41, 10, 32, 32,105, 32, 61, 32,105, 43, 49, 10, 32,101,110, + 100, 10, 32,112,114,105,110,116, 40,105,100,101,110,116, 46, + 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110, + 100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, + 115,115, 67,108, 97,115,115, 58,115,101,116, 95,112,114,111, + 116,101, 99,116,101,100, 95,100,101,115,116,114,117, 99,116, + 111,114, 40,112, 41, 10, 9,115,101,108,102, 46,102,108, 97, + 103,115, 46,112,114,111,116,101, 99,116,101,100, 95,100,101, + 115,116,114,117, 99,116,111,114, 32, 61, 32,115,101,108,102, + 46,102,108, 97,103,115, 46,112,114,111,116,101, 99,116,101, + 100, 95,100,101,115,116,114,117, 99,116,111,114, 32,111,114, + 32,112, 10,101,110,100, 10, 10, 45, 45, 32, 73,110,116,101, + 114,110, 97,108, 32, 99,111,110,115,116,114,117, 99,116,111, + 114, 10,102,117,110, 99,116,105,111,110, 32, 95, 67,108, 97, + 115,115, 32, 40,116, 41, 10, 32,115,101,116,109,101,116, 97, + 116, 97, 98,108,101, 40,116, 44, 99,108, 97,115,115, 67,108, + 97,115,115, 41, 10, 32,116, 58, 98,117,105,108,100,110, 97, + 109,101,115, 40, 41, 10, 32, 97,112,112,101,110,100, 40,116, + 41, 10, 32,114,101,116,117,114,110, 32,116, 10,101,110,100, + 10, 10, 45, 45, 32, 67,111,110,115,116,114,117, 99,116,111, + 114, 10, 45, 45, 32, 69,120,112,101, 99,116,115, 32,116,104, + 101, 32,110, 97,109,101, 44, 32,116,104,101, 32, 98, 97,115, + 101, 32, 40, 97,114,114, 97,121, 41, 32, 97,110,100, 32,116, + 104,101, 32, 98,111,100,121, 32,111,102, 32,116,104,101, 32, + 99,108, 97,115,115, 46, 10,102,117,110, 99,116,105,111,110, + 32, 67,108, 97,115,115, 32, 40,110, 44,112, 44, 98, 41, 10, + 10, 9,105,102, 32,116, 97, 98,108,101, 46,103,101,116,110, + 40,112, 41, 32, 62, 32, 49, 32,116,104,101,110, 10, 9, 9, + 98, 32, 61, 32,115,116,114,105,110,103, 46,115,117, 98, 40, + 98, 44, 32, 49, 44, 32, 45, 50, 41, 10, 9, 9,102,111,114, + 32,105, 61, 50, 44,116, 97, 98,108,101, 46,103,101,116,110, + 40,112, 41, 44, 49, 32,100,111, 10, 9, 9, 9, 98, 32, 61, + 32, 98, 46, 46, 34, 92,110, 32,116,111,108,117, 97, 95,105, + 110,104,101,114,105,116,115, 32, 34, 46, 46,112, 91,105, 93, + 46, 46, 34, 32, 95, 95, 34, 46, 46,112, 91,105, 93, 46, 46, + 34, 95, 95, 59, 92,110, 34, 10, 9, 9,101,110,100, 10, 9, + 9, 98, 32, 61, 32, 98, 46, 46, 34, 92,110,125, 34, 10, 9, + 101,110,100, 10, 10, 9, 45, 45, 32, 99,104,101, 99,107, 32, + 102,111,114, 32,116,101,109,112,108, 97,116,101, 10, 9, 98, + 32, 61, 32,115,116,114,105,110,103, 46,103,115,117, 98, 40, + 98, 44, 32, 34, 94,123, 37,115, 42, 84, 69, 77, 80, 76, 65, + 84, 69, 95, 66, 73, 78, 68, 34, 44, 32, 34,123, 92,110, 84, + 79, 76, 85, 65, 95, 84, 69, 77, 80, 76, 65, 84, 69, 95, 66, + 73, 78, 68, 34, 41, 10, 9,108,111, 99, 97,108, 32,116, 44, + 95, 44, 84, 44, 73, 32, 61, 32,115,116,114,105,110,103, 46, + 102,105,110,100, 40, 98, 44, 32, 39, 94,123, 37,115, 42, 84, + 79, 76, 85, 65, 95, 84, 69, 77, 80, 76, 65, 84, 69, 95, 66, + 73, 78, 68, 37,115, 42, 37, 40, 43, 37,115, 42, 92, 34, 63, + 40, 91, 94, 92, 34, 44, 93, 42, 41, 92, 34, 63, 37,115, 42, + 44, 37,115, 42, 40, 91, 94, 37, 41, 93, 42, 41, 37,115, 42, + 37, 41, 43, 39, 41, 10, 9,105,102, 32,116, 32,116,104,101, + 110, 10, 10, 9, 9, 45, 45, 32,114,101,109,111,118,101, 32, + 113,117,111,116,101,115, 10, 9, 9, 73, 32, 61, 32,115,116, + 114,105,110,103, 46,103,115,117, 98, 40, 73, 44, 32, 34, 92, + 34, 34, 44, 32, 34, 34, 41, 10, 9, 9, 84, 32, 61, 32,115, + 116,114,105,110,103, 46,103,115,117, 98, 40, 84, 44, 32, 34, + 92, 34, 34, 44, 32, 34, 34, 41, 10, 9, 9, 45, 45, 32,103, + 101,116, 32,116,121,112,101, 32,108,105,115,116, 10, 9, 9, + 108,111, 99, 97,108, 32,116,121,112,101,115, 32, 61, 32,115, + 112,108,105,116, 95, 99, 95,116,111,107,101,110,115, 40, 73, + 44, 32, 34, 44, 34, 41, 10, 9, 9, 45, 45, 32,114,101,109, + 111,118,101, 32, 84, 69, 77, 80, 76, 65, 84, 69, 95, 66, 73, + 78, 68, 32,108,105,110,101, 10, 9, 9,108,111, 99, 97,108, + 32, 98,115, 32, 61, 32,115,116,114,105,110,103, 46,103,115, + 117, 98, 40, 98, 44, 32, 34, 94,123, 37,115, 42, 84, 79, 76, + 85, 65, 95, 84, 69, 77, 80, 76, 65, 84, 69, 95, 66, 73, 78, + 68, 91, 94, 92,110, 93, 42, 92,110, 34, 44, 32, 34,123, 92, + 110, 34, 41, 10, 9, 9, 9, 10, 9, 9,108,111, 99, 97,108, + 32, 84,108, 32, 61, 32,115,112,108,105,116, 40, 84, 44, 32, + 34, 32, 34, 41, 10, 9, 9,108,111, 99, 97,108, 32,116, 99, + 32, 61, 32, 84,101,109,112,108, 97,116,101, 67,108, 97,115, + 115, 40,110, 44, 32,112, 44, 32, 98,115, 44, 32, 84,108, 41, + 10, 10, 9, 9, 10, 9, 9,116, 99, 58,116,104,114,111,119, + 40,116,121,112,101,115, 44, 32,116,114,117,101, 41, 10, 9, + 9, 45, 45,102,111,114, 32,105, 61, 49, 44,116,121,112,101, + 115, 46,110, 32,100,111, 10, 9, 9, 45, 45, 9,116, 99, 58, + 116,104,114,111,119, 40,115,112,108,105,116, 95, 99, 95,116, + 111,107,101,110,115, 40,116,121,112,101,115, 91,105, 93, 44, + 32, 34, 32, 34, 41, 44, 32,116,114,117,101, 41, 10, 9, 9, + 45, 45,101,110,100, 10, 9, 9,114,101,116,117,114,110, 10, + 9,101,110,100, 10, 9, 10, 9,108,111, 99, 97,108, 32,109, + 98, 97,115,101, 10, 10, 9,105,102, 32,112, 32,116,104,101, + 110, 10, 9, 9,109, 98, 97,115,101, 32, 61, 32,116, 97, 98, + 108,101, 46,114,101,109,111,118,101, 40,112, 44, 32, 49, 41, + 10, 9, 9,105,102, 32,110,111,116, 32,112, 91, 49, 93, 32, + 116,104,101,110, 32,112, 32, 61, 32,110,105,108, 32,101,110, + 100, 10, 9,101,110,100, 10, 10, 9,109, 98, 97,115,101, 32, + 61, 32,109, 98, 97,115,101, 32, 97,110,100, 32,114,101,115, + 111,108,118,101, 95,116,101,109,112,108, 97,116,101, 95,116, + 121,112,101,115, 40,109, 98, 97,115,101, 41, 10, 10, 9,108, + 111, 99, 97,108, 32, 99, 10, 9,108,111, 99, 97,108, 32,111, + 110, 97,109,101, 32, 61, 32,115,116,114,105,110,103, 46,103, + 115,117, 98, 40,110, 44, 32, 34, 64, 46, 42, 36, 34, 44, 32, + 34, 34, 41, 10, 9,111,110, 97,109,101, 32, 61, 32,103,101, + 116,110, 97,109,101,115,112, 97, 99,101, 40, 99,108, 97,115, + 115, 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, + 41, 46, 46,111,110, 97,109,101, 10, 10, 9,105,102, 32, 95, + 103,108,111, 98, 97,108, 95, 99,108, 97,115,115,101,115, 91, + 111,110, 97,109,101, 93, 32,116,104,101,110, 10, 9, 9, 99, + 32, 61, 32, 95,103,108,111, 98, 97,108, 95, 99,108, 97,115, + 115,101,115, 91,111,110, 97,109,101, 93, 10, 9, 9,105,102, + 32,109, 98, 97,115,101, 32, 97,110,100, 32, 40, 40,110,111, + 116, 32, 99, 46, 98, 97,115,101, 41, 32,111,114, 32, 99, 46, + 98, 97,115,101, 32, 61, 61, 32, 34, 34, 41, 32,116,104,101, + 110, 10, 9, 9, 9, 99, 46, 98, 97,115,101, 32, 61, 32,109, + 98, 97,115,101, 10, 9, 9,101,110,100, 10, 9,101,108,115, + 101, 10, 9, 9, 99, 32, 61, 32, 95, 67,108, 97,115,115, 40, + 95, 67,111,110,116, 97,105,110,101,114,123,110, 97,109,101, + 61,110, 44, 32, 98, 97,115,101, 61,109, 98, 97,115,101, 44, + 32,101,120,116,114, 97, 95, 98, 97,115,101,115, 61,112,125, + 41, 10, 10, 9, 9,108,111, 99, 97,108, 32,102,116, 32, 61, + 32,103,101,116,110, 97,109,101,115,112, 97, 99,101, 40, 99, + 46,112, 97,114,101,110,116, 41, 46, 46, 99, 46,111,114,105, + 103,105,110, 97,108, 95,110, 97,109,101, 10, 9, 9, 97,112, + 112,101,110,100, 95,103,108,111, 98, 97,108, 95,116,121,112, + 101, 40,102,116, 44, 32, 99, 41, 10, 9,101,110,100, 10, 10, + 9,112,117,115,104, 40, 99, 41, 10, 9, 99, 58,112, 97,114, + 115,101, 40,115,116,114,115,117, 98, 40, 98, 44, 50, 44,115, + 116,114,108,101,110, 40, 98, 41, 45, 49, 41, 41, 32, 45, 45, + 32,101,108,105,109,105,110, 97,116,101, 32, 98,114, 97, 99, + 101,115, 10, 9,112,111,112, 40, 41, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/class.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32,109, 97,114,107, 32,117,112, 32, 99,111,109,109, + 101,110,116,115, 32, 97,110,100, 32,115,116,114,105,110,103, + 115, 10, 83, 84, 82, 49, 32, 61, 32, 34, 92, 48, 48, 49, 34, + 10, 83, 84, 82, 50, 32, 61, 32, 34, 92, 48, 48, 50, 34, 10, + 83, 84, 82, 51, 32, 61, 32, 34, 92, 48, 48, 51, 34, 10, 83, + 84, 82, 52, 32, 61, 32, 34, 92, 48, 48, 52, 34, 10, 82, 69, + 77, 32, 32, 61, 32, 34, 92, 48, 48, 53, 34, 10, 65, 78, 89, + 32, 32, 61, 32, 34, 40, 91, 92, 48, 48, 49, 45, 92, 48, 48, + 53, 93, 41, 34, 10, 69, 83, 67, 49, 32, 61, 32, 34, 92, 48, + 48, 54, 34, 10, 69, 83, 67, 50, 32, 61, 32, 34, 92, 48, 48, + 55, 34, 10, 10, 77, 65, 83, 75, 32, 61, 32,123, 32, 45, 45, + 32,116,104,101, 32,115,117, 98,115,116,105,116,117,116,105, + 111,110, 32,111,114,100,101,114, 32,105,115, 32,105,109,112, + 111,114,116, 97,110,116, 10, 32,123, 69, 83, 67, 49, 44, 32, + 34, 92, 92, 39, 34,125, 44, 10, 32,123, 69, 83, 67, 50, 44, + 32, 39, 92, 92, 34, 39,125, 44, 10, 32,123, 83, 84, 82, 49, + 44, 32, 34, 39, 34,125, 44, 10, 32,123, 83, 84, 82, 50, 44, + 32, 39, 34, 39,125, 44, 10, 32,123, 83, 84, 82, 51, 44, 32, + 34, 37, 91, 37, 91, 34,125, 44, 10, 32,123, 83, 84, 82, 52, + 44, 32, 34, 37, 93, 37, 93, 34,125, 44, 10, 32,123, 82, 69, + 77, 32, 44, 32, 34, 37, 45, 37, 45, 34,125, 44, 10,125, 10, + 10,102,117,110, 99,116,105,111,110, 32,109, 97,115,107, 32, + 40,115, 41, 10, 32,102,111,114, 32,105, 32, 61, 32, 49, 44, + 103,101,116,110, 40, 77, 65, 83, 75, 41, 32, 32,100,111, 10, + 32, 32,115, 32, 61, 32,103,115,117, 98, 40,115, 44, 77, 65, + 83, 75, 91,105, 93, 91, 50, 93, 44, 77, 65, 83, 75, 91,105, + 93, 91, 49, 93, 41, 10, 32,101,110,100, 10, 32,114,101,116, + 117,114,110, 32,115, 10,101,110,100, 10, 10,102,117,110, 99, + 116,105,111,110, 32,117,110,109, 97,115,107, 32, 40,115, 41, + 10, 32,102,111,114, 32,105, 32, 61, 32, 49, 44,103,101,116, + 110, 40, 77, 65, 83, 75, 41, 32, 32,100,111, 10, 32, 32,115, + 32, 61, 32,103,115,117, 98, 40,115, 44, 77, 65, 83, 75, 91, + 105, 93, 91, 49, 93, 44, 77, 65, 83, 75, 91,105, 93, 91, 50, + 93, 41, 10, 32,101,110,100, 10, 32,114,101,116,117,114,110, + 32,115, 10,101,110,100, 10, 10,102,117,110, 99,116,105,111, + 110, 32, 99,108,101, 97,110, 32, 40,115, 41, 10, 32, 45, 45, + 32, 99,104,101, 99,107, 32,102,111,114, 32, 99,111,109,112, + 105,108, 97,116,105,111,110, 32,101,114,114,111,114, 10, 32, + 108,111, 99, 97,108, 32, 99,111,100,101, 32, 61, 32, 34,114, + 101,116,117,114,110, 32,102,117,110, 99,116,105,111,110, 32, + 40, 41, 92,110, 34, 32, 46, 46, 32,115, 32, 46, 46, 32, 34, + 92,110, 32,101,110,100, 34, 10, 32,105,102, 32,110,111,116, + 32,100,111,115,116,114,105,110,103, 40, 99,111,100,101, 41, + 32,116,104,101,110, 10, 32, 32,114,101,116,117,114,110, 32, + 110,105,108, 10, 32,101,110,100, 10, 10, 32,105,102, 32,102, + 108, 97,103,115, 91, 39, 67, 39, 93, 32,116,104,101,110, 10, + 32, 9,114,101,116,117,114,110, 32,115, 10, 32,101,110,100, + 10, 10, 32,108,111, 99, 97,108, 32, 83, 32, 61, 32, 34, 34, + 32, 45, 45, 32,115, 97,118,101,100, 32,115,116,114,105,110, + 103, 10, 10, 32,115, 32, 61, 32,109, 97,115,107, 40,115, 41, + 10, 10, 32, 45, 45, 32,114,101,109,111,118,101, 32, 98,108, + 97,110,107,115, 32, 97,110,100, 32, 99,111,109,109,101,110, + 116,115, 10, 32,119,104,105,108,101, 32, 49, 32,100,111, 10, + 32, 32,108,111, 99, 97,108, 32, 98, 44,101, 44,100, 32, 61, + 32,115,116,114,102,105,110,100, 40,115, 44, 65, 78, 89, 41, + 10, 32, 32,105,102, 32, 98, 32,116,104,101,110, 10, 32, 32, + 32, 83, 32, 61, 32, 83, 46, 46,115,116,114,115,117, 98, 40, + 115, 44, 49, 44, 98, 45, 49, 41, 10, 32, 32, 32,115, 32, 61, + 32,115,116,114,115,117, 98, 40,115, 44, 98, 43, 49, 41, 10, + 32, 32, 32,105,102, 32,100, 61, 61, 83, 84, 82, 49, 32,111, + 114, 32,100, 61, 61, 83, 84, 82, 50, 32,116,104,101,110, 10, + 32, 32, 32, 32,101, 32, 61, 32,115,116,114,102,105,110,100, + 40,115, 44,100, 41, 10, 32, 32, 32, 32, 83, 32, 61, 32, 83, + 32, 46, 46,100, 46, 46,115,116,114,115,117, 98, 40,115, 44, + 49, 44,101, 41, 10, 32, 32, 32, 32,115, 32, 61, 32,115,116, + 114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, 32, 32, 32, + 101,108,115,101,105,102, 32,100, 61, 61, 83, 84, 82, 51, 32, + 116,104,101,110, 10, 32, 32, 32, 32,101, 32, 61, 32,115,116, + 114,102,105,110,100, 40,115, 44, 83, 84, 82, 52, 41, 10, 32, + 32, 32, 32, 83, 32, 61, 32, 83, 46, 46,100, 46, 46,115,116, + 114,115,117, 98, 40,115, 44, 49, 44,101, 41, 10, 32, 32, 32, + 32,115, 32, 61, 32,115,116,114,115,117, 98, 40,115, 44,101, + 43, 49, 41, 10, 32, 32, 32,101,108,115,101,105,102, 32,100, + 61, 61, 82, 69, 77, 32,116,104,101,110, 10, 32, 32, 32, 32, + 115, 32, 61, 32,103,115,117, 98, 40,115, 44, 34, 91, 94, 92, + 110, 93, 42, 40, 92,110, 63, 41, 34, 44, 34, 37, 49, 34, 44, + 49, 41, 10, 32, 32, 32,101,110,100, 10, 32, 32,101,108,115, + 101, 10, 32, 32, 32, 83, 32, 61, 32, 83, 46, 46,115, 10, 32, + 32, 32, 98,114,101, 97,107, 10, 32, 32,101,110,100, 10, 32, + 101,110,100, 10, 32, 45, 45, 32,101,108,105,109,105,110, 97, + 116,101, 32,117,110,101, 99,101,115,115, 97,114,121, 32,115, + 112, 97, 99,101,115, 10, 32, 83, 32, 61, 32,103,115,117, 98, + 40, 83, 44, 34, 91, 32, 92,116, 93, 43, 34, 44, 34, 32, 34, + 41, 10, 32, 83, 32, 61, 32,103,115,117, 98, 40, 83, 44, 34, + 91, 32, 92,116, 93, 42, 92,110, 91, 32, 92,116, 93, 42, 34, + 44, 34, 92,110, 34, 41, 10, 9, 83, 32, 61, 32,103,115,117, + 98, 40, 83, 44, 34, 92,110, 43, 34, 44, 34, 92,110, 34, 41, + 10, 32, 83, 32, 61, 32,117,110,109, 97,115,107, 40, 83, 41, + 10, 32,114,101,116,117,114,110, 32, 83, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/clean.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 45, 45, 32, 71,101,110,101,114, 97,116,101, 32, 98,105,110, + 100,105,110,103, 32, 99,111,100,101, 10, 45, 45, 32, 87,114, + 105,116,116,101,110, 32, 98,121, 32, 87, 97,108,100,101,109, + 97,114, 32, 67,101,108,101,115, 10, 45, 45, 32, 84,101, 67, + 71,114, 97,102, 47, 80, 85, 67, 45, 82,105,111, 10, 45, 45, + 32, 74,117,108, 32, 49, 57, 57, 56, 10, 45, 45, 32, 76, 97, + 115,116, 32,117,112,100, 97,116,101, 58, 32, 65,112,114, 32, + 50, 48, 48, 51, 10, 45, 45, 32, 36, 73,100, 58, 32, 36, 10, + 10, 10, 45, 45, 32, 84,104,105,115, 32, 99,111,100,101, 32, + 105,115, 32,102,114,101,101, 32,115,111,102,116,119, 97,114, + 101, 59, 32,121,111,117, 32, 99, 97,110, 32,114,101,100,105, + 115,116,114,105, 98,117,116,101, 32,105,116, 32, 97,110,100, + 47,111,114, 32,109,111,100,105,102,121, 32,105,116, 46, 10, + 45, 45, 32, 84,104,101, 32,115,111,102,116,119, 97,114,101, + 32,112,114,111,118,105,100,101,100, 32,104,101,114,101,117, + 110,100,101,114, 32,105,115, 32,111,110, 32, 97,110, 32, 34, + 97,115, 32,105,115, 34, 32, 98, 97,115,105,115, 44, 32, 97, + 110,100, 10, 45, 45, 32,116,104,101, 32, 97,117,116,104,111, + 114, 32,104, 97,115, 32,110,111, 32,111, 98,108,105,103, 97, + 116,105,111,110, 32,116,111, 32,112,114,111,118,105,100,101, + 32,109, 97,105,110,116,101,110, 97,110, 99,101, 44, 32,115, + 117,112,112,111,114,116, 44, 32,117,112,100, 97,116,101,115, + 44, 10, 45, 45, 32,101,110,104, 97,110, 99,101,109,101,110, + 116,115, 44, 32,111,114, 32,109,111,100,105,102,105, 99, 97, + 116,105,111,110,115, 46, 10, 10,102,117,110, 99,116,105,111, + 110, 32,112, 97,114,115,101, 95,101,120,116,114, 97, 40, 41, + 10, 10, 9,102,111,114, 32,107, 44,118, 32,105,110, 32,105, + 112, 97,105,114,115, 40, 95,101,120,116,114, 97, 95,112, 97, + 114, 97,109,101,116,101,114,115, 32,111,114, 32,123,125, 41, + 32,100,111, 10, 9, 9, 10, 9, 9,108,111, 99, 97,108, 32, + 98, 44,101, 44,110, 97,109,101, 44,118, 97,108,117,101, 32, + 61, 32,115,116,114,105,110,103, 46,102,105,110,100, 40,118, + 44, 32, 34, 94, 40, 91, 94, 61, 93, 42, 41, 61, 40, 46, 42, + 41, 36, 34, 41, 10, 9, 9,105,102, 32, 98, 32,116,104,101, + 110, 10, 9, 9, 9, 95,101,120,116,114, 97, 95,112, 97,114, + 97,109,101,116,101,114,115, 91,110, 97,109,101, 93, 32, 61, + 32,118, 97,108,117,101, 10, 9, 9,101,108,115,101, 10, 9, + 9, 9, 95,101,120,116,114, 97, 95,112, 97,114, 97,109,101, + 116,101,114,115, 91,118, 93, 32, 61, 32,116,114,117,101, 10, + 9, 9,101,110,100, 10, 9,101,110,100, 10,101,110,100, 10, + 10,102,117,110, 99,116,105,111,110, 32,100,111,105,116, 32, + 40, 41, 10, 9, 45, 45, 32,100,101,102,105,110,101, 32,112, + 97, 99,107, 97,103,101, 32,110, 97,109,101, 44, 32,105,102, + 32,110,111,116, 32,112,114,111,118,105,100,101,100, 10, 9, + 105,102, 32,110,111,116, 32,102,108, 97,103,115, 46,110, 32, + 116,104,101,110, 10, 9, 9,105,102, 32,102,108, 97,103,115, + 46,102, 32,116,104,101,110, 10, 9, 9, 9,102,108, 97,103, + 115, 46,110, 32, 61, 32,103,115,117, 98, 40,102,108, 97,103, + 115, 46,102, 44, 34, 37, 46, 46, 42, 36, 34, 44, 34, 34, 41, + 10, 9, 9, 9, 95, 44, 95, 44,102,108, 97,103,115, 46,110, + 32, 61, 32,115,116,114,105,110,103, 46,102,105,110,100, 40, + 102,108, 97,103,115, 46,110, 44, 32, 34, 40, 91, 94, 47, 92, + 92, 93, 42, 41, 36, 34, 41, 10, 9, 9,101,108,115,101, 10, + 9, 9, 9,101,114,114,111,114, 40, 34, 35,110,111, 32,112, + 97, 99,107, 97,103,101, 32,110, 97,109,101, 32,110,111,114, + 32,105,110,112,117,116, 32,102,105,108,101, 32,112,114,111, + 118,105,100,101,100, 34, 41, 10, 9, 9,101,110,100, 10, 9, + 101,110,100, 10, 10, 9, 45, 45, 32,112, 97,114,115,101, 32, + 116, 97, 98,108,101, 32,119,105,116,104, 32,101,120,116,114, + 97, 32,112, 97,114, 97,109,116,101,114,115, 10, 9,112, 97, + 114,115,101, 95,101,120,116,114, 97, 40, 41, 10, 10, 9, 45, + 45, 32,100,111, 32,116,104,105,115, 32, 97,102,116,101,114, + 32,115,101,116,116,105,110,103, 32,116,104,101, 32,112, 97, + 99,107, 97,103,101, 32,110, 97,109,101, 10, 9,105,102, 32, + 102,108, 97,103,115, 91, 39, 76, 39, 93, 32,116,104,101,110, + 10, 9, 9,100,111,102,105,108,101, 40,102,108, 97,103,115, + 91, 39, 76, 39, 93, 41, 10, 9,101,110,100, 10, 10, 9, 45, + 45, 32, 97,100,100, 32, 99,112,112,115,116,114,105,110,103, + 10, 9,105,102, 32,110,111,116, 32,102,108, 97,103,115, 91, + 39, 83, 39, 93, 32,116,104,101,110, 10, 9, 9, 95, 98, 97, + 115,105, 99, 91, 39,115,116,114,105,110,103, 39, 93, 32, 61, + 32, 39, 99,112,112,115,116,114,105,110,103, 39, 10, 9, 9, + 95, 98, 97,115,105, 99, 91, 39,115,116,100, 58, 58,115,116, + 114,105,110,103, 39, 93, 32, 61, 32, 39, 99,112,112,115,116, + 114,105,110,103, 39, 10, 9, 9, 95, 98, 97,115,105, 99, 95, + 99,116,121,112,101, 46, 99,112,112,115,116,114,105,110,103, + 32, 61, 32, 39, 99,111,110,115,116, 32, 99,104, 97,114, 42, + 39, 10, 9,101,110,100, 10, 10, 9, 45, 45, 32,112,114,111, + 99, 99,101,115,115, 32,112, 97, 99,107, 97,103,101, 10, 9, + 108,111, 99, 97,108, 32,112, 32, 32, 61, 32, 80, 97, 99,107, + 97,103,101, 40,102,108, 97,103,115, 46,110, 44,102,108, 97, + 103,115, 46,102, 41, 10, 10, 9,105,102, 32,102,108, 97,103, + 115, 46,112, 32,116,104,101,110, 10, 9, 9,114,101,116,117, + 114,110, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 32,111,110, + 108,121, 32,112, 97,114,115,101, 10, 9,101,110,100, 10, 10, + 9,105,102, 32,102,108, 97,103,115, 46,111, 32,116,104,101, + 110, 10, 9, 9,108,111, 99, 97,108, 32,115,116, 44,109,115, + 103, 32, 61, 32,119,114,105,116,101,116,111, 40,102,108, 97, + 103,115, 46,111, 41, 10, 9, 9,105,102, 32,110,111,116, 32, + 115,116, 32,116,104,101,110, 10, 9, 9, 9,101,114,114,111, + 114, 40, 39, 35, 39, 46, 46,109,115,103, 41, 10, 9, 9,101, + 110,100, 10, 9,101,110,100, 10, 10, 9,112, 58,100,101, 99, + 108,116,121,112,101, 40, 41, 10, 9,105,102, 32,102,108, 97, + 103,115, 46, 80, 32,116,104,101,110, 10, 9, 9,112, 58,112, + 114,105,110,116, 40, 41, 10, 9,101,108,115,101, 10, 9, 9, + 112, 58,112,114,101, 97,109, 98,108,101, 40, 41, 10, 9, 9, + 112, 58,115,117,112, 99,111,100,101, 40, 41, 10, 9, 9,112, + 58,114,101,103,105,115,116,101,114, 40, 41, 10, 9, 9,112, + 117,115,104, 40,112, 41, 10, 9, 9,112,111,115,116, 95,111, + 117,116,112,117,116, 95,104,111,111,107, 40,112, 41, 10, 9, + 9,112,111,112, 40, 41, 10, 9,101,110,100, 10, 10, 9,105, + 102, 32,102,108, 97,103,115, 46,111, 32,116,104,101,110, 10, + 9, 9,119,114,105,116,101,116,111, 40, 41, 10, 9,101,110, + 100, 10, 10, 9, 45, 45, 32,119,114,105,116,101, 32,104,101, + 97,100,101,114, 32,102,105,108,101, 10, 9,105,102, 32,110, + 111,116, 32,102,108, 97,103,115, 46, 80, 32,116,104,101,110, + 10, 9, 9,105,102, 32,102,108, 97,103,115, 46, 72, 32,116, + 104,101,110, 10, 9, 9, 9,108,111, 99, 97,108, 32,115,116, + 44,109,115,103, 32, 61, 32,119,114,105,116,101,116,111, 40, + 102,108, 97,103,115, 46, 72, 41, 10, 9, 9, 9,105,102, 32, + 110,111,116, 32,115,116, 32,116,104,101,110, 10, 9, 9, 9, + 9,101,114,114,111,114, 40, 39, 35, 39, 46, 46,109,115,103, + 41, 10, 9, 9, 9,101,110,100, 10, 9, 9, 9,112, 58,104, + 101, 97,100,101,114, 40, 41, 10, 9, 9, 9,119,114,105,116, + 101,116,111, 40, 41, 10, 9, 9,101,110,100, 10, 9,101,110, + 100, 10,101,110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: lua/tolua++/src/bin/lua/doit.lua"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + + { /* begin embedded lua code */ + int top = lua_gettop(tolua_S); + static unsigned char B[] = { + 10,108,111, 99, 97,108, 32,101,114,114, 44,109,115,103, 32, + 61, 32,112, 99, 97,108,108, 40,100,111,105,116, 41, 10,105, + 102, 32,110,111,116, 32,101,114,114, 32,116,104,101,110, 10, + 32,108,111, 99, 97,108, 32, 95, 44, 95, 44,108, 97, 98,101, + 108, 44,109,115,103, 32, 61, 32,115,116,114,102,105,110,100, + 40,109,115,103, 44, 34, 40, 46, 45, 58, 46, 45, 58, 37,115, + 42, 41, 40, 46, 42, 41, 34, 41, 10, 32,116,111,108,117, 97, + 95,101,114,114,111,114, 40,109,115,103, 44,108, 97, 98,101, + 108, 41, 10, 32,112,114,105,110,116, 40,100,101, 98,117,103, + 46,116,114, 97, 99,101, 98, 97, 99,107, 40, 41, 41, 10,101, + 110,100,32 + }; + tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua: embedded Lua code 23"); + lua_settop(tolua_S, top); + } /* end of embedded lua code */ + + tolua_endmodule(tolua_S); + return 1; +} + + +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + TOLUA_API int luaopen_tolua (lua_State* tolua_S) { + return tolua_tolua_open(tolua_S); +}; +#endif + diff --git a/lib/tolua++/src/bin/toluabind_default.h b/lib/tolua++/src/bin/toluabind_default.h new file mode 100644 index 000000000..c31a14875 --- /dev/null +++ b/lib/tolua++/src/bin/toluabind_default.h @@ -0,0 +1,8 @@ +/* +** Lua binding: tolua +** Generated automatically by tolua++-1.0.8pre2 on Tue Dec 13 01:43:55 2005. +*/ + +/* Exported function */ +TOLUA_API int tolua_tolua_open (lua_State* tolua_S); + 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..8258867b4 --- /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 + +#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..898f33dfc --- /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 "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..c486b271e --- /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 "tolua++.h" +#include "lauxlib.h" + +#include +#include + +/* 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)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)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)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)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)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)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)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)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)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..d00e7069b --- /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 "tolua++.h" +#include "tolua_event.h" +#include "lauxlib.h" + +#include +#include +#include +#include + + +/* Create metatable + * Create and register new metatable +*/ +static int tolua_newmetatable (lua_State* L, 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: */ +} + +/* 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..639414755 --- /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 "tolua++.h" +#include "lauxlib.h" + +#include + +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..542ca67d1 --- /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 "tolua++.h" + +#include +#include + +TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def) +{ + return lua_gettop(L) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + 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 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {AB745E71-04B2-454F-A806-A0D553DAE08C} + tolualib + + + + Application + true + MultiByte + + + StaticLibrary + false + true + MultiByte + + + + + + + + + + + + + tolua++ + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + true + true + ../../include;C:\Program Files (x86)\Lua\5.1\include;%(AdditionalIncludeDirectories) + + + true + true + true + C:\Program Files (x86)\Lua\5.1\lib + lua51.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + \ 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 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + \ 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 @@ + + + \ 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + 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 @@ + + + + + withLua50_Debug + Win32 + + + withLua50_Release + Win32 + + + withLua51_Debug + Win32 + + + withLua51_Release + Win32 + + + + {71891C1A-E328-4258-AC3F-6F9698C6D8B4} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + $(Configuration)\ + $(Configuration)\ + true + $(Configuration)\ + $(Configuration)\ + false + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + lua50.lib;%(AdditionalDependencies) + ..\..\bin\tolua++_d.exe + ..\..\lib;%(AdditionalLibraryDirectories) + true + $(OutDir)tolua++.pdb + Console + MachineX86 + + + + + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Level3 + ProgramDatabase + + + lua50.lib;%(AdditionalDependencies) + ..\..\bin\tolua++.exe + ..\..\lib;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + Disabled + ..\..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + Lua5.1.lib;%(AdditionalDependencies) + ..\..\bin\tolua++_d.exe + ..\..\lib;%(AdditionalLibraryDirectories) + true + $(OutDir)tolua++.pdb + Console + MachineX86 + + + + + ..\..\include;C:\Program Files (x86)\Lua\5.1\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + + + Level3 + ProgramDatabase + + + lua5.1.lib;%(AdditionalDependencies) + ..\..\bin\tolua++.exe + ..\..\lib;C:\Program Files (x86)\Lua\5.1\lib;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + + + + + + + + + + + + + + \ 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 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + + + ソース ファイル + + + \ 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 @@ + + + \ No newline at end of file -- cgit v1.2.3 From 16435995a55f142538228100d61d2445ce6bb851 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 24 Nov 2013 17:33:47 +0000 Subject: Moved SQLite, LuaExpat, and MD5 to /lib --- lib/luaexpat/lxplib.c | 599 + lib/luaexpat/lxplib.h | 24 + lib/md5/md5.cpp | 369 + lib/md5/md5.h | 93 + lib/sqlite/lsqlite3.c | 2175 + lib/sqlite/sqlite3.c | 138114 +++++++++++++++++++++++++++++++++++++++++++++++ lib/sqlite/sqlite3.h | 7174 +++ lib/sqlite/urls.txt | 9 + 8 files changed, 148557 insertions(+) create mode 100644 lib/luaexpat/lxplib.c create mode 100644 lib/luaexpat/lxplib.h create mode 100644 lib/md5/md5.cpp create mode 100644 lib/md5/md5.h create mode 100644 lib/sqlite/lsqlite3.c create mode 100644 lib/sqlite/sqlite3.c create mode 100644 lib/sqlite/sqlite3.h create mode 100644 lib/sqlite/urls.txt (limited to 'lib') diff --git a/lib/luaexpat/lxplib.c b/lib/luaexpat/lxplib.c new file mode 100644 index 000000000..e26343ce9 --- /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 +#include +#include + +#include "expat.h" + +#include "lua.h" +#include "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 + +#ifndef _WIN32 + #include +#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 +#include + + +// 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..4c81b5878 --- /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 * +* Author : Doug Currie * +* 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 +#include +#include + +#define LUA_LIB +#include "lua.h" +#include "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 +#endif +#ifdef HAVE_INTTYPES_H +#include +#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 +#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 /* 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 +** Fossil configuration management +** system. ^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. +** +**

+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** 
)^ +** +** ^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: +** +**
    +**
  • The application must insure that the 1st parameter to sqlite3_exec() +** is a valid and open [database connection]. +**
  • The application must not close [database connection] specified by +** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not modify the SQL statement text passed into +** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
+*/ +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 +**
    +**
  • [SQLITE_LOCK_NONE], +**
  • [SQLITE_LOCK_SHARED], +**
  • [SQLITE_LOCK_RESERVED], +**
  • [SQLITE_LOCK_PENDING], or +**
  • [SQLITE_LOCK_EXCLUSIVE]. +**
+** 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: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
+** +** 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. +**
    +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
  • [[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. +** +**
+*/ +#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: +** +**
    +**
  • [SQLITE_OPEN_MAIN_DB] +**
  • [SQLITE_OPEN_MAIN_JOURNAL] +**
  • [SQLITE_OPEN_TEMP_DB] +**
  • [SQLITE_OPEN_TEMP_JOURNAL] +**
  • [SQLITE_OPEN_TRANSIENT_DB] +**
  • [SQLITE_OPEN_SUBJOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] +**
  • [SQLITE_OPEN_WAL] +**
)^ +** +** 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: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** 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 not 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: +** +**
    +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED +**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE +**
+** +** 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. +** +**
+** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
+**
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.
+** +** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
+**
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.
+** +** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
+**
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.
+** +** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
+**
^(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.
+** +** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
+**
^(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.
+** +** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
+**
^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: +**
    +**
  • [sqlite3_memory_used()] +**
  • [sqlite3_memory_highwater()] +**
  • [sqlite3_soft_heap_limit64()] +**
  • [sqlite3_status()] +**
)^ +** ^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. +**
+** +** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
+**
^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.
+** +** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
+**
^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.
+** +** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
+**
^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.
+** +** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
+**
^(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].
+** +** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
+**
^(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].
+** +** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
+**
^(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 +** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.)^
+** +** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
+**
^(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.
+** +** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
+**
^(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.)^
+** +** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
+**
^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.
+** +** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI +**
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]]
SQLITE_CONFIG_COVERING_INDEX_SCAN +**
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]] +**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE +**
These options are obsolete and should not be used by new code. +** They are retained for backwards compatibility but are now no-ops. +**
+** +** [[SQLITE_CONFIG_SQLLOG]] +**
SQLITE_CONFIG_SQLLOG +**
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. +** +*/ +#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. +** +**
+**
SQLITE_DBCONFIG_LOOKASIDE
+**
^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].)^
+** +**
SQLITE_DBCONFIG_ENABLE_FKEY
+**
^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.
+** +**
SQLITE_DBCONFIG_ENABLE_TRIGGER
+**
^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.
+** +**
+*/ +#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 +** +** CorruptionFollowingBusyError 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 result table 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: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** 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: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
)^ +** +** ^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: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** 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: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** 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:)^ +** +**
+** ^(
[SQLITE_OPEN_READONLY]
+**
The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE]
+**
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.
)^ +** +** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
+**
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().
)^ +**
+** +** 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()]]

URI Filenames

+** +** ^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: +** +**
    +**
  • vfs: ^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(). +** +**
  • mode: ^(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(). +** +**
  • cache: ^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. +**
+** +** ^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]]

URI filename examples

+** +** +**
URI filenames Results +**
file:data.db +** Open the file "data.db" in the current directory. +**
file:/home/fred/data.db
+** file:///home/fred/data.db
+** file://localhost/home/fred/data.db
+** Open the database file "/home/fred/data.db". +**
file://darkstar/home/fred/data.db +** An error. "darkstar" is not a recognized authority. +**
+** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db +** 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. +**
file:data.db?mode=ro&cache=private +** 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. +**
file:/home/fred/data.db?vfs=unix-nolock +** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". +**
file:data.db?mode=readonly +** An error. "readonly" is not a valid option for the "mode" parameter. +**
+** +** ^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. +** +** Note to Windows users: 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(). +** +** Note to Windows Runtime users: 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: +** +**
    +**
  1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
  2. Bind values to [host parameters] using the sqlite3_bind_*() +** interfaces. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+** +** 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_NAME there is a +** [limits | hard upper bound] +** set at compile-time by a C preprocessor macro called +** [limits | SQLITE_MAX_NAME]. +** (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]. +** +**
+** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
+**
The maximum size of any string or BLOB or table row, in bytes.
)^ +** +** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
+**
The maximum length of an SQL statement, in bytes.
)^ +** +** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
+**
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.
)^ +** +** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
+**
The maximum depth of the parse tree on any expression.
)^ +** +** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
+**
The maximum number of terms in a compound SELECT statement.
)^ +** +** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
+**
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.
)^ +** +** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
+**
The maximum number of arguments on a function.
)^ +** +** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
+**
The maximum number of [ATTACH | attached databases].)^
+** +** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] +** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
+**
The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
)^ +** +** [[SQLITE_LIMIT_VARIABLE_NUMBER]] +** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
+**
The maximum index number of any [parameter] in an SQL statement.)^ +** +** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
+**
The maximum depth of recursion for triggers.
)^ +**
+*/ +#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 including +** 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: +** +**
    +**
  1. +** ^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. +**
  2. +** +**
  3. +** ^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. +**
  4. +** +**
  5. +** ^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 +**
  6. +**
+*/ +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: +** +**
+**    SELECT eval('DELETE FROM t1') FROM t2;
+** 
+** +** 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: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** 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 bytes 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. +** +** Goofy Interface Alert: 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: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
)^ +** +** 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: +** +**
+** +**
Internal
Type
Requested
Type
Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is NULL pointer +**
NULL BLOB Result is NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as INTEGER->TEXT +**
FLOAT INTEGER Convert from float to integer +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB Same as FLOAT->TEXT +**
TEXT INTEGER Use atoi() +**
TEXT FLOAT Use atof() +**
TEXT BLOB No change +**
BLOB INTEGER Convert to TEXT then use atoi() +**
BLOB FLOAT Convert to TEXT then use atof() +**
BLOB TEXT Add a zero terminator if needed +**
+**
)^ +** +** 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: +** +**
    +**
  • 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.
  • +**
  • 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.
  • +**
  • 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.
  • +**
+** +** ^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: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** 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 not 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: +**
    +**
  • [SQLITE_UTF8], +**
  • [SQLITE_UTF16LE], +**
  • [SQLITE_UTF16BE], +**
  • [SQLITE_UTF16], or +**
  • [SQLITE_UTF16_ALIGNED]. +**
)^ +** ^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: +** +**
    +**
  1. If A==B then B==A. +**
  2. If A==B and B==C then A==C. +**
  3. If A<B THEN B>A. +**
  4. If A<B and B<C then A<C. +**
+** +** 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 not 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. +** +** Note to Windows Runtime users: 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: +** +**
+** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
+**       TemporaryFolder->Path->Data();
+** char zPathBuf[MAX_PATH + 1];
+** memset(zPathBuf, 0, sizeof(zPathBuf));
+** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
+**       NULL, NULL);
+** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
+** 
+*/ +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: +** +**
    +**
  • The soft heap limit is set to zero. +**
  • 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. +**
  • An alternative page cache implementation is specified using +** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). +**
  • The page cache allocates from its own memory pool supplied +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than +** from the heap. +**
)^ +** +** 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. +** +** ^(
+** +**
Parameter Output
Type
Description +** +**
5th const char* Data type +**
6th const char* Name of default collation sequence +**
7th int True if column has a NOT NULL constraint +**
8th int True if column is part of the PRIMARY KEY +**
9th int True if column is [AUTOINCREMENT] +**
+**
)^ +** +** ^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: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
)^ +** +** ^(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: +** +**
+**    int xEntryPoint(
+**      sqlite3 *db,
+**      const char **pzErrMsg,
+**      const struct sqlite3_api_routines *pThunk
+**    );
+** 
)^ +** +** 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: +** +**
column OP expr
+** +** where OP is =, <, <=, >, or >=.)^ ^(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: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
+** 
)^ +** +** ^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: +** +**
    +**
  • SQLITE_MUTEX_PTHREADS +**
  • SQLITE_MUTEX_W32 +**
  • SQLITE_MUTEX_NOOP +**
)^ +** +** ^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: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_MEM2 +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_LRU2 +**
)^ +** +** ^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): +** +**
    +**
  • [sqlite3_mutex_alloc()]
  • +**
  • [sqlite3_mutex_free()]
  • +**
  • [sqlite3_mutex_enter()]
  • +**
  • [sqlite3_mutex_try()]
  • +**
  • [sqlite3_mutex_leave()]
  • +**
  • [sqlite3_mutex_held()]
  • +**
  • [sqlite3_mutex_notheld()]
  • +**
)^ +** +** 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()]. +** +**
+** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
+**
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].
)^ +** +** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
+**
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.
)^ +** +** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
+**
This parameter records the number of separate memory allocations +** currently checked out.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
+**
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.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
+**
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.
)^ +** +** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
+**
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.
)^ +** +** [[SQLITE_STATUS_SCRATCH_USED]] ^(
SQLITE_STATUS_SCRATCH_USED
+**
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.
)^ +** +** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
+**
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. +**
)^ +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
SQLITE_STATUS_SCRATCH_SIZE
+**
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.
)^ +** +** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
+**
This parameter records the deepest parser stack. It is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ +**
+** +** 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. +** +**
+** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
+**
This parameter returns the number of lookaside memory slots currently +** checked out.
)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
+**
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]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
+**
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]] +** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
+**
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]] ^(
SQLITE_DBSTATUS_CACHE_USED
+**
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]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
+**
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]] ^(
SQLITE_DBSTATUS_STMT_USED
+**
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. +**
+** +** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
+**
This parameter returns the number of pager cache hits that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
+**
This parameter returns the number of pager cache misses that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** is always 0. +**
+** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
+**
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. +**
+**
+*/ +#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: +** +**
+** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
+**
^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.
+** +** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
+**
^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.
+** +** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
+**
^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.
+**
+*/ +#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: +** +** +**
createFlag Behavior when page is not already in cache +**
0 Do not allocate a new page. Return NULL. +**
1 Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +**
2 Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. +**
+** +** ^(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: +**
    +**
  1. sqlite3_backup_init() is called once to initialize the +** backup, +**
  2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
  3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
)^ +** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** [[sqlite3_backup_init()]] sqlite3_backup_init() +** +** ^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()]] sqlite3_backup_step() +** +** ^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 +**
    +**
  1. the destination database was opened read-only, or +**
  2. the destination database is using write-ahead-log journaling +** and the destination and source page sizes differ, or +**
  3. the destination database is an in-memory database and the +** destination and source page sizes differ. +**
)^ +** +** ^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()]] sqlite3_backup_finish() +** +** 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()]] +** sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** +** ^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. +** +** Concurrent Usage of Database Handles +** +** ^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. +** +** Callback Invocation Details +** +** 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. +** +** Deadlock Detection +** +** 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. +** +** The "DROP TABLE" Exception +** +** 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: +** +**
+**
SQLITE_CHECKPOINT_PASSIVE
+** 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. +** +**
SQLITE_CHECKPOINT_FULL
+** 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. +** +**
SQLITE_CHECKPOINT_RESTART
+** 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. +**
+** +** 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. +** +**
+**
SQLITE_VTAB_CONSTRAINT_SUPPORT +**
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. +**
+*/ +#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 WHERE 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 +#include +#include +#include +#include + +/* +** 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 */ + +/* +** 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 +#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 " IN (, ...)". +** Expr.x.pSelect is used if the expression is a sub-select or an expression of +** the form " 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 " IN ( IN (