summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/arm32-neon-salsa2012-asm/README.md6
-rw-r--r--ext/arm32-neon-salsa2012-asm/salsa2012.h23
-rw-r--r--ext/arm32-neon-salsa2012-asm/salsa2012.s2231
-rw-r--r--ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dllbin1795952 -> 0 bytes
-rw-r--r--ext/bin/tap-windows-ndis5/x64/zttap200.catbin10549 -> 0 bytes
-rw-r--r--ext/bin/tap-windows-ndis5/x64/zttap200.inf79
-rw-r--r--ext/bin/tap-windows-ndis5/x64/zttap200.sysbin31896 -> 0 bytes
-rw-r--r--ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dllbin1629040 -> 0 bytes
-rw-r--r--ext/bin/tap-windows-ndis5/x86/zttap200.catbin10496 -> 0 bytes
-rw-r--r--ext/bin/tap-windows-ndis5/x86/zttap200.inf76
-rw-r--r--ext/bin/tap-windows-ndis5/x86/zttap200.sysbin28824 -> 0 bytes
-rw-r--r--ext/bin/tap-windows-ndis6/certutil.exebin0 -> 903168 bytes
-rw-r--r--ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msibin1453056 -> 2056704 bytes
-rw-r--r--ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msibin1070080 -> 1673728 bytes
-rw-r--r--ext/bin/tap-windows-ndis6/zttap300.cerbin0 -> 1321 bytes
-rw-r--r--ext/ed25519-amd64-asm/batch.c94
-rw-r--r--ext/ed25519-amd64-asm/choose_t.s1565
-rw-r--r--ext/ed25519-amd64-asm/consts.s39
-rw-r--r--ext/ed25519-amd64-asm/fe25519.h64
-rw-r--r--ext/ed25519-amd64-asm/fe25519_add.s189
-rw-r--r--ext/ed25519-amd64-asm/fe25519_freeze.s322
-rw-r--r--ext/ed25519-amd64-asm/fe25519_getparity.c8
-rw-r--r--ext/ed25519-amd64-asm/fe25519_invert.c60
-rw-r--r--ext/ed25519-amd64-asm/fe25519_iseq.c14
-rw-r--r--ext/ed25519-amd64-asm/fe25519_iszero.c12
-rw-r--r--ext/ed25519-amd64-asm/fe25519_mul.s865
-rw-r--r--ext/ed25519-amd64-asm/fe25519_neg.c8
-rw-r--r--ext/ed25519-amd64-asm/fe25519_pack.c13
-rw-r--r--ext/ed25519-amd64-asm/fe25519_pow2523.c55
-rw-r--r--ext/ed25519-amd64-asm/fe25519_setint.c9
-rw-r--r--ext/ed25519-amd64-asm/fe25519_square.s639
-rw-r--r--ext/ed25519-amd64-asm/fe25519_sub.s189
-rw-r--r--ext/ed25519-amd64-asm/fe25519_unpack.c11
-rw-r--r--ext/ed25519-amd64-asm/ge25519.h95
-rw-r--r--ext/ed25519-amd64-asm/ge25519_add.c8
-rw-r--r--ext/ed25519-amd64-asm/ge25519_add_p1p1.s4554
-rw-r--r--ext/ed25519-amd64-asm/ge25519_base.c7
-rw-r--r--ext/ed25519-amd64-asm/ge25519_base_niels.data1536
-rw-r--r--ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data768
-rw-r--r--ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data96
-rw-r--r--ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s2975
-rw-r--r--ext/ed25519-amd64-asm/ge25519_double.c8
-rw-r--r--ext/ed25519-amd64-asm/ge25519_double_scalarmult.c102
-rw-r--r--ext/ed25519-amd64-asm/ge25519_isneutral.c9
-rw-r--r--ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c102
-rw-r--r--ext/ed25519-amd64-asm/ge25519_nielsadd2.s5791
-rw-r--r--ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s3072
-rw-r--r--ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s2236
-rw-r--r--ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s2926
-rw-r--r--ext/ed25519-amd64-asm/ge25519_pack.c13
-rw-r--r--ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s3662
-rw-r--r--ext/ed25519-amd64-asm/ge25519_scalarmult_base.c68
-rw-r--r--ext/ed25519-amd64-asm/ge25519_unpackneg.c60
-rw-r--r--ext/ed25519-amd64-asm/heap_rootreplaced.s476
-rw-r--r--ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s416
-rw-r--r--ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s436
-rw-r--r--ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s456
-rw-r--r--ext/ed25519-amd64-asm/hram.c16
-rw-r--r--ext/ed25519-amd64-asm/hram.h8
-rw-r--r--ext/ed25519-amd64-asm/implementors5
-rw-r--r--ext/ed25519-amd64-asm/index_heap.c58
-rw-r--r--ext/ed25519-amd64-asm/index_heap.h31
-rw-r--r--ext/ed25519-amd64-asm/keypair.c25
-rw-r--r--ext/ed25519-amd64-asm/open.c49
-rw-r--r--ext/ed25519-amd64-asm/sc25519.h66
-rw-r--r--ext/ed25519-amd64-asm/sc25519_add.s232
-rw-r--r--ext/ed25519-amd64-asm/sc25519_barrett.s1188
-rw-r--r--ext/ed25519-amd64-asm/sc25519_from32bytes.c55
-rw-r--r--ext/ed25519-amd64-asm/sc25519_from64bytes.c7
-rw-r--r--ext/ed25519-amd64-asm/sc25519_from_shortsc.c9
-rw-r--r--ext/ed25519-amd64-asm/sc25519_iszero.c10
-rw-r--r--ext/ed25519-amd64-asm/sc25519_lt.s131
-rw-r--r--ext/ed25519-amd64-asm/sc25519_mul.c12
-rw-r--r--ext/ed25519-amd64-asm/sc25519_mul_shortsc.c9
-rw-r--r--ext/ed25519-amd64-asm/sc25519_slide.c49
-rw-r--r--ext/ed25519-amd64-asm/sc25519_sub_nored.s142
-rw-r--r--ext/ed25519-amd64-asm/sc25519_to32bytes.c8
-rw-r--r--ext/ed25519-amd64-asm/sc25519_window4.c27
-rw-r--r--ext/ed25519-amd64-asm/sign.c165
-rw-r--r--ext/ed25519-amd64-asm/ull4_mul.s716
-rw-r--r--ext/http-parser/http_parser.c11
-rw-r--r--ext/http-parser/http_parser.h72
-rw-r--r--ext/installfiles/linux/zerotier-containerized/Dockerfile20
-rwxr-xr-xext/installfiles/linux/zerotier-containerized/main.sh10
-rw-r--r--ext/installfiles/mac-update/updater.tmpl.sh49
-rwxr-xr-xext/installfiles/mac/ZeroTier One.pkgproj141
-rwxr-xr-xext/installfiles/mac/launch.sh6
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist59
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier Onebin152736 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo1
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icnsbin125598 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf13
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.stringsbin92 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nibbin25269 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nibbin3616 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources187
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/LICENSE25
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj489
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout41
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstatebin46675 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings10
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstatebin27811 -> 0 bytes
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings10
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h18
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m159
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h20
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m168
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h21
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m128
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h18
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m28
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h11
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m31
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h31
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m150
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h31
-rwxr-xr-xext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m233
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h26
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m108
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h21
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m53
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h17
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m97
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h43
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m211
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h9
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m48
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h7
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h15
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m68
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h20
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m41
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h20
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m93
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h49
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m206
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h23
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m94
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h10
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m51
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist39
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch15
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h13
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m54
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf13
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings2
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib3404
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib44
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/main.m14
-rw-r--r--ext/installfiles/mac/mac-ui-macgap1-wrapper/src/README.md6
-rwxr-xr-xext/installfiles/mac/postinst.sh23
-rwxr-xr-xext/installfiles/mac/preinst.sh13
-rw-r--r--ext/installfiles/mac/ui/Makefile6
-rw-r--r--ext/installfiles/mac/ui/README.md10
-rw-r--r--ext/installfiles/mac/ui/ZeroTierNetwork.jsx74
-rw-r--r--ext/installfiles/mac/ui/ZeroTierNode.jsx158
-rw-r--r--ext/installfiles/mac/ui/index.html58
-rw-r--r--ext/installfiles/mac/ui/main.js51
-rw-r--r--ext/installfiles/mac/ui/react.min.js15
-rw-r--r--ext/installfiles/mac/ui/simpleajax.min.js2
-rw-r--r--ext/installfiles/mac/ui/zerotier.css199
-rw-r--r--ext/installfiles/mac/ui/ztui.min.js1
-rwxr-xr-xext/installfiles/mac/uninstall.sh12
-rw-r--r--ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip64
-rw-r--r--ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip64
-rw-r--r--ext/installfiles/windows/ZeroTier One.aip870
-rw-r--r--ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps14
-rw-r--r--ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec8
-rw-r--r--ext/json-parser/AUTHORS20
-rw-r--r--ext/json-parser/LICENSE26
-rw-r--r--ext/json-parser/README.md97
-rw-r--r--ext/json-parser/json.c1012
-rw-r--r--ext/json-parser/json.h283
-rw-r--r--ext/json/LICENSE.MIT17
-rw-r--r--ext/json/README.md566
-rw-r--r--ext/json/json.hpp15313
-rw-r--r--ext/librethinkdbxx/.travis.yml11
-rw-r--r--ext/librethinkdbxx/COPYRIGHT16
-rw-r--r--ext/librethinkdbxx/Makefile126
-rw-r--r--ext/librethinkdbxx/README.md72
-rw-r--r--ext/librethinkdbxx/reql/add_docs.py80
-rw-r--r--ext/librethinkdbxx/reql/gen.py33
-rw-r--r--ext/librethinkdbxx/reql/python_docs.txt189
-rw-r--r--ext/librethinkdbxx/reql/ql2.proto843
-rw-r--r--ext/librethinkdbxx/src/connection.cc434
-rw-r--r--ext/librethinkdbxx/src/connection.h59
-rw-r--r--ext/librethinkdbxx/src/connection_p.h133
-rw-r--r--ext/librethinkdbxx/src/cursor.cc223
-rw-r--r--ext/librethinkdbxx/src/cursor.h76
-rw-r--r--ext/librethinkdbxx/src/cursor_p.h29
-rw-r--r--ext/librethinkdbxx/src/datum.cc449
-rw-r--r--ext/librethinkdbxx/src/datum.h287
-rw-r--r--ext/librethinkdbxx/src/error.h46
-rw-r--r--ext/librethinkdbxx/src/exceptions.h13
-rw-r--r--ext/librethinkdbxx/src/json.cc62
-rw-r--r--ext/librethinkdbxx/src/json_p.h19
-rw-r--r--ext/librethinkdbxx/src/rapidjson-config.h8
-rw-r--r--ext/librethinkdbxx/src/rapidjson/allocators.h263
-rw-r--r--ext/librethinkdbxx/src/rapidjson/document.h2575
-rw-r--r--ext/librethinkdbxx/src/rapidjson/encodedstream.h299
-rw-r--r--ext/librethinkdbxx/src/rapidjson/encodings.h716
-rw-r--r--ext/librethinkdbxx/src/rapidjson/error/en.h74
-rw-r--r--ext/librethinkdbxx/src/rapidjson/error/error.h155
-rw-r--r--ext/librethinkdbxx/src/rapidjson/filereadstream.h99
-rw-r--r--ext/librethinkdbxx/src/rapidjson/filewritestream.h104
-rw-r--r--ext/librethinkdbxx/src/rapidjson/fwd.h151
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/biginteger.h290
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/diyfp.h258
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/dtoa.h245
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/ieee754.h78
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/itoa.h304
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/meta.h181
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/pow10.h55
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/regex.h701
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/stack.h230
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/strfunc.h55
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/strtod.h269
-rw-r--r--ext/librethinkdbxx/src/rapidjson/internal/swap.h46
-rw-r--r--ext/librethinkdbxx/src/rapidjson/istreamwrapper.h115
-rw-r--r--ext/librethinkdbxx/src/rapidjson/memorybuffer.h70
-rw-r--r--ext/librethinkdbxx/src/rapidjson/memorystream.h71
-rw-r--r--ext/librethinkdbxx/src/rapidjson/msinttypes/inttypes.h316
-rw-r--r--ext/librethinkdbxx/src/rapidjson/msinttypes/stdint.h300
-rw-r--r--ext/librethinkdbxx/src/rapidjson/ostreamwrapper.h81
-rw-r--r--ext/librethinkdbxx/src/rapidjson/pointer.h1358
-rw-r--r--ext/librethinkdbxx/src/rapidjson/prettywriter.h249
-rw-r--r--ext/librethinkdbxx/src/rapidjson/rapidjson.h615
-rw-r--r--ext/librethinkdbxx/src/rapidjson/reader.h1879
-rw-r--r--ext/librethinkdbxx/src/rapidjson/schema.h2006
-rw-r--r--ext/librethinkdbxx/src/rapidjson/stream.h179
-rw-r--r--ext/librethinkdbxx/src/rapidjson/stringbuffer.h117
-rw-r--r--ext/librethinkdbxx/src/rapidjson/writer.h609
-rw-r--r--ext/librethinkdbxx/src/term.cc285
-rw-r--r--ext/librethinkdbxx/src/term.h592
-rw-r--r--ext/librethinkdbxx/src/types.cc47
-rw-r--r--ext/librethinkdbxx/src/types.h53
-rw-r--r--ext/librethinkdbxx/src/utils.cc153
-rw-r--r--ext/librethinkdbxx/src/utils.h19
-rw-r--r--ext/lz4/lz4.c1516
-rw-r--r--ext/lz4/lz4.h360
-rw-r--r--ext/miniupnpc/Changelog.txt16
-rw-r--r--ext/miniupnpc/LICENSE2
-rw-r--r--ext/miniupnpc/MANIFEST.in5
-rw-r--r--ext/miniupnpc/README7
-rw-r--r--ext/miniupnpc/apiversions.txt172
-rw-r--r--ext/miniupnpc/connecthostport.c14
-rwxr-xr-xext/miniupnpc/external-ip.sh4
-rw-r--r--ext/miniupnpc/minihttptestserver.c659
-rw-r--r--ext/miniupnpc/minisoap.c14
-rw-r--r--ext/miniupnpc/minissdpc.c67
-rw-r--r--ext/miniupnpc/miniupnpc.c2
-rw-r--r--ext/miniupnpc/miniupnpc.h2
-rw-r--r--ext/miniupnpc/miniupnpcmodule.c16
-rw-r--r--ext/miniupnpc/miniwget.c30
-rw-r--r--ext/miniupnpc/minixml.c11
-rw-r--r--ext/miniupnpc/minixmlvalid.c1
-rw-r--r--ext/miniupnpc/portlistingparse.c6
-rw-r--r--ext/miniupnpc/pymoduletest.py88
-rw-r--r--ext/miniupnpc/receivedata.c4
-rw-r--r--ext/miniupnpc/testdesc/linksys_WAG200G_desc.values14
-rw-r--r--ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml110
-rw-r--r--ext/miniupnpc/testdesc/new_LiveBox_desc.values20
-rw-r--r--ext/miniupnpc/testdesc/new_LiveBox_desc.xml90
-rw-r--r--ext/miniupnpc/testigddescparse.c187
-rw-r--r--ext/miniupnpc/testminiwget.c55
-rwxr-xr-xext/miniupnpc/testminiwget.sh96
-rw-r--r--ext/miniupnpc/testminixml.c89
-rw-r--r--ext/miniupnpc/testportlistingparse.c151
-rw-r--r--ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue3
-rw-r--r--ext/miniupnpc/testreplyparse/DeletePortMapping.xml6
-rw-r--r--ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue2
-rw-r--r--ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml2
-rw-r--r--ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue3
-rw-r--r--ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml3
-rw-r--r--ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue5
-rw-r--r--ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml2
-rw-r--r--ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue1
-rw-r--r--ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml1
-rw-r--r--ext/miniupnpc/testreplyparse/readme.txt7
-rwxr-xr-xext/miniupnpc/testupnpigd.py84
-rw-r--r--ext/miniupnpc/testupnpreplyparse.c96
-rwxr-xr-xext/miniupnpc/testupnpreplyparse.sh14
-rw-r--r--ext/miniupnpc/upnpc.c82
-rw-r--r--ext/miniupnpc/upnpcommands.c93
-rw-r--r--ext/miniupnpc/upnpreplyparse.c16
-rw-r--r--ext/misc/linux-old-glibc-compat.c18
-rw-r--r--ext/x64-salsa2012-asm/README.md6
-rw-r--r--ext/x64-salsa2012-asm/salsa2012.h16
-rw-r--r--ext/x64-salsa2012-asm/salsa2012.s4488
290 files changed, 74865 insertions, 18920 deletions
diff --git a/ext/arm32-neon-salsa2012-asm/README.md b/ext/arm32-neon-salsa2012-asm/README.md
new file mode 100644
index 00000000..54fc6f5f
--- /dev/null
+++ b/ext/arm32-neon-salsa2012-asm/README.md
@@ -0,0 +1,6 @@
+ARM NEON (32-bit) ASM implementation of Salsa20/12
+======
+
+This is from [supercop](http://bench.cr.yp.to/supercop.html) and was originally written by Daniel J. Bernstein. Code is in the public domain like the rest of Salsa20. It's much faster than the naive implementation.
+
+It's included automatically in 32-bit Linux ARM builds. It likely will not work on 64-bit ARM, so it'll need to be ported at least. That will unfortunately keep it out of mobile versions for now since those are all going 64-bit.
diff --git a/ext/arm32-neon-salsa2012-asm/salsa2012.h b/ext/arm32-neon-salsa2012-asm/salsa2012.h
new file mode 100644
index 00000000..95b247f2
--- /dev/null
+++ b/ext/arm32-neon-salsa2012-asm/salsa2012.h
@@ -0,0 +1,23 @@
+#ifndef ZT_SALSA2012_ARM32NEON_ASM
+#define ZT_SALSA2012_ARM32NEON_ASM
+
+#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
+#include <sys/auxv.h>
+#include <asm/hwcap.h>
+#define zt_arm_has_neon() ((getauxval(AT_HWCAP) & HWCAP_NEON) != 0)
+#else
+#define zt_arm_has_neon() (true)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ciphertext buffer, message/NULL, length, nonce (8 bytes), key (32 bytes)
+extern int zt_salsa2012_armneon3_xor(unsigned char *c,const unsigned char *m,unsigned long long len,const unsigned char *n,const unsigned char *k);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/arm32-neon-salsa2012-asm/salsa2012.s b/ext/arm32-neon-salsa2012-asm/salsa2012.s
new file mode 100644
index 00000000..9e5989cd
--- /dev/null
+++ b/ext/arm32-neon-salsa2012-asm/salsa2012.s
@@ -0,0 +1,2231 @@
+
+# qhasm: int32 input_0
+
+# qhasm: int32 input_1
+
+# qhasm: int32 input_2
+
+# qhasm: int32 input_3
+
+# qhasm: stack32 input_4
+
+# qhasm: stack32 input_5
+
+# qhasm: stack32 input_6
+
+# qhasm: stack32 input_7
+
+# qhasm: int32 caller_r4
+
+# qhasm: int32 caller_r5
+
+# qhasm: int32 caller_r6
+
+# qhasm: int32 caller_r7
+
+# qhasm: int32 caller_r8
+
+# qhasm: int32 caller_r9
+
+# qhasm: int32 caller_r10
+
+# qhasm: int32 caller_r11
+
+# qhasm: int32 caller_r14
+
+# qhasm: reg128 caller_q4
+
+# qhasm: reg128 caller_q5
+
+# qhasm: reg128 caller_q6
+
+# qhasm: reg128 caller_q7
+
+# qhasm: startcode
+.fpu neon
+.text
+
+# qhasm: constant sigma:
+.align 2
+sigma:
+
+# qhasm: const32 1634760805
+.word 1634760805
+
+# qhasm: const32 857760878
+.word 857760878
+
+# qhasm: const32 2036477234
+.word 2036477234
+
+# qhasm: const32 1797285236
+.word 1797285236
+
+# qhasm: int128 abab
+
+# qhasm: int128 diag0
+
+# qhasm: int128 diag1
+
+# qhasm: int128 diag2
+
+# qhasm: int128 diag3
+
+# qhasm: int128 a0
+
+# qhasm: int128 a1
+
+# qhasm: int128 a2
+
+# qhasm: int128 a3
+
+# qhasm: int128 b0
+
+# qhasm: int128 b1
+
+# qhasm: int128 b2
+
+# qhasm: int128 b3
+
+# qhasm: int128 next_diag0
+
+# qhasm: int128 next_diag1
+
+# qhasm: int128 next_diag2
+
+# qhasm: int128 next_diag3
+
+# qhasm: int128 next_a0
+
+# qhasm: int128 next_a1
+
+# qhasm: int128 next_a2
+
+# qhasm: int128 next_a3
+
+# qhasm: int128 next_b0
+
+# qhasm: int128 next_b1
+
+# qhasm: int128 next_b2
+
+# qhasm: int128 next_b3
+
+# qhasm: int128 x0x5x10x15
+
+# qhasm: int128 x12x1x6x11
+
+# qhasm: int128 x8x13x2x7
+
+# qhasm: int128 x4x9x14x3
+
+# qhasm: int128 x0x1x10x11
+
+# qhasm: int128 x12x13x6x7
+
+# qhasm: int128 x8x9x2x3
+
+# qhasm: int128 x4x5x14x15
+
+# qhasm: int128 x0x1x2x3
+
+# qhasm: int128 x4x5x6x7
+
+# qhasm: int128 x8x9x10x11
+
+# qhasm: int128 x12x13x14x15
+
+# qhasm: int128 m0m1m2m3
+
+# qhasm: int128 m4m5m6m7
+
+# qhasm: int128 m8m9m10m11
+
+# qhasm: int128 m12m13m14m15
+
+# qhasm: int128 start0
+
+# qhasm: int128 start1
+
+# qhasm: int128 start2
+
+# qhasm: int128 start3
+
+# qhasm: stack128 stack_start3
+
+# qhasm: stack128 next_start2
+
+# qhasm: stack128 next_start3
+
+# qhasm: int128 k0k1k2k3
+
+# qhasm: int128 k4k5k6k7
+
+# qhasm: int128 k1n1k7k2
+
+# qhasm: int128 n2n3n3n2
+
+# qhasm: int128 k2k3k6k7
+
+# qhasm: int128 nextblock
+
+# qhasm: stack128 stack_q4
+
+# qhasm: stack128 stack_q5
+
+# qhasm: stack128 stack_q6
+
+# qhasm: stack128 stack_q7
+
+# qhasm: stack32 stack_r4
+
+# qhasm: stack128 k2k3k6k7_stack
+
+# qhasm: stack128 k1n1k7k2_stack
+
+# qhasm: stack512 tmp
+
+# qhasm: stack32 savec
+
+# qhasm: int32 i
+
+# qhasm: int32 ci
+
+# qhasm: int32 mi
+
+# qhasm: enter zt_salsa2012_armneon3_xor
+.align 2
+.global _zt_salsa2012_armneon3_xor
+.global zt_salsa2012_armneon3_xor
+.type _zt_salsa2012_armneon3_xor STT_FUNC
+.type zt_salsa2012_armneon3_xor STT_FUNC
+_zt_salsa2012_armneon3_xor:
+zt_salsa2012_armneon3_xor:
+sub sp,sp,#256
+
+# qhasm: new stack_q4
+
+# qhasm: new stack_q5
+
+# qhasm: new stack_q6
+
+# qhasm: new stack_q7
+
+# qhasm: stack_q4 bot = caller_q4 bot
+# asm 1: vstr <caller_q4=reg128#5%bot,<stack_q4=stack128#1
+# asm 2: vstr <caller_q4=d8,<stack_q4=[sp,#96]
+vstr d8,[sp,#96]
+
+# qhasm: stack_q4 top = caller_q4 top
+# asm 1: vstr <caller_q4=reg128#5%top,<stack_q4=stack128#1
+# asm 2: vstr <caller_q4=d9,<stack_q4=[sp,#104]
+vstr d9,[sp,#104]
+
+# qhasm: stack_q5 bot = caller_q5 bot
+# asm 1: vstr <caller_q5=reg128#6%bot,<stack_q5=stack128#2
+# asm 2: vstr <caller_q5=d10,<stack_q5=[sp,#112]
+vstr d10,[sp,#112]
+
+# qhasm: stack_q5 top = caller_q5 top
+# asm 1: vstr <caller_q5=reg128#6%top,<stack_q5=stack128#2
+# asm 2: vstr <caller_q5=d11,<stack_q5=[sp,#120]
+vstr d11,[sp,#120]
+
+# qhasm: stack_q6 bot = caller_q6 bot
+# asm 1: vstr <caller_q6=reg128#7%bot,<stack_q6=stack128#3
+# asm 2: vstr <caller_q6=d12,<stack_q6=[sp,#128]
+vstr d12,[sp,#128]
+
+# qhasm: stack_q6 top = caller_q6 top
+# asm 1: vstr <caller_q6=reg128#7%top,<stack_q6=stack128#3
+# asm 2: vstr <caller_q6=d13,<stack_q6=[sp,#136]
+vstr d13,[sp,#136]
+
+# qhasm: stack_q7 bot = caller_q7 bot
+# asm 1: vstr <caller_q7=reg128#8%bot,<stack_q7=stack128#4
+# asm 2: vstr <caller_q7=d14,<stack_q7=[sp,#144]
+vstr d14,[sp,#144]
+
+# qhasm: stack_q7 top = caller_q7 top
+# asm 1: vstr <caller_q7=reg128#8%top,<stack_q7=stack128#4
+# asm 2: vstr <caller_q7=d15,<stack_q7=[sp,#152]
+vstr d15,[sp,#152]
+
+# qhasm: new stack_r4
+
+# qhasm: stack_r4 = caller_r4
+# asm 1: str <caller_r4=int32#5,>stack_r4=stack32#2
+# asm 2: str <caller_r4=r4,>stack_r4=[sp,#68]
+str r4,[sp,#68]
+
+# qhasm: int32 c
+
+# qhasm: c = input_0
+# asm 1: mov >c=int32#1,<input_0=int32#1
+# asm 2: mov >c=r0,<input_0=r0
+mov r0,r0
+
+# qhasm: int32 m
+
+# qhasm: m = input_1
+# asm 1: mov >m=int32#2,<input_1=int32#2
+# asm 2: mov >m=r1,<input_1=r1
+mov r1,r1
+
+# qhasm: int32 mlenlow
+
+# qhasm: mlenlow = input_2
+# asm 1: mov >mlenlow=int32#3,<input_2=int32#3
+# asm 2: mov >mlenlow=r2,<input_2=r2
+mov r2,r2
+
+# qhasm: int32 mlenhigh
+
+# qhasm: mlenhigh = input_3
+# asm 1: mov >mlenhigh=int32#4,<input_3=int32#4
+# asm 2: mov >mlenhigh=r3,<input_3=r3
+mov r3,r3
+
+# qhasm: int32 n
+
+# qhasm: n = input_4
+# asm 1: ldr >n=int32#5,<input_4=stack32#arg1
+# asm 2: ldr >n=r4,<input_4=[sp,#256]
+ldr r4,[sp,#256]
+
+# qhasm: int32 k
+
+# qhasm: k = input_5
+# asm 1: ldr >k=int32#13,<input_5=stack32#arg2
+# asm 2: ldr >k=r12,<input_5=[sp,#260]
+ldr r12,[sp,#260]
+
+# qhasm: k0k1k2k3 = mem128[k]
+# asm 1: vld1.8 {>k0k1k2k3=reg128#1%bot->k0k1k2k3=reg128#1%top},[<k=int32#13]
+# asm 2: vld1.8 {>k0k1k2k3=d0->k0k1k2k3=d1},[<k=r12]
+vld1.8 {d0-d1},[r12]
+
+# qhasm: k += 16
+# asm 1: add <k=int32#13,<k=int32#13,#16
+# asm 2: add <k=r12,<k=r12,#16
+add r12,r12,#16
+
+# qhasm: k4k5k6k7 = mem128[k]
+# asm 1: vld1.8 {>k4k5k6k7=reg128#2%bot->k4k5k6k7=reg128#2%top},[<k=int32#13]
+# asm 2: vld1.8 {>k4k5k6k7=d2->k4k5k6k7=d3},[<k=r12]
+vld1.8 {d2-d3},[r12]
+
+# qhasm: i = sigma
+# asm 1: ldr >i=int32#13,=sigma
+# asm 2: ldr >i=r12,=sigma
+ldr r12,=sigma
+
+# qhasm: start0 = mem128[i]
+# asm 1: vld1.8 {>start0=reg128#3%bot->start0=reg128#3%top},[<i=int32#13]
+# asm 2: vld1.8 {>start0=d4->start0=d5},[<i=r12]
+vld1.8 {d4-d5},[r12]
+
+# qhasm: 2x start1 = 0
+# asm 1: vmov.i64 >start1=reg128#4,#0
+# asm 2: vmov.i64 >start1=q3,#0
+vmov.i64 q3,#0
+
+# qhasm: start1 bot = mem64[n]
+# asm 1: vld1.8 {<start1=reg128#4%bot},[<n=int32#5]
+# asm 2: vld1.8 {<start1=d6},[<n=r4]
+vld1.8 {d6},[r4]
+
+# qhasm: start1 = start1[1] start1[0] start1[2,3]
+# asm 1: vext.32 <start1=reg128#4%bot,<start1=reg128#4%bot,<start1=reg128#4%bot,#1
+# asm 2: vext.32 <start1=d6,<start1=d6,<start1=d6,#1
+vext.32 d6,d6,d6,#1
+
+# qhasm: start1 = start1[0,1] start1[1] k4k5k6k7[0]
+# asm 1: vext.32 <start1=reg128#4%top,<start1=reg128#4%bot,<k4k5k6k7=reg128#2%bot,#1
+# asm 2: vext.32 <start1=d7,<start1=d6,<k4k5k6k7=d2,#1
+vext.32 d7,d6,d2,#1
+
+# qhasm: new k1n1k7k2
+
+# qhasm: k1n1k7k2 = k0k1k2k3[1] start1[0] k1n1k7k2[2,3]
+# asm 1: vext.32 <k1n1k7k2=reg128#5%bot,<k0k1k2k3=reg128#1%bot,<start1=reg128#4%bot,#1
+# asm 2: vext.32 <k1n1k7k2=d8,<k0k1k2k3=d0,<start1=d6,#1
+vext.32 d8,d0,d6,#1
+
+# qhasm: k1n1k7k2 = k1n1k7k2[0,1] k4k5k6k7[3] k0k1k2k3[2]
+# asm 1: vext.32 <k1n1k7k2=reg128#5%top,<k4k5k6k7=reg128#2%top,<k0k1k2k3=reg128#1%top,#1
+# asm 2: vext.32 <k1n1k7k2=d9,<k4k5k6k7=d3,<k0k1k2k3=d1,#1
+vext.32 d9,d3,d1,#1
+
+# qhasm: k2k3k6k7 = k4k5k6k7
+# asm 1: vmov >k2k3k6k7=reg128#6,<k4k5k6k7=reg128#2
+# asm 2: vmov >k2k3k6k7=q5,<k4k5k6k7=q1
+vmov q5,q1
+
+# qhasm: k2k3k6k7 = k0k1k2k3[2,3] k2k3k6k7[2,3]
+# asm 1: vmov <k2k3k6k7=reg128#6%bot,<k0k1k2k3=reg128#1%top
+# asm 2: vmov <k2k3k6k7=d10,<k0k1k2k3=d1
+vmov d10,d1
+
+# qhasm: start1 = k4k5k6k7[1] k0k1k2k3[0] start1[2,3]
+# asm 1: vext.32 <start1=reg128#4%bot,<k4k5k6k7=reg128#2%bot,<k0k1k2k3=reg128#1%bot,#1
+# asm 2: vext.32 <start1=d6,<k4k5k6k7=d2,<k0k1k2k3=d0,#1
+vext.32 d6,d2,d0,#1
+
+# qhasm: new k2k3k6k7_stack
+
+# qhasm: k2k3k6k7_stack bot = k2k3k6k7 bot
+# asm 1: vstr <k2k3k6k7=reg128#6%bot,<k2k3k6k7_stack=stack128#5
+# asm 2: vstr <k2k3k6k7=d10,<k2k3k6k7_stack=[sp,#160]
+vstr d10,[sp,#160]
+
+# qhasm: k2k3k6k7_stack top = k2k3k6k7 top
+# asm 1: vstr <k2k3k6k7=reg128#6%top,<k2k3k6k7_stack=stack128#5
+# asm 2: vstr <k2k3k6k7=d11,<k2k3k6k7_stack=[sp,#168]
+vstr d11,[sp,#168]
+
+# qhasm: new k1n1k7k2_stack
+
+# qhasm: k1n1k7k2_stack bot = k1n1k7k2 bot
+# asm 1: vstr <k1n1k7k2=reg128#5%bot,<k1n1k7k2_stack=stack128#6
+# asm 2: vstr <k1n1k7k2=d8,<k1n1k7k2_stack=[sp,#176]
+vstr d8,[sp,#176]
+
+# qhasm: k1n1k7k2_stack top = k1n1k7k2 top
+# asm 1: vstr <k1n1k7k2=reg128#5%top,<k1n1k7k2_stack=stack128#6
+# asm 2: vstr <k1n1k7k2=d9,<k1n1k7k2_stack=[sp,#184]
+vstr d9,[sp,#184]
+
+# qhasm: 2x n2n3n3n2 = 0
+# asm 1: vmov.i64 >n2n3n3n2=reg128#1,#0
+# asm 2: vmov.i64 >n2n3n3n2=q0,#0
+vmov.i64 q0,#0
+
+# qhasm: unsigned<? mlenlow - 128
+# asm 1: cmp <mlenlow=int32#3,#128
+# asm 2: cmp <mlenlow=r2,#128
+cmp r2,#128
+
+# qhasm: goto mlenlowbelow128 if unsigned<
+blo ._mlenlowbelow128
+
+# qhasm: mlenatleast128:
+._mlenatleast128:
+
+# qhasm: new k2k3k6k7
+
+# qhasm: k2k3k6k7 bot = k2k3k6k7_stack bot
+# asm 1: vldr <k2k3k6k7=reg128#2%bot,<k2k3k6k7_stack=stack128#5
+# asm 2: vldr <k2k3k6k7=d2,<k2k3k6k7_stack=[sp,#160]
+vldr d2,[sp,#160]
+
+# qhasm: k2k3k6k7 top = k2k3k6k7_stack top
+# asm 1: vldr <k2k3k6k7=reg128#2%top,<k2k3k6k7_stack=stack128#5
+# asm 2: vldr <k2k3k6k7=d3,<k2k3k6k7_stack=[sp,#168]
+vldr d3,[sp,#168]
+
+# qhasm: new k1n1k7k2
+
+# qhasm: k1n1k7k2 bot = k1n1k7k2_stack bot
+# asm 1: vldr <k1n1k7k2=reg128#5%bot,<k1n1k7k2_stack=stack128#6
+# asm 2: vldr <k1n1k7k2=d8,<k1n1k7k2_stack=[sp,#176]
+vldr d8,[sp,#176]
+
+# qhasm: k1n1k7k2 top = k1n1k7k2_stack top
+# asm 1: vldr <k1n1k7k2=reg128#5%top,<k1n1k7k2_stack=stack128#6
+# asm 2: vldr <k1n1k7k2=d9,<k1n1k7k2_stack=[sp,#184]
+vldr d9,[sp,#184]
+
+# qhasm: n2n3n3n2 = n2n3n3n2[0,1] n2n3n3n2[1] n2n3n3n2[0]
+# asm 1: vext.32 <n2n3n3n2=reg128#1%top,<n2n3n3n2=reg128#1%bot,<n2n3n3n2=reg128#1%bot,#1
+# asm 2: vext.32 <n2n3n3n2=d1,<n2n3n3n2=d0,<n2n3n3n2=d0,#1
+vext.32 d1,d0,d0,#1
+
+# qhasm: new diag2
+
+# qhasm: diag2 = diag2[0,1] k1n1k7k2[0,1]
+# asm 1: vmov <diag2=reg128#6%top,<k1n1k7k2=reg128#5%bot
+# asm 2: vmov <diag2=d11,<k1n1k7k2=d8
+vmov d11,d8
+
+# qhasm: diag2 = n2n3n3n2[3] k2k3k6k7[2] diag2[2,3]
+# asm 1: vext.32 <diag2=reg128#6%bot,<n2n3n3n2=reg128#1%top,<k2k3k6k7=reg128#2%top,#1
+# asm 2: vext.32 <diag2=d10,<n2n3n3n2=d1,<k2k3k6k7=d3,#1
+vext.32 d10,d1,d3,#1
+
+# qhasm: new diag3
+
+# qhasm: diag3 = diag3[0,1] k1n1k7k2[2,3]
+# asm 1: vmov <diag3=reg128#7%top,<k1n1k7k2=reg128#5%top
+# asm 2: vmov <diag3=d13,<k1n1k7k2=d9
+vmov d13,d9
+
+# qhasm: diag3 = k2k3k6k7[1] n2n3n3n2[2] diag3[2,3]
+# asm 1: vext.32 <diag3=reg128#7%bot,<k2k3k6k7=reg128#2%bot,<n2n3n3n2=reg128#1%top,#1
+# asm 2: vext.32 <diag3=d12,<k2k3k6k7=d2,<n2n3n3n2=d1,#1
+vext.32 d12,d2,d1,#1
+
+# qhasm: diag0 = start0
+# asm 1: vmov >diag0=reg128#8,<start0=reg128#3
+# asm 2: vmov >diag0=q7,<start0=q2
+vmov q7,q2
+
+# qhasm: diag1 = start1
+# asm 1: vmov >diag1=reg128#9,<start1=reg128#4
+# asm 2: vmov >diag1=q8,<start1=q3
+vmov q8,q3
+
+# qhasm: start2 = diag2
+# asm 1: vmov >start2=reg128#10,<diag2=reg128#6
+# asm 2: vmov >start2=q9,<diag2=q5
+vmov q9,q5
+
+# qhasm: new stack_start3
+
+# qhasm: stack_start3 bot = diag3 bot
+# asm 1: vstr <diag3=reg128#7%bot,<stack_start3=stack128#9
+# asm 2: vstr <diag3=d12,<stack_start3=[sp,#224]
+vstr d12,[sp,#224]
+
+# qhasm: stack_start3 top = diag3 top
+# asm 1: vstr <diag3=reg128#7%top,<stack_start3=stack128#9
+# asm 2: vstr <diag3=d13,<stack_start3=[sp,#232]
+vstr d13,[sp,#232]
+
+# qhasm: 2x nextblock = 0xff
+# asm 1: vmov.i64 >nextblock=reg128#11,#0xff
+# asm 2: vmov.i64 >nextblock=q10,#0xff
+vmov.i64 q10,#0xff
+
+# qhasm: 4x nextblock unsigned>>= 7
+# asm 1: vshr.u32 >nextblock=reg128#11,<nextblock=reg128#11,#7
+# asm 2: vshr.u32 >nextblock=q10,<nextblock=q10,#7
+vshr.u32 q10,q10,#7
+
+# qhasm: 2x n2n3n3n2 += nextblock
+# asm 1: vadd.i64 >n2n3n3n2=reg128#1,<n2n3n3n2=reg128#1,<nextblock=reg128#11
+# asm 2: vadd.i64 >n2n3n3n2=q0,<n2n3n3n2=q0,<nextblock=q10
+vadd.i64 q0,q0,q10
+
+# qhasm: n2n3n3n2 = n2n3n3n2[0,1] n2n3n3n2[1] n2n3n3n2[0]
+# asm 1: vext.32 <n2n3n3n2=reg128#1%top,<n2n3n3n2=reg128#1%bot,<n2n3n3n2=reg128#1%bot,#1
+# asm 2: vext.32 <n2n3n3n2=d1,<n2n3n3n2=d0,<n2n3n3n2=d0,#1
+vext.32 d1,d0,d0,#1
+
+# qhasm: new next_diag2
+
+# qhasm: next_diag2 = next_diag2[0,1] k1n1k7k2[0,1]
+# asm 1: vmov <next_diag2=reg128#12%top,<k1n1k7k2=reg128#5%bot
+# asm 2: vmov <next_diag2=d23,<k1n1k7k2=d8
+vmov d23,d8
+
+# qhasm: next_diag2 = n2n3n3n2[3] k2k3k6k7[2] next_diag2[2,3]
+# asm 1: vext.32 <next_diag2=reg128#12%bot,<n2n3n3n2=reg128#1%top,<k2k3k6k7=reg128#2%top,#1
+# asm 2: vext.32 <next_diag2=d22,<n2n3n3n2=d1,<k2k3k6k7=d3,#1
+vext.32 d22,d1,d3,#1
+
+# qhasm: new next_diag3
+
+# qhasm: next_diag3 = next_diag3[0,1] k1n1k7k2[2,3]
+# asm 1: vmov <next_diag3=reg128#13%top,<k1n1k7k2=reg128#5%top
+# asm 2: vmov <next_diag3=d25,<k1n1k7k2=d9
+vmov d25,d9
+
+# qhasm: next_diag3 = k2k3k6k7[1] n2n3n3n2[2] next_diag3[2,3]
+# asm 1: vext.32 <next_diag3=reg128#13%bot,<k2k3k6k7=reg128#2%bot,<n2n3n3n2=reg128#1%top,#1
+# asm 2: vext.32 <next_diag3=d24,<k2k3k6k7=d2,<n2n3n3n2=d1,#1
+vext.32 d24,d2,d1,#1
+
+# qhasm: 2x n2n3n3n2 += nextblock
+# asm 1: vadd.i64 >n2n3n3n2=reg128#1,<n2n3n3n2=reg128#1,<nextblock=reg128#11
+# asm 2: vadd.i64 >n2n3n3n2=q0,<n2n3n3n2=q0,<nextblock=q10
+vadd.i64 q0,q0,q10
+
+# qhasm: next_diag0 = diag0
+# asm 1: vmov >next_diag0=reg128#2,<diag0=reg128#8
+# asm 2: vmov >next_diag0=q1,<diag0=q7
+vmov q1,q7
+
+# qhasm: next_diag1 = diag1
+# asm 1: vmov >next_diag1=reg128#5,<diag1=reg128#9
+# asm 2: vmov >next_diag1=q4,<diag1=q8
+vmov q4,q8
+
+# qhasm: next_start2 bot = next_diag2 bot
+# asm 1: vstr <next_diag2=reg128#12%bot,<next_start2=stack128#7
+# asm 2: vstr <next_diag2=d22,<next_start2=[sp,#192]
+vstr d22,[sp,#192]
+
+# qhasm: next_start2 top = next_diag2 top
+# asm 1: vstr <next_diag2=reg128#12%top,<next_start2=stack128#7
+# asm 2: vstr <next_diag2=d23,<next_start2=[sp,#200]
+vstr d23,[sp,#200]
+
+# qhasm: next_start3 bot = next_diag3 bot
+# asm 1: vstr <next_diag3=reg128#13%bot,<next_start3=stack128#8
+# asm 2: vstr <next_diag3=d24,<next_start3=[sp,#208]
+vstr d24,[sp,#208]
+
+# qhasm: next_start3 top = next_diag3 top
+# asm 1: vstr <next_diag3=reg128#13%top,<next_start3=stack128#8
+# asm 2: vstr <next_diag3=d25,<next_start3=[sp,#216]
+vstr d25,[sp,#216]
+
+# qhasm: i = 12
+# asm 1: ldr >i=int32#5,=12
+# asm 2: ldr >i=r4,=12
+ldr r4,=12
+
+# qhasm: mainloop2:
+._mainloop2:
+
+# qhasm: 4x a0 = diag1 + diag0
+# asm 1: vadd.i32 >a0=reg128#11,<diag1=reg128#9,<diag0=reg128#8
+# asm 2: vadd.i32 >a0=q10,<diag1=q8,<diag0=q7
+vadd.i32 q10,q8,q7
+
+# qhasm: 4x next_a0 = next_diag1 + next_diag0
+# asm 1: vadd.i32 >next_a0=reg128#14,<next_diag1=reg128#5,<next_diag0=reg128#2
+# asm 2: vadd.i32 >next_a0=q13,<next_diag1=q4,<next_diag0=q1
+vadd.i32 q13,q4,q1
+
+# qhasm: 4x b0 = a0 << 7
+# asm 1: vshl.i32 >b0=reg128#15,<a0=reg128#11,#7
+# asm 2: vshl.i32 >b0=q14,<a0=q10,#7
+vshl.i32 q14,q10,#7
+
+# qhasm: 4x next_b0 = next_a0 << 7
+# asm 1: vshl.i32 >next_b0=reg128#16,<next_a0=reg128#14,#7
+# asm 2: vshl.i32 >next_b0=q15,<next_a0=q13,#7
+vshl.i32 q15,q13,#7
+
+# qhasm: 4x b0 insert= a0 >> 25
+# asm 1: vsri.i32 <b0=reg128#15,<a0=reg128#11,#25
+# asm 2: vsri.i32 <b0=q14,<a0=q10,#25
+vsri.i32 q14,q10,#25
+
+# qhasm: 4x next_b0 insert= next_a0 >> 25
+# asm 1: vsri.i32 <next_b0=reg128#16,<next_a0=reg128#14,#25
+# asm 2: vsri.i32 <next_b0=q15,<next_a0=q13,#25
+vsri.i32 q15,q13,#25
+
+# qhasm: diag3 ^= b0
+# asm 1: veor >diag3=reg128#7,<diag3=reg128#7,<b0=reg128#15
+# asm 2: veor >diag3=q6,<diag3=q6,<b0=q14
+veor q6,q6,q14
+
+# qhasm: next_diag3 ^= next_b0
+# asm 1: veor >next_diag3=reg128#11,<next_diag3=reg128#13,<next_b0=reg128#16
+# asm 2: veor >next_diag3=q10,<next_diag3=q12,<next_b0=q15
+veor q10,q12,q15
+
+# qhasm: 4x a1 = diag0 + diag3
+# asm 1: vadd.i32 >a1=reg128#13,<diag0=reg128#8,<diag3=reg128#7
+# asm 2: vadd.i32 >a1=q12,<diag0=q7,<diag3=q6
+vadd.i32 q12,q7,q6
+
+# qhasm: 4x next_a1 = next_diag0 + next_diag3
+# asm 1: vadd.i32 >next_a1=reg128#14,<next_diag0=reg128#2,<next_diag3=reg128#11
+# asm 2: vadd.i32 >next_a1=q13,<next_diag0=q1,<next_diag3=q10
+vadd.i32 q13,q1,q10
+
+# qhasm: 4x b1 = a1 << 9
+# asm 1: vshl.i32 >b1=reg128#15,<a1=reg128#13,#9
+# asm 2: vshl.i32 >b1=q14,<a1=q12,#9
+vshl.i32 q14,q12,#9
+
+# qhasm: 4x next_b1 = next_a1 << 9
+# asm 1: vshl.i32 >next_b1=reg128#16,<next_a1=reg128#14,#9
+# asm 2: vshl.i32 >next_b1=q15,<next_a1=q13,#9
+vshl.i32 q15,q13,#9
+
+# qhasm: 4x b1 insert= a1 >> 23
+# asm 1: vsri.i32 <b1=reg128#15,<a1=reg128#13,#23
+# asm 2: vsri.i32 <b1=q14,<a1=q12,#23
+vsri.i32 q14,q12,#23
+
+# qhasm: 4x next_b1 insert= next_a1 >> 23
+# asm 1: vsri.i32 <next_b1=reg128#16,<next_a1=reg128#14,#23
+# asm 2: vsri.i32 <next_b1=q15,<next_a1=q13,#23
+vsri.i32 q15,q13,#23
+
+# qhasm: diag2 ^= b1
+# asm 1: veor >diag2=reg128#6,<diag2=reg128#6,<b1=reg128#15
+# asm 2: veor >diag2=q5,<diag2=q5,<b1=q14
+veor q5,q5,q14
+
+# qhasm: next_diag2 ^= next_b1
+# asm 1: veor >next_diag2=reg128#12,<next_diag2=reg128#12,<next_b1=reg128#16
+# asm 2: veor >next_diag2=q11,<next_diag2=q11,<next_b1=q15
+veor q11,q11,q15
+
+# qhasm: 4x a2 = diag3 + diag2
+# asm 1: vadd.i32 >a2=reg128#13,<diag3=reg128#7,<diag2=reg128#6
+# asm 2: vadd.i32 >a2=q12,<diag3=q6,<diag2=q5
+vadd.i32 q12,q6,q5
+
+# qhasm: diag3 = diag3[3] diag3[0,1,2]
+# asm 1: vext.32 >diag3=reg128#7,<diag3=reg128#7,<diag3=reg128#7,#3
+# asm 2: vext.32 >diag3=q6,<diag3=q6,<diag3=q6,#3
+vext.32 q6,q6,q6,#3
+
+# qhasm: 4x next_a2 = next_diag3 + next_diag2
+# asm 1: vadd.i32 >next_a2=reg128#14,<next_diag3=reg128#11,<next_diag2=reg128#12
+# asm 2: vadd.i32 >next_a2=q13,<next_diag3=q10,<next_diag2=q11
+vadd.i32 q13,q10,q11
+
+# qhasm: 4x b2 = a2 << 13
+# asm 1: vshl.i32 >b2=reg128#15,<a2=reg128#13,#13
+# asm 2: vshl.i32 >b2=q14,<a2=q12,#13
+vshl.i32 q14,q12,#13
+
+# qhasm: next_diag3 = next_diag3[3] next_diag3[0,1,2]
+# asm 1: vext.32 >next_diag3=reg128#11,<next_diag3=reg128#11,<next_diag3=reg128#11,#3
+# asm 2: vext.32 >next_diag3=q10,<next_diag3=q10,<next_diag3=q10,#3
+vext.32 q10,q10,q10,#3
+
+# qhasm: 4x next_b2 = next_a2 << 13
+# asm 1: vshl.i32 >next_b2=reg128#16,<next_a2=reg128#14,#13
+# asm 2: vshl.i32 >next_b2=q15,<next_a2=q13,#13
+vshl.i32 q15,q13,#13
+
+# qhasm: 4x b2 insert= a2 >> 19
+# asm 1: vsri.i32 <b2=reg128#15,<a2=reg128#13,#19
+# asm 2: vsri.i32 <b2=q14,<a2=q12,#19
+vsri.i32 q14,q12,#19
+
+# qhasm: 4x next_b2 insert= next_a2 >> 19
+# asm 1: vsri.i32 <next_b2=reg128#16,<next_a2=reg128#14,#19
+# asm 2: vsri.i32 <next_b2=q15,<next_a2=q13,#19
+vsri.i32 q15,q13,#19
+
+# qhasm: diag1 ^= b2
+# asm 1: veor >diag1=reg128#9,<diag1=reg128#9,<b2=reg128#15
+# asm 2: veor >diag1=q8,<diag1=q8,<b2=q14
+veor q8,q8,q14
+
+# qhasm: next_diag1 ^= next_b2
+# asm 1: veor >next_diag1=reg128#5,<next_diag1=reg128#5,<next_b2=reg128#16
+# asm 2: veor >next_diag1=q4,<next_diag1=q4,<next_b2=q15
+veor q4,q4,q15
+
+# qhasm: 4x a3 = diag2 + diag1
+# asm 1: vadd.i32 >a3=reg128#13,<diag2=reg128#6,<diag1=reg128#9
+# asm 2: vadd.i32 >a3=q12,<diag2=q5,<diag1=q8
+vadd.i32 q12,q5,q8
+
+# qhasm: diag2 = diag2[2,3] diag2[0,1]
+# asm 1: vswp <diag2=reg128#6%bot,<diag2=reg128#6%top
+# asm 2: vswp <diag2=d10,<diag2=d11
+vswp d10,d11
+
+# qhasm: 4x next_a3 = next_diag2 + next_diag1
+# asm 1: vadd.i32 >next_a3=reg128#14,<next_diag2=reg128#12,<next_diag1=reg128#5
+# asm 2: vadd.i32 >next_a3=q13,<next_diag2=q11,<next_diag1=q4
+vadd.i32 q13,q11,q4
+
+# qhasm: 4x b3 = a3 << 18
+# asm 1: vshl.i32 >b3=reg128#15,<a3=reg128#13,#18
+# asm 2: vshl.i32 >b3=q14,<a3=q12,#18
+vshl.i32 q14,q12,#18
+
+# qhasm: next_diag2 = next_diag2[2,3] next_diag2[0,1]
+# asm 1: vswp <next_diag2=reg128#12%bot,<next_diag2=reg128#12%top
+# asm 2: vswp <next_diag2=d22,<next_diag2=d23
+vswp d22,d23
+
+# qhasm: 4x next_b3 = next_a3 << 18
+# asm 1: vshl.i32 >next_b3=reg128#16,<next_a3=reg128#14,#18
+# asm 2: vshl.i32 >next_b3=q15,<next_a3=q13,#18
+vshl.i32 q15,q13,#18
+
+# qhasm: 4x b3 insert= a3 >> 14
+# asm 1: vsri.i32 <b3=reg128#15,<a3=reg128#13,#14
+# asm 2: vsri.i32 <b3=q14,<a3=q12,#14
+vsri.i32 q14,q12,#14
+
+# qhasm: diag1 = diag1[1,2,3] diag1[0]
+# asm 1: vext.32 >diag1=reg128#9,<diag1=reg128#9,<diag1=reg128#9,#1
+# asm 2: vext.32 >diag1=q8,<diag1=q8,<diag1=q8,#1
+vext.32 q8,q8,q8,#1
+
+# qhasm: 4x next_b3 insert= next_a3 >> 14
+# asm 1: vsri.i32 <next_b3=reg128#16,<next_a3=reg128#14,#14
+# asm 2: vsri.i32 <next_b3=q15,<next_a3=q13,#14
+vsri.i32 q15,q13,#14
+
+# qhasm: diag0 ^= b3
+# asm 1: veor >diag0=reg128#8,<diag0=reg128#8,<b3=reg128#15
+# asm 2: veor >diag0=q7,<diag0=q7,<b3=q14
+veor q7,q7,q14
+
+# qhasm: next_diag1 = next_diag1[1,2,3] next_diag1[0]
+# asm 1: vext.32 >next_diag1=reg128#5,<next_diag1=reg128#5,<next_diag1=reg128#5,#1
+# asm 2: vext.32 >next_diag1=q4,<next_diag1=q4,<next_diag1=q4,#1
+vext.32 q4,q4,q4,#1
+
+# qhasm: next_diag0 ^= next_b3
+# asm 1: veor >next_diag0=reg128#2,<next_diag0=reg128#2,<next_b3=reg128#16
+# asm 2: veor >next_diag0=q1,<next_diag0=q1,<next_b3=q15
+veor q1,q1,q15
+
+# qhasm: 4x a0 = diag3 + diag0
+# asm 1: vadd.i32 >a0=reg128#13,<diag3=reg128#7,<diag0=reg128#8
+# asm 2: vadd.i32 >a0=q12,<diag3=q6,<diag0=q7
+vadd.i32 q12,q6,q7
+
+# qhasm: 4x next_a0 = next_diag3 + next_diag0
+# asm 1: vadd.i32 >next_a0=reg128#14,<next_diag3=reg128#11,<next_diag0=reg128#2
+# asm 2: vadd.i32 >next_a0=q13,<next_diag3=q10,<next_diag0=q1
+vadd.i32 q13,q10,q1
+
+# qhasm: 4x b0 = a0 << 7
+# asm 1: vshl.i32 >b0=reg128#15,<a0=reg128#13,#7
+# asm 2: vshl.i32 >b0=q14,<a0=q12,#7
+vshl.i32 q14,q12,#7
+
+# qhasm: 4x next_b0 = next_a0 << 7
+# asm 1: vshl.i32 >next_b0=reg128#16,<next_a0=reg128#14,#7
+# asm 2: vshl.i32 >next_b0=q15,<next_a0=q13,#7
+vshl.i32 q15,q13,#7
+
+# qhasm: 4x b0 insert= a0 >> 25
+# asm 1: vsri.i32 <b0=reg128#15,<a0=reg128#13,#25
+# asm 2: vsri.i32 <b0=q14,<a0=q12,#25
+vsri.i32 q14,q12,#25
+
+# qhasm: 4x next_b0 insert= next_a0 >> 25
+# asm 1: vsri.i32 <next_b0=reg128#16,<next_a0=reg128#14,#25
+# asm 2: vsri.i32 <next_b0=q15,<next_a0=q13,#25
+vsri.i32 q15,q13,#25
+
+# qhasm: diag1 ^= b0
+# asm 1: veor >diag1=reg128#9,<diag1=reg128#9,<b0=reg128#15
+# asm 2: veor >diag1=q8,<diag1=q8,<b0=q14
+veor q8,q8,q14
+
+# qhasm: next_diag1 ^= next_b0
+# asm 1: veor >next_diag1=reg128#5,<next_diag1=reg128#5,<next_b0=reg128#16
+# asm 2: veor >next_diag1=q4,<next_diag1=q4,<next_b0=q15
+veor q4,q4,q15
+
+# qhasm: 4x a1 = diag0 + diag1
+# asm 1: vadd.i32 >a1=reg128#13,<diag0=reg128#8,<diag1=reg128#9
+# asm 2: vadd.i32 >a1=q12,<diag0=q7,<diag1=q8
+vadd.i32 q12,q7,q8
+
+# qhasm: 4x next_a1 = next_diag0 + next_diag1
+# asm 1: vadd.i32 >next_a1=reg128#14,<next_diag0=reg128#2,<next_diag1=reg128#5
+# asm 2: vadd.i32 >next_a1=q13,<next_diag0=q1,<next_diag1=q4
+vadd.i32 q13,q1,q4
+
+# qhasm: 4x b1 = a1 << 9
+# asm 1: vshl.i32 >b1=reg128#15,<a1=reg128#13,#9
+# asm 2: vshl.i32 >b1=q14,<a1=q12,#9
+vshl.i32 q14,q12,#9
+
+# qhasm: 4x next_b1 = next_a1 << 9
+# asm 1: vshl.i32 >next_b1=reg128#16,<next_a1=reg128#14,#9
+# asm 2: vshl.i32 >next_b1=q15,<next_a1=q13,#9
+vshl.i32 q15,q13,#9
+
+# qhasm: 4x b1 insert= a1 >> 23
+# asm 1: vsri.i32 <b1=reg128#15,<a1=reg128#13,#23
+# asm 2: vsri.i32 <b1=q14,<a1=q12,#23
+vsri.i32 q14,q12,#23
+
+# qhasm: unsigned>? i -= 2
+# asm 1: subs <i=int32#5,<i=int32#5,#2
+# asm 2: subs <i=r4,<i=r4,#2
+subs r4,r4,#2
+
+# qhasm: 4x next_b1 insert= next_a1 >> 23
+# asm 1: vsri.i32 <next_b1=reg128#16,<next_a1=reg128#14,#23
+# asm 2: vsri.i32 <next_b1=q15,<next_a1=q13,#23
+vsri.i32 q15,q13,#23
+
+# qhasm: diag2 ^= b1
+# asm 1: veor >diag2=reg128#6,<diag2=reg128#6,<b1=reg128#15
+# asm 2: veor >diag2=q5,<diag2=q5,<b1=q14
+veor q5,q5,q14
+
+# qhasm: next_diag2 ^= next_b1
+# asm 1: veor >next_diag2=reg128#12,<next_diag2=reg128#12,<next_b1=reg128#16
+# asm 2: veor >next_diag2=q11,<next_diag2=q11,<next_b1=q15
+veor q11,q11,q15
+
+# qhasm: 4x a2 = diag1 + diag2
+# asm 1: vadd.i32 >a2=reg128#13,<diag1=reg128#9,<diag2=reg128#6
+# asm 2: vadd.i32 >a2=q12,<diag1=q8,<diag2=q5
+vadd.i32 q12,q8,q5
+
+# qhasm: diag1 = diag1[3] diag1[0,1,2]
+# asm 1: vext.32 >diag1=reg128#9,<diag1=reg128#9,<diag1=reg128#9,#3
+# asm 2: vext.32 >diag1=q8,<diag1=q8,<diag1=q8,#3
+vext.32 q8,q8,q8,#3
+
+# qhasm: 4x next_a2 = next_diag1 + next_diag2
+# asm 1: vadd.i32 >next_a2=reg128#14,<next_diag1=reg128#5,<next_diag2=reg128#12
+# asm 2: vadd.i32 >next_a2=q13,<next_diag1=q4,<next_diag2=q11
+vadd.i32 q13,q4,q11
+
+# qhasm: 4x b2 = a2 << 13
+# asm 1: vshl.i32 >b2=reg128#15,<a2=reg128#13,#13
+# asm 2: vshl.i32 >b2=q14,<a2=q12,#13
+vshl.i32 q14,q12,#13
+
+# qhasm: next_diag1 = next_diag1[3] next_diag1[0,1,2]
+# asm 1: vext.32 >next_diag1=reg128#5,<next_diag1=reg128#5,<next_diag1=reg128#5,#3
+# asm 2: vext.32 >next_diag1=q4,<next_diag1=q4,<next_diag1=q4,#3
+vext.32 q4,q4,q4,#3
+
+# qhasm: 4x next_b2 = next_a2 << 13
+# asm 1: vshl.i32 >next_b2=reg128#16,<next_a2=reg128#14,#13
+# asm 2: vshl.i32 >next_b2=q15,<next_a2=q13,#13
+vshl.i32 q15,q13,#13
+
+# qhasm: 4x b2 insert= a2 >> 19
+# asm 1: vsri.i32 <b2=reg128#15,<a2=reg128#13,#19
+# asm 2: vsri.i32 <b2=q14,<a2=q12,#19
+vsri.i32 q14,q12,#19
+
+# qhasm: 4x next_b2 insert= next_a2 >> 19
+# asm 1: vsri.i32 <next_b2=reg128#16,<next_a2=reg128#14,#19
+# asm 2: vsri.i32 <next_b2=q15,<next_a2=q13,#19
+vsri.i32 q15,q13,#19
+
+# qhasm: diag3 ^= b2
+# asm 1: veor >diag3=reg128#7,<diag3=reg128#7,<b2=reg128#15
+# asm 2: veor >diag3=q6,<diag3=q6,<b2=q14
+veor q6,q6,q14
+
+# qhasm: next_diag3 ^= next_b2
+# asm 1: veor >next_diag3=reg128#11,<next_diag3=reg128#11,<next_b2=reg128#16
+# asm 2: veor >next_diag3=q10,<next_diag3=q10,<next_b2=q15
+veor q10,q10,q15
+
+# qhasm: 4x a3 = diag2 + diag3
+# asm 1: vadd.i32 >a3=reg128#13,<diag2=reg128#6,<diag3=reg128#7
+# asm 2: vadd.i32 >a3=q12,<diag2=q5,<diag3=q6
+vadd.i32 q12,q5,q6
+
+# qhasm: diag2 = diag2[2,3] diag2[0,1]
+# asm 1: vswp <diag2=reg128#6%bot,<diag2=reg128#6%top
+# asm 2: vswp <diag2=d10,<diag2=d11
+vswp d10,d11
+
+# qhasm: 4x next_a3 = next_diag2 + next_diag3
+# asm 1: vadd.i32 >next_a3=reg128#14,<next_diag2=reg128#12,<next_diag3=reg128#11
+# asm 2: vadd.i32 >next_a3=q13,<next_diag2=q11,<next_diag3=q10
+vadd.i32 q13,q11,q10
+
+# qhasm: 4x b3 = a3 << 18
+# asm 1: vshl.i32 >b3=reg128#15,<a3=reg128#13,#18
+# asm 2: vshl.i32 >b3=q14,<a3=q12,#18
+vshl.i32 q14,q12,#18
+
+# qhasm: next_diag2 = next_diag2[2,3] next_diag2[0,1]
+# asm 1: vswp <next_diag2=reg128#12%bot,<next_diag2=reg128#12%top
+# asm 2: vswp <next_diag2=d22,<next_diag2=d23
+vswp d22,d23
+
+# qhasm: 4x next_b3 = next_a3 << 18
+# asm 1: vshl.i32 >next_b3=reg128#16,<next_a3=reg128#14,#18
+# asm 2: vshl.i32 >next_b3=q15,<next_a3=q13,#18
+vshl.i32 q15,q13,#18
+
+# qhasm: 4x b3 insert= a3 >> 14
+# asm 1: vsri.i32 <b3=reg128#15,<a3=reg128#13,#14
+# asm 2: vsri.i32 <b3=q14,<a3=q12,#14
+vsri.i32 q14,q12,#14
+
+# qhasm: diag3 = diag3[1,2,3] diag3[0]
+# asm 1: vext.32 >diag3=reg128#7,<diag3=reg128#7,<diag3=reg128#7,#1
+# asm 2: vext.32 >diag3=q6,<diag3=q6,<diag3=q6,#1
+vext.32 q6,q6,q6,#1
+
+# qhasm: 4x next_b3 insert= next_a3 >> 14
+# asm 1: vsri.i32 <next_b3=reg128#16,<next_a3=reg128#14,#14
+# asm 2: vsri.i32 <next_b3=q15,<next_a3=q13,#14
+vsri.i32 q15,q13,#14
+
+# qhasm: diag0 ^= b3
+# asm 1: veor >diag0=reg128#8,<diag0=reg128#8,<b3=reg128#15
+# asm 2: veor >diag0=q7,<diag0=q7,<b3=q14
+veor q7,q7,q14
+
+# qhasm: next_diag3 = next_diag3[1,2,3] next_diag3[0]
+# asm 1: vext.32 >next_diag3=reg128#13,<next_diag3=reg128#11,<next_diag3=reg128#11,#1
+# asm 2: vext.32 >next_diag3=q12,<next_diag3=q10,<next_diag3=q10,#1
+vext.32 q12,q10,q10,#1
+
+# qhasm: next_diag0 ^= next_b3
+# asm 1: veor >next_diag0=reg128#2,<next_diag0=reg128#2,<next_b3=reg128#16
+# asm 2: veor >next_diag0=q1,<next_diag0=q1,<next_b3=q15
+veor q1,q1,q15
+
+# qhasm: goto mainloop2 if unsigned>
+bhi ._mainloop2
+
+# qhasm: 2x abab = 0xffffffff
+# asm 1: vmov.i64 >abab=reg128#11,#0xffffffff
+# asm 2: vmov.i64 >abab=q10,#0xffffffff
+vmov.i64 q10,#0xffffffff
+
+# qhasm: new x4x9x14x3
+
+# qhasm: x4x9x14x3 bot = stack_start3 bot
+# asm 1: vldr <x4x9x14x3=reg128#14%bot,<stack_start3=stack128#9
+# asm 2: vldr <x4x9x14x3=d26,<stack_start3=[sp,#224]
+vldr d26,[sp,#224]
+
+# qhasm: x4x9x14x3 top = stack_start3 top
+# asm 1: vldr <x4x9x14x3=reg128#14%top,<stack_start3=stack128#9
+# asm 2: vldr <x4x9x14x3=d27,<stack_start3=[sp,#232]
+vldr d27,[sp,#232]
+
+# qhasm: 4x x0x5x10x15 = diag0 + start0
+# asm 1: vadd.i32 >x0x5x10x15=reg128#8,<diag0=reg128#8,<start0=reg128#3
+# asm 2: vadd.i32 >x0x5x10x15=q7,<diag0=q7,<start0=q2
+vadd.i32 q7,q7,q2
+
+# qhasm: 4x x12x1x6x11 = diag1 + start1
+# asm 1: vadd.i32 >x12x1x6x11=reg128#9,<diag1=reg128#9,<start1=reg128#4
+# asm 2: vadd.i32 >x12x1x6x11=q8,<diag1=q8,<start1=q3
+vadd.i32 q8,q8,q3
+
+# qhasm: 4x x8x13x2x7 = diag2 + start2
+# asm 1: vadd.i32 >x8x13x2x7=reg128#6,<diag2=reg128#6,<start2=reg128#10
+# asm 2: vadd.i32 >x8x13x2x7=q5,<diag2=q5,<start2=q9
+vadd.i32 q5,q5,q9
+
+# qhasm: 4x x4x9x14x3 += diag3
+# asm 1: vadd.i32 >x4x9x14x3=reg128#7,<x4x9x14x3=reg128#14,<diag3=reg128#7
+# asm 2: vadd.i32 >x4x9x14x3=q6,<x4x9x14x3=q13,<diag3=q6
+vadd.i32 q6,q13,q6
+
+# qhasm: x0x1x10x11 = x0x5x10x15
+# asm 1: vmov >x0x1x10x11=reg128#10,<x0x5x10x15=reg128#8
+# asm 2: vmov >x0x1x10x11=q9,<x0x5x10x15=q7
+vmov q9,q7
+
+# qhasm: x12x13x6x7 = x12x1x6x11
+# asm 1: vmov >x12x13x6x7=reg128#14,<x12x1x6x11=reg128#9
+# asm 2: vmov >x12x13x6x7=q13,<x12x1x6x11=q8
+vmov q13,q8
+
+# qhasm: x8x9x2x3 = x8x13x2x7
+# asm 1: vmov >x8x9x2x3=reg128#15,<x8x13x2x7=reg128#6
+# asm 2: vmov >x8x9x2x3=q14,<x8x13x2x7=q5
+vmov q14,q5
+
+# qhasm: x4x5x14x15 = x4x9x14x3
+# asm 1: vmov >x4x5x14x15=reg128#16,<x4x9x14x3=reg128#7
+# asm 2: vmov >x4x5x14x15=q15,<x4x9x14x3=q6
+vmov q15,q6
+
+# qhasm: x0x1x10x11 = (abab & x0x1x10x11) | (~abab & x12x1x6x11)
+# asm 1: vbif <x0x1x10x11=reg128#10,<x12x1x6x11=reg128#9,<abab=reg128#11
+# asm 2: vbif <x0x1x10x11=q9,<x12x1x6x11=q8,<abab=q10
+vbif q9,q8,q10
+
+# qhasm: x12x13x6x7 = (abab & x12x13x6x7) | (~abab & x8x13x2x7)
+# asm 1: vbif <x12x13x6x7=reg128#14,<x8x13x2x7=reg128#6,<abab=reg128#11
+# asm 2: vbif <x12x13x6x7=q13,<x8x13x2x7=q5,<abab=q10
+vbif q13,q5,q10
+
+# qhasm: x8x9x2x3 = (abab & x8x9x2x3) | (~abab & x4x9x14x3)
+# asm 1: vbif <x8x9x2x3=reg128#15,<x4x9x14x3=reg128#7,<abab=reg128#11
+# asm 2: vbif <x8x9x2x3=q14,<x4x9x14x3=q6,<abab=q10
+vbif q14,q6,q10
+
+# qhasm: x4x5x14x15 = (abab & x4x5x14x15) | (~abab & x0x5x10x15)
+# asm 1: vbif <x4x5x14x15=reg128#16,<x0x5x10x15=reg128#8,<abab=reg128#11
+# asm 2: vbif <x4x5x14x15=q15,<x0x5x10x15=q7,<abab=q10
+vbif q15,q7,q10
+
+# qhasm: x0x1x2x3 = x0x1x10x11
+# asm 1: vmov >x0x1x2x3=reg128#6,<x0x1x10x11=reg128#10
+# asm 2: vmov >x0x1x2x3=q5,<x0x1x10x11=q9
+vmov q5,q9
+
+# qhasm: x4x5x6x7 = x4x5x14x15
+# asm 1: vmov >x4x5x6x7=reg128#7,<x4x5x14x15=reg128#16
+# asm 2: vmov >x4x5x6x7=q6,<x4x5x14x15=q15
+vmov q6,q15
+
+# qhasm: x8x9x10x11 = x8x9x2x3
+# asm 1: vmov >x8x9x10x11=reg128#8,<x8x9x2x3=reg128#15
+# asm 2: vmov >x8x9x10x11=q7,<x8x9x2x3=q14
+vmov q7,q14
+
+# qhasm: x12x13x14x15 = x12x13x6x7
+# asm 1: vmov >x12x13x14x15=reg128#9,<x12x13x6x7=reg128#14
+# asm 2: vmov >x12x13x14x15=q8,<x12x13x6x7=q13
+vmov q8,q13
+
+# qhasm: x0x1x2x3 = x0x1x2x3[0,1] x8x9x2x3[2,3]
+# asm 1: vmov <x0x1x2x3=reg128#6%top,<x8x9x2x3=reg128#15%top
+# asm 2: vmov <x0x1x2x3=d11,<x8x9x2x3=d29
+vmov d11,d29
+
+# qhasm: x4x5x6x7 = x4x5x6x7[0,1] x12x13x6x7[2,3]
+# asm 1: vmov <x4x5x6x7=reg128#7%top,<x12x13x6x7=reg128#14%top
+# asm 2: vmov <x4x5x6x7=d13,<x12x13x6x7=d27
+vmov d13,d27
+
+# qhasm: x8x9x10x11 = x8x9x10x11[0,1] x0x1x10x11[2,3]
+# asm 1: vmov <x8x9x10x11=reg128#8%top,<x0x1x10x11=reg128#10%top
+# asm 2: vmov <x8x9x10x11=d15,<x0x1x10x11=d19
+vmov d15,d19
+
+# qhasm: x12x13x14x15 = x12x13x14x15[0,1] x4x5x14x15[2,3]
+# asm 1: vmov <x12x13x14x15=reg128#9%top,<x4x5x14x15=reg128#16%top
+# asm 2: vmov <x12x13x14x15=d17,<x4x5x14x15=d31
+vmov d17,d31
+
+# qhasm: =? m - 0
+# asm 1: cmp <m=int32#2,#0
+# asm 2: cmp <m=r1,#0
+cmp r1,#0
+
+# qhasm: goto nomessage2 if =
+beq ._nomessage2
+
+# qhasm: m0m1m2m3 = mem128[m]
+# asm 1: vld1.8 {>m0m1m2m3=reg128#10%bot->m0m1m2m3=reg128#10%top},[<m=int32#2]
+# asm 2: vld1.8 {>m0m1m2m3=d18->m0m1m2m3=d19},[<m=r1]
+vld1.8 {d18-d19},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m4m5m6m7 = mem128[m]
+# asm 1: vld1.8 {>m4m5m6m7=reg128#14%bot->m4m5m6m7=reg128#14%top},[<m=int32#2]
+# asm 2: vld1.8 {>m4m5m6m7=d26->m4m5m6m7=d27},[<m=r1]
+vld1.8 {d26-d27},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m8m9m10m11 = mem128[m]
+# asm 1: vld1.8 {>m8m9m10m11=reg128#15%bot->m8m9m10m11=reg128#15%top},[<m=int32#2]
+# asm 2: vld1.8 {>m8m9m10m11=d28->m8m9m10m11=d29},[<m=r1]
+vld1.8 {d28-d29},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m12m13m14m15 = mem128[m]
+# asm 1: vld1.8 {>m12m13m14m15=reg128#16%bot->m12m13m14m15=reg128#16%top},[<m=int32#2]
+# asm 2: vld1.8 {>m12m13m14m15=d30->m12m13m14m15=d31},[<m=r1]
+vld1.8 {d30-d31},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: x0x1x2x3 ^= m0m1m2m3
+# asm 1: veor >x0x1x2x3=reg128#6,<x0x1x2x3=reg128#6,<m0m1m2m3=reg128#10
+# asm 2: veor >x0x1x2x3=q5,<x0x1x2x3=q5,<m0m1m2m3=q9
+veor q5,q5,q9
+
+# qhasm: x4x5x6x7 ^= m4m5m6m7
+# asm 1: veor >x4x5x6x7=reg128#7,<x4x5x6x7=reg128#7,<m4m5m6m7=reg128#14
+# asm 2: veor >x4x5x6x7=q6,<x4x5x6x7=q6,<m4m5m6m7=q13
+veor q6,q6,q13
+
+# qhasm: x8x9x10x11 ^= m8m9m10m11
+# asm 1: veor >x8x9x10x11=reg128#8,<x8x9x10x11=reg128#8,<m8m9m10m11=reg128#15
+# asm 2: veor >x8x9x10x11=q7,<x8x9x10x11=q7,<m8m9m10m11=q14
+veor q7,q7,q14
+
+# qhasm: x12x13x14x15 ^= m12m13m14m15
+# asm 1: veor >x12x13x14x15=reg128#9,<x12x13x14x15=reg128#9,<m12m13m14m15=reg128#16
+# asm 2: veor >x12x13x14x15=q8,<x12x13x14x15=q8,<m12m13m14m15=q15
+veor q8,q8,q15
+
+# qhasm: nomessage2:
+._nomessage2:
+
+# qhasm: mem128[c] = x0x1x2x3
+# asm 1: vst1.8 {<x0x1x2x3=reg128#6%bot-<x0x1x2x3=reg128#6%top},[<c=int32#1]
+# asm 2: vst1.8 {<x0x1x2x3=d10-<x0x1x2x3=d11},[<c=r0]
+vst1.8 {d10-d11},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x4x5x6x7
+# asm 1: vst1.8 {<x4x5x6x7=reg128#7%bot-<x4x5x6x7=reg128#7%top},[<c=int32#1]
+# asm 2: vst1.8 {<x4x5x6x7=d12-<x4x5x6x7=d13},[<c=r0]
+vst1.8 {d12-d13},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x8x9x10x11
+# asm 1: vst1.8 {<x8x9x10x11=reg128#8%bot-<x8x9x10x11=reg128#8%top},[<c=int32#1]
+# asm 2: vst1.8 {<x8x9x10x11=d14-<x8x9x10x11=d15},[<c=r0]
+vst1.8 {d14-d15},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x12x13x14x15
+# asm 1: vst1.8 {<x12x13x14x15=reg128#9%bot-<x12x13x14x15=reg128#9%top},[<c=int32#1]
+# asm 2: vst1.8 {<x12x13x14x15=d16-<x12x13x14x15=d17},[<c=r0]
+vst1.8 {d16-d17},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: new x8x13x2x7
+
+# qhasm: x8x13x2x7 bot = next_start2 bot
+# asm 1: vldr <x8x13x2x7=reg128#6%bot,<next_start2=stack128#7
+# asm 2: vldr <x8x13x2x7=d10,<next_start2=[sp,#192]
+vldr d10,[sp,#192]
+
+# qhasm: x8x13x2x7 top = next_start2 top
+# asm 1: vldr <x8x13x2x7=reg128#6%top,<next_start2=stack128#7
+# asm 2: vldr <x8x13x2x7=d11,<next_start2=[sp,#200]
+vldr d11,[sp,#200]
+
+# qhasm: new x4x9x14x3
+
+# qhasm: x4x9x14x3 bot = next_start3 bot
+# asm 1: vldr <x4x9x14x3=reg128#7%bot,<next_start3=stack128#8
+# asm 2: vldr <x4x9x14x3=d12,<next_start3=[sp,#208]
+vldr d12,[sp,#208]
+
+# qhasm: x4x9x14x3 top = next_start3 top
+# asm 1: vldr <x4x9x14x3=reg128#7%top,<next_start3=stack128#8
+# asm 2: vldr <x4x9x14x3=d13,<next_start3=[sp,#216]
+vldr d13,[sp,#216]
+
+# qhasm: 4x x0x5x10x15 = next_diag0 + start0
+# asm 1: vadd.i32 >x0x5x10x15=reg128#2,<next_diag0=reg128#2,<start0=reg128#3
+# asm 2: vadd.i32 >x0x5x10x15=q1,<next_diag0=q1,<start0=q2
+vadd.i32 q1,q1,q2
+
+# qhasm: 4x x12x1x6x11 = next_diag1 + start1
+# asm 1: vadd.i32 >x12x1x6x11=reg128#5,<next_diag1=reg128#5,<start1=reg128#4
+# asm 2: vadd.i32 >x12x1x6x11=q4,<next_diag1=q4,<start1=q3
+vadd.i32 q4,q4,q3
+
+# qhasm: 4x x8x13x2x7 += next_diag2
+# asm 1: vadd.i32 >x8x13x2x7=reg128#6,<x8x13x2x7=reg128#6,<next_diag2=reg128#12
+# asm 2: vadd.i32 >x8x13x2x7=q5,<x8x13x2x7=q5,<next_diag2=q11
+vadd.i32 q5,q5,q11
+
+# qhasm: 4x x4x9x14x3 += next_diag3
+# asm 1: vadd.i32 >x4x9x14x3=reg128#7,<x4x9x14x3=reg128#7,<next_diag3=reg128#13
+# asm 2: vadd.i32 >x4x9x14x3=q6,<x4x9x14x3=q6,<next_diag3=q12
+vadd.i32 q6,q6,q12
+
+# qhasm: x0x1x10x11 = x0x5x10x15
+# asm 1: vmov >x0x1x10x11=reg128#8,<x0x5x10x15=reg128#2
+# asm 2: vmov >x0x1x10x11=q7,<x0x5x10x15=q1
+vmov q7,q1
+
+# qhasm: x12x13x6x7 = x12x1x6x11
+# asm 1: vmov >x12x13x6x7=reg128#9,<x12x1x6x11=reg128#5
+# asm 2: vmov >x12x13x6x7=q8,<x12x1x6x11=q4
+vmov q8,q4
+
+# qhasm: x8x9x2x3 = x8x13x2x7
+# asm 1: vmov >x8x9x2x3=reg128#10,<x8x13x2x7=reg128#6
+# asm 2: vmov >x8x9x2x3=q9,<x8x13x2x7=q5
+vmov q9,q5
+
+# qhasm: x4x5x14x15 = x4x9x14x3
+# asm 1: vmov >x4x5x14x15=reg128#12,<x4x9x14x3=reg128#7
+# asm 2: vmov >x4x5x14x15=q11,<x4x9x14x3=q6
+vmov q11,q6
+
+# qhasm: x0x1x10x11 = (abab & x0x1x10x11) | (~abab & x12x1x6x11)
+# asm 1: vbif <x0x1x10x11=reg128#8,<x12x1x6x11=reg128#5,<abab=reg128#11
+# asm 2: vbif <x0x1x10x11=q7,<x12x1x6x11=q4,<abab=q10
+vbif q7,q4,q10
+
+# qhasm: x12x13x6x7 = (abab & x12x13x6x7) | (~abab & x8x13x2x7)
+# asm 1: vbif <x12x13x6x7=reg128#9,<x8x13x2x7=reg128#6,<abab=reg128#11
+# asm 2: vbif <x12x13x6x7=q8,<x8x13x2x7=q5,<abab=q10
+vbif q8,q5,q10
+
+# qhasm: x8x9x2x3 = (abab & x8x9x2x3) | (~abab & x4x9x14x3)
+# asm 1: vbif <x8x9x2x3=reg128#10,<x4x9x14x3=reg128#7,<abab=reg128#11
+# asm 2: vbif <x8x9x2x3=q9,<x4x9x14x3=q6,<abab=q10
+vbif q9,q6,q10
+
+# qhasm: x4x5x14x15 = (abab & x4x5x14x15) | (~abab & x0x5x10x15)
+# asm 1: vbif <x4x5x14x15=reg128#12,<x0x5x10x15=reg128#2,<abab=reg128#11
+# asm 2: vbif <x4x5x14x15=q11,<x0x5x10x15=q1,<abab=q10
+vbif q11,q1,q10
+
+# qhasm: x0x1x2x3 = x0x1x10x11
+# asm 1: vmov >x0x1x2x3=reg128#2,<x0x1x10x11=reg128#8
+# asm 2: vmov >x0x1x2x3=q1,<x0x1x10x11=q7
+vmov q1,q7
+
+# qhasm: x4x5x6x7 = x4x5x14x15
+# asm 1: vmov >x4x5x6x7=reg128#5,<x4x5x14x15=reg128#12
+# asm 2: vmov >x4x5x6x7=q4,<x4x5x14x15=q11
+vmov q4,q11
+
+# qhasm: x8x9x10x11 = x8x9x2x3
+# asm 1: vmov >x8x9x10x11=reg128#6,<x8x9x2x3=reg128#10
+# asm 2: vmov >x8x9x10x11=q5,<x8x9x2x3=q9
+vmov q5,q9
+
+# qhasm: x12x13x14x15 = x12x13x6x7
+# asm 1: vmov >x12x13x14x15=reg128#7,<x12x13x6x7=reg128#9
+# asm 2: vmov >x12x13x14x15=q6,<x12x13x6x7=q8
+vmov q6,q8
+
+# qhasm: x0x1x2x3 = x0x1x2x3[0,1] x8x9x2x3[2,3]
+# asm 1: vmov <x0x1x2x3=reg128#2%top,<x8x9x2x3=reg128#10%top
+# asm 2: vmov <x0x1x2x3=d3,<x8x9x2x3=d19
+vmov d3,d19
+
+# qhasm: x4x5x6x7 = x4x5x6x7[0,1] x12x13x6x7[2,3]
+# asm 1: vmov <x4x5x6x7=reg128#5%top,<x12x13x6x7=reg128#9%top
+# asm 2: vmov <x4x5x6x7=d9,<x12x13x6x7=d17
+vmov d9,d17
+
+# qhasm: x8x9x10x11 = x8x9x10x11[0,1] x0x1x10x11[2,3]
+# asm 1: vmov <x8x9x10x11=reg128#6%top,<x0x1x10x11=reg128#8%top
+# asm 2: vmov <x8x9x10x11=d11,<x0x1x10x11=d15
+vmov d11,d15
+
+# qhasm: x12x13x14x15 = x12x13x14x15[0,1] x4x5x14x15[2,3]
+# asm 1: vmov <x12x13x14x15=reg128#7%top,<x4x5x14x15=reg128#12%top
+# asm 2: vmov <x12x13x14x15=d13,<x4x5x14x15=d23
+vmov d13,d23
+
+# qhasm: =? m - 0
+# asm 1: cmp <m=int32#2,#0
+# asm 2: cmp <m=r1,#0
+cmp r1,#0
+
+# qhasm: goto nomessage2next if =
+beq ._nomessage2next
+
+# qhasm: m0m1m2m3 = mem128[m]
+# asm 1: vld1.8 {>m0m1m2m3=reg128#8%bot->m0m1m2m3=reg128#8%top},[<m=int32#2]
+# asm 2: vld1.8 {>m0m1m2m3=d14->m0m1m2m3=d15},[<m=r1]
+vld1.8 {d14-d15},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m4m5m6m7 = mem128[m]
+# asm 1: vld1.8 {>m4m5m6m7=reg128#9%bot->m4m5m6m7=reg128#9%top},[<m=int32#2]
+# asm 2: vld1.8 {>m4m5m6m7=d16->m4m5m6m7=d17},[<m=r1]
+vld1.8 {d16-d17},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m8m9m10m11 = mem128[m]
+# asm 1: vld1.8 {>m8m9m10m11=reg128#10%bot->m8m9m10m11=reg128#10%top},[<m=int32#2]
+# asm 2: vld1.8 {>m8m9m10m11=d18->m8m9m10m11=d19},[<m=r1]
+vld1.8 {d18-d19},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m12m13m14m15 = mem128[m]
+# asm 1: vld1.8 {>m12m13m14m15=reg128#11%bot->m12m13m14m15=reg128#11%top},[<m=int32#2]
+# asm 2: vld1.8 {>m12m13m14m15=d20->m12m13m14m15=d21},[<m=r1]
+vld1.8 {d20-d21},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: x0x1x2x3 ^= m0m1m2m3
+# asm 1: veor >x0x1x2x3=reg128#2,<x0x1x2x3=reg128#2,<m0m1m2m3=reg128#8
+# asm 2: veor >x0x1x2x3=q1,<x0x1x2x3=q1,<m0m1m2m3=q7
+veor q1,q1,q7
+
+# qhasm: x4x5x6x7 ^= m4m5m6m7
+# asm 1: veor >x4x5x6x7=reg128#5,<x4x5x6x7=reg128#5,<m4m5m6m7=reg128#9
+# asm 2: veor >x4x5x6x7=q4,<x4x5x6x7=q4,<m4m5m6m7=q8
+veor q4,q4,q8
+
+# qhasm: x8x9x10x11 ^= m8m9m10m11
+# asm 1: veor >x8x9x10x11=reg128#6,<x8x9x10x11=reg128#6,<m8m9m10m11=reg128#10
+# asm 2: veor >x8x9x10x11=q5,<x8x9x10x11=q5,<m8m9m10m11=q9
+veor q5,q5,q9
+
+# qhasm: x12x13x14x15 ^= m12m13m14m15
+# asm 1: veor >x12x13x14x15=reg128#7,<x12x13x14x15=reg128#7,<m12m13m14m15=reg128#11
+# asm 2: veor >x12x13x14x15=q6,<x12x13x14x15=q6,<m12m13m14m15=q10
+veor q6,q6,q10
+
+# qhasm: nomessage2next:
+._nomessage2next:
+
+# qhasm: mem128[c] = x0x1x2x3
+# asm 1: vst1.8 {<x0x1x2x3=reg128#2%bot-<x0x1x2x3=reg128#2%top},[<c=int32#1]
+# asm 2: vst1.8 {<x0x1x2x3=d2-<x0x1x2x3=d3},[<c=r0]
+vst1.8 {d2-d3},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x4x5x6x7
+# asm 1: vst1.8 {<x4x5x6x7=reg128#5%bot-<x4x5x6x7=reg128#5%top},[<c=int32#1]
+# asm 2: vst1.8 {<x4x5x6x7=d8-<x4x5x6x7=d9},[<c=r0]
+vst1.8 {d8-d9},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x8x9x10x11
+# asm 1: vst1.8 {<x8x9x10x11=reg128#6%bot-<x8x9x10x11=reg128#6%top},[<c=int32#1]
+# asm 2: vst1.8 {<x8x9x10x11=d10-<x8x9x10x11=d11},[<c=r0]
+vst1.8 {d10-d11},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x12x13x14x15
+# asm 1: vst1.8 {<x12x13x14x15=reg128#7%bot-<x12x13x14x15=reg128#7%top},[<c=int32#1]
+# asm 2: vst1.8 {<x12x13x14x15=d12-<x12x13x14x15=d13},[<c=r0]
+vst1.8 {d12-d13},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: carry? mlenlow -= 128
+# asm 1: subs <mlenlow=int32#3,<mlenlow=int32#3,#128
+# asm 2: subs <mlenlow=r2,<mlenlow=r2,#128
+subs r2,r2,#128
+
+# qhasm: mlenhigh -= 0 - carry
+# asm 1: sbc <mlenhigh=int32#4,<mlenhigh=int32#4,#0
+# asm 2: sbc <mlenhigh=r3,<mlenhigh=r3,#0
+sbc r3,r3,#0
+
+# qhasm: unsigned<? mlenlow - 128
+# asm 1: cmp <mlenlow=int32#3,#128
+# asm 2: cmp <mlenlow=r2,#128
+cmp r2,#128
+
+# qhasm: goto mlenatleast128 if !unsigned<
+bhs ._mlenatleast128
+
+# qhasm: mlenlowbelow128:
+._mlenlowbelow128:
+
+# qhasm: unsigned>? mlenhigh - 0
+# asm 1: cmp <mlenhigh=int32#4,#0
+# asm 2: cmp <mlenhigh=r3,#0
+cmp r3,#0
+
+# qhasm: goto mlenatleast128 if unsigned>
+bhi ._mlenatleast128
+
+# qhasm: =? mlenlow - 0
+# asm 1: cmp <mlenlow=int32#3,#0
+# asm 2: cmp <mlenlow=r2,#0
+cmp r2,#0
+
+# qhasm: goto done if =
+beq ._done
+
+# qhasm: mlenatleast1:
+._mlenatleast1:
+
+# qhasm: unsigned<? mlenlow - 64
+# asm 1: cmp <mlenlow=int32#3,#64
+# asm 2: cmp <mlenlow=r2,#64
+cmp r2,#64
+
+# qhasm: goto mlenatleast64 if !unsigned<
+bhs ._mlenatleast64
+
+# qhasm: savec = c
+# asm 1: str <c=int32#1,>savec=stack32#1
+# asm 2: str <c=r0,>savec=[sp,#64]
+str r0,[sp,#64]
+
+# qhasm: c = &tmp
+# asm 1: lea >c=int32#1,<tmp=stack512#1
+# asm 2: lea >c=r0,<tmp=[sp,#0]
+add r0,sp,#0
+
+# qhasm: =? m - 0
+# asm 1: cmp <m=int32#2,#0
+# asm 2: cmp <m=r1,#0
+cmp r1,#0
+
+# qhasm: goto mlenatleast64 if =
+beq ._mlenatleast64
+
+# qhasm: i = 0
+# asm 1: ldr >i=int32#4,=0
+# asm 2: ldr >i=r3,=0
+ldr r3,=0
+
+# qhasm: mcopy:
+._mcopy:
+
+# qhasm: mi = mem8[m + 0]
+# asm 1: ldrb >mi=int32#5,[<m=int32#2,#0]
+# asm 2: ldrb >mi=r4,[<m=r1,#0]
+ldrb r4,[r1,#0]
+
+# qhasm: mem8[c + 0] = mi
+# asm 1: strb <mi=int32#5,[<c=int32#1,#0]
+# asm 2: strb <mi=r4,[<c=r0,#0]
+strb r4,[r0,#0]
+
+# qhasm: m += 1
+# asm 1: add <m=int32#2,<m=int32#2,#1
+# asm 2: add <m=r1,<m=r1,#1
+add r1,r1,#1
+
+# qhasm: c += 1
+# asm 1: add <c=int32#1,<c=int32#1,#1
+# asm 2: add <c=r0,<c=r0,#1
+add r0,r0,#1
+
+# qhasm: i += 1
+# asm 1: add <i=int32#4,<i=int32#4,#1
+# asm 2: add <i=r3,<i=r3,#1
+add r3,r3,#1
+
+# qhasm: unsigned<? i - mlenlow
+# asm 1: cmp <i=int32#4,<mlenlow=int32#3
+# asm 2: cmp <i=r3,<mlenlow=r2
+cmp r3,r2
+
+# qhasm: goto mcopy if unsigned<
+blo ._mcopy
+
+# qhasm: mi = 0
+# asm 1: ldr >mi=int32#2,=0
+# asm 2: ldr >mi=r1,=0
+ldr r1,=0
+
+# qhasm: pad:
+._pad:
+
+# qhasm: mem8[c + 0] = mi
+# asm 1: strb <mi=int32#2,[<c=int32#1,#0]
+# asm 2: strb <mi=r1,[<c=r0,#0]
+strb r1,[r0,#0]
+
+# qhasm: c += 1
+# asm 1: add <c=int32#1,<c=int32#1,#1
+# asm 2: add <c=r0,<c=r0,#1
+add r0,r0,#1
+
+# qhasm: i += 1
+# asm 1: add <i=int32#4,<i=int32#4,#1
+# asm 2: add <i=r3,<i=r3,#1
+add r3,r3,#1
+
+# qhasm: unsigned<? i - 64
+# asm 1: cmp <i=int32#4,#64
+# asm 2: cmp <i=r3,#64
+cmp r3,#64
+
+# qhasm: goto pad if unsigned<
+blo ._pad
+
+# qhasm: c -= 64
+# asm 1: sub <c=int32#1,<c=int32#1,#64
+# asm 2: sub <c=r0,<c=r0,#64
+sub r0,r0,#64
+
+# qhasm: m = &tmp
+# asm 1: lea >m=int32#2,<tmp=stack512#1
+# asm 2: lea >m=r1,<tmp=[sp,#0]
+add r1,sp,#0
+
+# qhasm: mlenatleast64:
+._mlenatleast64:
+
+# qhasm: new k2k3k6k7
+
+# qhasm: k2k3k6k7 bot = k2k3k6k7_stack bot
+# asm 1: vldr <k2k3k6k7=reg128#2%bot,<k2k3k6k7_stack=stack128#5
+# asm 2: vldr <k2k3k6k7=d2,<k2k3k6k7_stack=[sp,#160]
+vldr d2,[sp,#160]
+
+# qhasm: k2k3k6k7 top = k2k3k6k7_stack top
+# asm 1: vldr <k2k3k6k7=reg128#2%top,<k2k3k6k7_stack=stack128#5
+# asm 2: vldr <k2k3k6k7=d3,<k2k3k6k7_stack=[sp,#168]
+vldr d3,[sp,#168]
+
+# qhasm: new k1n1k7k2
+
+# qhasm: k1n1k7k2 bot = k1n1k7k2_stack bot
+# asm 1: vldr <k1n1k7k2=reg128#5%bot,<k1n1k7k2_stack=stack128#6
+# asm 2: vldr <k1n1k7k2=d8,<k1n1k7k2_stack=[sp,#176]
+vldr d8,[sp,#176]
+
+# qhasm: k1n1k7k2 top = k1n1k7k2_stack top
+# asm 1: vldr <k1n1k7k2=reg128#5%top,<k1n1k7k2_stack=stack128#6
+# asm 2: vldr <k1n1k7k2=d9,<k1n1k7k2_stack=[sp,#184]
+vldr d9,[sp,#184]
+
+# qhasm: n2n3n3n2 = n2n3n3n2[0,1] n2n3n3n2[1] n2n3n3n2[0]
+# asm 1: vext.32 <n2n3n3n2=reg128#1%top,<n2n3n3n2=reg128#1%bot,<n2n3n3n2=reg128#1%bot,#1
+# asm 2: vext.32 <n2n3n3n2=d1,<n2n3n3n2=d0,<n2n3n3n2=d0,#1
+vext.32 d1,d0,d0,#1
+
+# qhasm: new start2
+
+# qhasm: start2 = start2[0,1] k1n1k7k2[0,1]
+# asm 1: vmov <start2=reg128#6%top,<k1n1k7k2=reg128#5%bot
+# asm 2: vmov <start2=d11,<k1n1k7k2=d8
+vmov d11,d8
+
+# qhasm: start2 = n2n3n3n2[3] k2k3k6k7[2] start2[2,3]
+# asm 1: vext.32 <start2=reg128#6%bot,<n2n3n3n2=reg128#1%top,<k2k3k6k7=reg128#2%top,#1
+# asm 2: vext.32 <start2=d10,<n2n3n3n2=d1,<k2k3k6k7=d3,#1
+vext.32 d10,d1,d3,#1
+
+# qhasm: new start3
+
+# qhasm: start3 = start3[0,1] k1n1k7k2[2,3]
+# asm 1: vmov <start3=reg128#7%top,<k1n1k7k2=reg128#5%top
+# asm 2: vmov <start3=d13,<k1n1k7k2=d9
+vmov d13,d9
+
+# qhasm: start3 = k2k3k6k7[1] n2n3n3n2[2] start3[2,3]
+# asm 1: vext.32 <start3=reg128#7%bot,<k2k3k6k7=reg128#2%bot,<n2n3n3n2=reg128#1%top,#1
+# asm 2: vext.32 <start3=d12,<k2k3k6k7=d2,<n2n3n3n2=d1,#1
+vext.32 d12,d2,d1,#1
+
+# qhasm: diag0 = start0
+# asm 1: vmov >diag0=reg128#2,<start0=reg128#3
+# asm 2: vmov >diag0=q1,<start0=q2
+vmov q1,q2
+
+# qhasm: diag1 = start1
+# asm 1: vmov >diag1=reg128#5,<start1=reg128#4
+# asm 2: vmov >diag1=q4,<start1=q3
+vmov q4,q3
+
+# qhasm: diag2 = start2
+# asm 1: vmov >diag2=reg128#8,<start2=reg128#6
+# asm 2: vmov >diag2=q7,<start2=q5
+vmov q7,q5
+
+# qhasm: diag3 = start3
+# asm 1: vmov >diag3=reg128#9,<start3=reg128#7
+# asm 2: vmov >diag3=q8,<start3=q6
+vmov q8,q6
+
+# qhasm: 2x nextblock = 0xff
+# asm 1: vmov.i64 >nextblock=reg128#10,#0xff
+# asm 2: vmov.i64 >nextblock=q9,#0xff
+vmov.i64 q9,#0xff
+
+# qhasm: 4x nextblock unsigned>>= 7
+# asm 1: vshr.u32 >nextblock=reg128#10,<nextblock=reg128#10,#7
+# asm 2: vshr.u32 >nextblock=q9,<nextblock=q9,#7
+vshr.u32 q9,q9,#7
+
+# qhasm: 2x n2n3n3n2 += nextblock
+# asm 1: vadd.i64 >n2n3n3n2=reg128#1,<n2n3n3n2=reg128#1,<nextblock=reg128#10
+# asm 2: vadd.i64 >n2n3n3n2=q0,<n2n3n3n2=q0,<nextblock=q9
+vadd.i64 q0,q0,q9
+
+# qhasm: i = 12
+# asm 1: ldr >i=int32#4,=12
+# asm 2: ldr >i=r3,=12
+ldr r3,=12
+
+# qhasm: mainloop1:
+._mainloop1:
+
+# qhasm: 4x a0 = diag1 + diag0
+# asm 1: vadd.i32 >a0=reg128#10,<diag1=reg128#5,<diag0=reg128#2
+# asm 2: vadd.i32 >a0=q9,<diag1=q4,<diag0=q1
+vadd.i32 q9,q4,q1
+
+# qhasm: 4x b0 = a0 << 7
+# asm 1: vshl.i32 >b0=reg128#11,<a0=reg128#10,#7
+# asm 2: vshl.i32 >b0=q10,<a0=q9,#7
+vshl.i32 q10,q9,#7
+
+# qhasm: 4x b0 insert= a0 >> 25
+# asm 1: vsri.i32 <b0=reg128#11,<a0=reg128#10,#25
+# asm 2: vsri.i32 <b0=q10,<a0=q9,#25
+vsri.i32 q10,q9,#25
+
+# qhasm: diag3 ^= b0
+# asm 1: veor >diag3=reg128#9,<diag3=reg128#9,<b0=reg128#11
+# asm 2: veor >diag3=q8,<diag3=q8,<b0=q10
+veor q8,q8,q10
+
+# qhasm: 4x a1 = diag0 + diag3
+# asm 1: vadd.i32 >a1=reg128#10,<diag0=reg128#2,<diag3=reg128#9
+# asm 2: vadd.i32 >a1=q9,<diag0=q1,<diag3=q8
+vadd.i32 q9,q1,q8
+
+# qhasm: 4x b1 = a1 << 9
+# asm 1: vshl.i32 >b1=reg128#11,<a1=reg128#10,#9
+# asm 2: vshl.i32 >b1=q10,<a1=q9,#9
+vshl.i32 q10,q9,#9
+
+# qhasm: 4x b1 insert= a1 >> 23
+# asm 1: vsri.i32 <b1=reg128#11,<a1=reg128#10,#23
+# asm 2: vsri.i32 <b1=q10,<a1=q9,#23
+vsri.i32 q10,q9,#23
+
+# qhasm: diag2 ^= b1
+# asm 1: veor >diag2=reg128#8,<diag2=reg128#8,<b1=reg128#11
+# asm 2: veor >diag2=q7,<diag2=q7,<b1=q10
+veor q7,q7,q10
+
+# qhasm: 4x a2 = diag3 + diag2
+# asm 1: vadd.i32 >a2=reg128#10,<diag3=reg128#9,<diag2=reg128#8
+# asm 2: vadd.i32 >a2=q9,<diag3=q8,<diag2=q7
+vadd.i32 q9,q8,q7
+
+# qhasm: diag3 = diag3[3] diag3[0,1,2]
+# asm 1: vext.32 >diag3=reg128#9,<diag3=reg128#9,<diag3=reg128#9,#3
+# asm 2: vext.32 >diag3=q8,<diag3=q8,<diag3=q8,#3
+vext.32 q8,q8,q8,#3
+
+# qhasm: 4x b2 = a2 << 13
+# asm 1: vshl.i32 >b2=reg128#11,<a2=reg128#10,#13
+# asm 2: vshl.i32 >b2=q10,<a2=q9,#13
+vshl.i32 q10,q9,#13
+
+# qhasm: 4x b2 insert= a2 >> 19
+# asm 1: vsri.i32 <b2=reg128#11,<a2=reg128#10,#19
+# asm 2: vsri.i32 <b2=q10,<a2=q9,#19
+vsri.i32 q10,q9,#19
+
+# qhasm: diag1 ^= b2
+# asm 1: veor >diag1=reg128#5,<diag1=reg128#5,<b2=reg128#11
+# asm 2: veor >diag1=q4,<diag1=q4,<b2=q10
+veor q4,q4,q10
+
+# qhasm: 4x a3 = diag2 + diag1
+# asm 1: vadd.i32 >a3=reg128#10,<diag2=reg128#8,<diag1=reg128#5
+# asm 2: vadd.i32 >a3=q9,<diag2=q7,<diag1=q4
+vadd.i32 q9,q7,q4
+
+# qhasm: diag2 = diag2[2,3] diag2[0,1]
+# asm 1: vswp <diag2=reg128#8%bot,<diag2=reg128#8%top
+# asm 2: vswp <diag2=d14,<diag2=d15
+vswp d14,d15
+
+# qhasm: 4x b3 = a3 << 18
+# asm 1: vshl.i32 >b3=reg128#11,<a3=reg128#10,#18
+# asm 2: vshl.i32 >b3=q10,<a3=q9,#18
+vshl.i32 q10,q9,#18
+
+# qhasm: 4x b3 insert= a3 >> 14
+# asm 1: vsri.i32 <b3=reg128#11,<a3=reg128#10,#14
+# asm 2: vsri.i32 <b3=q10,<a3=q9,#14
+vsri.i32 q10,q9,#14
+
+# qhasm: diag1 = diag1[1,2,3] diag1[0]
+# asm 1: vext.32 >diag1=reg128#5,<diag1=reg128#5,<diag1=reg128#5,#1
+# asm 2: vext.32 >diag1=q4,<diag1=q4,<diag1=q4,#1
+vext.32 q4,q4,q4,#1
+
+# qhasm: diag0 ^= b3
+# asm 1: veor >diag0=reg128#2,<diag0=reg128#2,<b3=reg128#11
+# asm 2: veor >diag0=q1,<diag0=q1,<b3=q10
+veor q1,q1,q10
+
+# qhasm: 4x a0 = diag3 + diag0
+# asm 1: vadd.i32 >a0=reg128#10,<diag3=reg128#9,<diag0=reg128#2
+# asm 2: vadd.i32 >a0=q9,<diag3=q8,<diag0=q1
+vadd.i32 q9,q8,q1
+
+# qhasm: 4x b0 = a0 << 7
+# asm 1: vshl.i32 >b0=reg128#11,<a0=reg128#10,#7
+# asm 2: vshl.i32 >b0=q10,<a0=q9,#7
+vshl.i32 q10,q9,#7
+
+# qhasm: 4x b0 insert= a0 >> 25
+# asm 1: vsri.i32 <b0=reg128#11,<a0=reg128#10,#25
+# asm 2: vsri.i32 <b0=q10,<a0=q9,#25
+vsri.i32 q10,q9,#25
+
+# qhasm: diag1 ^= b0
+# asm 1: veor >diag1=reg128#5,<diag1=reg128#5,<b0=reg128#11
+# asm 2: veor >diag1=q4,<diag1=q4,<b0=q10
+veor q4,q4,q10
+
+# qhasm: 4x a1 = diag0 + diag1
+# asm 1: vadd.i32 >a1=reg128#10,<diag0=reg128#2,<diag1=reg128#5
+# asm 2: vadd.i32 >a1=q9,<diag0=q1,<diag1=q4
+vadd.i32 q9,q1,q4
+
+# qhasm: 4x b1 = a1 << 9
+# asm 1: vshl.i32 >b1=reg128#11,<a1=reg128#10,#9
+# asm 2: vshl.i32 >b1=q10,<a1=q9,#9
+vshl.i32 q10,q9,#9
+
+# qhasm: 4x b1 insert= a1 >> 23
+# asm 1: vsri.i32 <b1=reg128#11,<a1=reg128#10,#23
+# asm 2: vsri.i32 <b1=q10,<a1=q9,#23
+vsri.i32 q10,q9,#23
+
+# qhasm: unsigned>? i -= 2
+# asm 1: subs <i=int32#4,<i=int32#4,#2
+# asm 2: subs <i=r3,<i=r3,#2
+subs r3,r3,#2
+
+# qhasm: diag2 ^= b1
+# asm 1: veor >diag2=reg128#8,<diag2=reg128#8,<b1=reg128#11
+# asm 2: veor >diag2=q7,<diag2=q7,<b1=q10
+veor q7,q7,q10
+
+# qhasm: 4x a2 = diag1 + diag2
+# asm 1: vadd.i32 >a2=reg128#10,<diag1=reg128#5,<diag2=reg128#8
+# asm 2: vadd.i32 >a2=q9,<diag1=q4,<diag2=q7
+vadd.i32 q9,q4,q7
+
+# qhasm: diag1 = diag1[3] diag1[0,1,2]
+# asm 1: vext.32 >diag1=reg128#5,<diag1=reg128#5,<diag1=reg128#5,#3
+# asm 2: vext.32 >diag1=q4,<diag1=q4,<diag1=q4,#3
+vext.32 q4,q4,q4,#3
+
+# qhasm: 4x b2 = a2 << 13
+# asm 1: vshl.i32 >b2=reg128#11,<a2=reg128#10,#13
+# asm 2: vshl.i32 >b2=q10,<a2=q9,#13
+vshl.i32 q10,q9,#13
+
+# qhasm: 4x b2 insert= a2 >> 19
+# asm 1: vsri.i32 <b2=reg128#11,<a2=reg128#10,#19
+# asm 2: vsri.i32 <b2=q10,<a2=q9,#19
+vsri.i32 q10,q9,#19
+
+# qhasm: diag3 ^= b2
+# asm 1: veor >diag3=reg128#9,<diag3=reg128#9,<b2=reg128#11
+# asm 2: veor >diag3=q8,<diag3=q8,<b2=q10
+veor q8,q8,q10
+
+# qhasm: 4x a3 = diag2 + diag3
+# asm 1: vadd.i32 >a3=reg128#10,<diag2=reg128#8,<diag3=reg128#9
+# asm 2: vadd.i32 >a3=q9,<diag2=q7,<diag3=q8
+vadd.i32 q9,q7,q8
+
+# qhasm: diag2 = diag2[2,3] diag2[0,1]
+# asm 1: vswp <diag2=reg128#8%bot,<diag2=reg128#8%top
+# asm 2: vswp <diag2=d14,<diag2=d15
+vswp d14,d15
+
+# qhasm: 4x b3 = a3 << 18
+# asm 1: vshl.i32 >b3=reg128#11,<a3=reg128#10,#18
+# asm 2: vshl.i32 >b3=q10,<a3=q9,#18
+vshl.i32 q10,q9,#18
+
+# qhasm: 4x b3 insert= a3 >> 14
+# asm 1: vsri.i32 <b3=reg128#11,<a3=reg128#10,#14
+# asm 2: vsri.i32 <b3=q10,<a3=q9,#14
+vsri.i32 q10,q9,#14
+
+# qhasm: diag3 = diag3[1,2,3] diag3[0]
+# asm 1: vext.32 >diag3=reg128#9,<diag3=reg128#9,<diag3=reg128#9,#1
+# asm 2: vext.32 >diag3=q8,<diag3=q8,<diag3=q8,#1
+vext.32 q8,q8,q8,#1
+
+# qhasm: diag0 ^= b3
+# asm 1: veor >diag0=reg128#2,<diag0=reg128#2,<b3=reg128#11
+# asm 2: veor >diag0=q1,<diag0=q1,<b3=q10
+veor q1,q1,q10
+
+# qhasm: goto mainloop1 if unsigned>
+bhi ._mainloop1
+
+# qhasm: 2x abab = 0xffffffff
+# asm 1: vmov.i64 >abab=reg128#10,#0xffffffff
+# asm 2: vmov.i64 >abab=q9,#0xffffffff
+vmov.i64 q9,#0xffffffff
+
+# qhasm: 4x x0x5x10x15 = diag0 + start0
+# asm 1: vadd.i32 >x0x5x10x15=reg128#2,<diag0=reg128#2,<start0=reg128#3
+# asm 2: vadd.i32 >x0x5x10x15=q1,<diag0=q1,<start0=q2
+vadd.i32 q1,q1,q2
+
+# qhasm: 4x x12x1x6x11 = diag1 + start1
+# asm 1: vadd.i32 >x12x1x6x11=reg128#5,<diag1=reg128#5,<start1=reg128#4
+# asm 2: vadd.i32 >x12x1x6x11=q4,<diag1=q4,<start1=q3
+vadd.i32 q4,q4,q3
+
+# qhasm: 4x x8x13x2x7 = diag2 + start2
+# asm 1: vadd.i32 >x8x13x2x7=reg128#6,<diag2=reg128#8,<start2=reg128#6
+# asm 2: vadd.i32 >x8x13x2x7=q5,<diag2=q7,<start2=q5
+vadd.i32 q5,q7,q5
+
+# qhasm: 4x x4x9x14x3 = diag3 + start3
+# asm 1: vadd.i32 >x4x9x14x3=reg128#7,<diag3=reg128#9,<start3=reg128#7
+# asm 2: vadd.i32 >x4x9x14x3=q6,<diag3=q8,<start3=q6
+vadd.i32 q6,q8,q6
+
+# qhasm: x0x1x10x11 = x0x5x10x15
+# asm 1: vmov >x0x1x10x11=reg128#8,<x0x5x10x15=reg128#2
+# asm 2: vmov >x0x1x10x11=q7,<x0x5x10x15=q1
+vmov q7,q1
+
+# qhasm: x12x13x6x7 = x12x1x6x11
+# asm 1: vmov >x12x13x6x7=reg128#9,<x12x1x6x11=reg128#5
+# asm 2: vmov >x12x13x6x7=q8,<x12x1x6x11=q4
+vmov q8,q4
+
+# qhasm: x8x9x2x3 = x8x13x2x7
+# asm 1: vmov >x8x9x2x3=reg128#11,<x8x13x2x7=reg128#6
+# asm 2: vmov >x8x9x2x3=q10,<x8x13x2x7=q5
+vmov q10,q5
+
+# qhasm: x4x5x14x15 = x4x9x14x3
+# asm 1: vmov >x4x5x14x15=reg128#12,<x4x9x14x3=reg128#7
+# asm 2: vmov >x4x5x14x15=q11,<x4x9x14x3=q6
+vmov q11,q6
+
+# qhasm: x0x1x10x11 = (abab & x0x1x10x11) | (~abab & x12x1x6x11)
+# asm 1: vbif <x0x1x10x11=reg128#8,<x12x1x6x11=reg128#5,<abab=reg128#10
+# asm 2: vbif <x0x1x10x11=q7,<x12x1x6x11=q4,<abab=q9
+vbif q7,q4,q9
+
+# qhasm: x12x13x6x7 = (abab & x12x13x6x7) | (~abab & x8x13x2x7)
+# asm 1: vbif <x12x13x6x7=reg128#9,<x8x13x2x7=reg128#6,<abab=reg128#10
+# asm 2: vbif <x12x13x6x7=q8,<x8x13x2x7=q5,<abab=q9
+vbif q8,q5,q9
+
+# qhasm: x8x9x2x3 = (abab & x8x9x2x3) | (~abab & x4x9x14x3)
+# asm 1: vbif <x8x9x2x3=reg128#11,<x4x9x14x3=reg128#7,<abab=reg128#10
+# asm 2: vbif <x8x9x2x3=q10,<x4x9x14x3=q6,<abab=q9
+vbif q10,q6,q9
+
+# qhasm: x4x5x14x15 = (abab & x4x5x14x15) | (~abab & x0x5x10x15)
+# asm 1: vbif <x4x5x14x15=reg128#12,<x0x5x10x15=reg128#2,<abab=reg128#10
+# asm 2: vbif <x4x5x14x15=q11,<x0x5x10x15=q1,<abab=q9
+vbif q11,q1,q9
+
+# qhasm: x0x1x2x3 = x0x1x10x11
+# asm 1: vmov >x0x1x2x3=reg128#2,<x0x1x10x11=reg128#8
+# asm 2: vmov >x0x1x2x3=q1,<x0x1x10x11=q7
+vmov q1,q7
+
+# qhasm: x4x5x6x7 = x4x5x14x15
+# asm 1: vmov >x4x5x6x7=reg128#5,<x4x5x14x15=reg128#12
+# asm 2: vmov >x4x5x6x7=q4,<x4x5x14x15=q11
+vmov q4,q11
+
+# qhasm: x8x9x10x11 = x8x9x2x3
+# asm 1: vmov >x8x9x10x11=reg128#6,<x8x9x2x3=reg128#11
+# asm 2: vmov >x8x9x10x11=q5,<x8x9x2x3=q10
+vmov q5,q10
+
+# qhasm: x12x13x14x15 = x12x13x6x7
+# asm 1: vmov >x12x13x14x15=reg128#7,<x12x13x6x7=reg128#9
+# asm 2: vmov >x12x13x14x15=q6,<x12x13x6x7=q8
+vmov q6,q8
+
+# qhasm: x0x1x2x3 = x0x1x2x3[0,1] x8x9x2x3[2,3]
+# asm 1: vmov <x0x1x2x3=reg128#2%top,<x8x9x2x3=reg128#11%top
+# asm 2: vmov <x0x1x2x3=d3,<x8x9x2x3=d21
+vmov d3,d21
+
+# qhasm: x4x5x6x7 = x4x5x6x7[0,1] x12x13x6x7[2,3]
+# asm 1: vmov <x4x5x6x7=reg128#5%top,<x12x13x6x7=reg128#9%top
+# asm 2: vmov <x4x5x6x7=d9,<x12x13x6x7=d17
+vmov d9,d17
+
+# qhasm: x8x9x10x11 = x8x9x10x11[0,1] x0x1x10x11[2,3]
+# asm 1: vmov <x8x9x10x11=reg128#6%top,<x0x1x10x11=reg128#8%top
+# asm 2: vmov <x8x9x10x11=d11,<x0x1x10x11=d15
+vmov d11,d15
+
+# qhasm: x12x13x14x15 = x12x13x14x15[0,1] x4x5x14x15[2,3]
+# asm 1: vmov <x12x13x14x15=reg128#7%top,<x4x5x14x15=reg128#12%top
+# asm 2: vmov <x12x13x14x15=d13,<x4x5x14x15=d23
+vmov d13,d23
+
+# qhasm: =? m - 0
+# asm 1: cmp <m=int32#2,#0
+# asm 2: cmp <m=r1,#0
+cmp r1,#0
+
+# qhasm: goto nomessage1 if =
+beq ._nomessage1
+
+# qhasm: m0m1m2m3 = mem128[m]
+# asm 1: vld1.8 {>m0m1m2m3=reg128#8%bot->m0m1m2m3=reg128#8%top},[<m=int32#2]
+# asm 2: vld1.8 {>m0m1m2m3=d14->m0m1m2m3=d15},[<m=r1]
+vld1.8 {d14-d15},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m4m5m6m7 = mem128[m]
+# asm 1: vld1.8 {>m4m5m6m7=reg128#9%bot->m4m5m6m7=reg128#9%top},[<m=int32#2]
+# asm 2: vld1.8 {>m4m5m6m7=d16->m4m5m6m7=d17},[<m=r1]
+vld1.8 {d16-d17},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m8m9m10m11 = mem128[m]
+# asm 1: vld1.8 {>m8m9m10m11=reg128#10%bot->m8m9m10m11=reg128#10%top},[<m=int32#2]
+# asm 2: vld1.8 {>m8m9m10m11=d18->m8m9m10m11=d19},[<m=r1]
+vld1.8 {d18-d19},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: m12m13m14m15 = mem128[m]
+# asm 1: vld1.8 {>m12m13m14m15=reg128#11%bot->m12m13m14m15=reg128#11%top},[<m=int32#2]
+# asm 2: vld1.8 {>m12m13m14m15=d20->m12m13m14m15=d21},[<m=r1]
+vld1.8 {d20-d21},[r1]
+
+# qhasm: m += 16
+# asm 1: add <m=int32#2,<m=int32#2,#16
+# asm 2: add <m=r1,<m=r1,#16
+add r1,r1,#16
+
+# qhasm: x0x1x2x3 ^= m0m1m2m3
+# asm 1: veor >x0x1x2x3=reg128#2,<x0x1x2x3=reg128#2,<m0m1m2m3=reg128#8
+# asm 2: veor >x0x1x2x3=q1,<x0x1x2x3=q1,<m0m1m2m3=q7
+veor q1,q1,q7
+
+# qhasm: x4x5x6x7 ^= m4m5m6m7
+# asm 1: veor >x4x5x6x7=reg128#5,<x4x5x6x7=reg128#5,<m4m5m6m7=reg128#9
+# asm 2: veor >x4x5x6x7=q4,<x4x5x6x7=q4,<m4m5m6m7=q8
+veor q4,q4,q8
+
+# qhasm: x8x9x10x11 ^= m8m9m10m11
+# asm 1: veor >x8x9x10x11=reg128#6,<x8x9x10x11=reg128#6,<m8m9m10m11=reg128#10
+# asm 2: veor >x8x9x10x11=q5,<x8x9x10x11=q5,<m8m9m10m11=q9
+veor q5,q5,q9
+
+# qhasm: x12x13x14x15 ^= m12m13m14m15
+# asm 1: veor >x12x13x14x15=reg128#7,<x12x13x14x15=reg128#7,<m12m13m14m15=reg128#11
+# asm 2: veor >x12x13x14x15=q6,<x12x13x14x15=q6,<m12m13m14m15=q10
+veor q6,q6,q10
+
+# qhasm: nomessage1:
+._nomessage1:
+
+# qhasm: mem128[c] = x0x1x2x3
+# asm 1: vst1.8 {<x0x1x2x3=reg128#2%bot-<x0x1x2x3=reg128#2%top},[<c=int32#1]
+# asm 2: vst1.8 {<x0x1x2x3=d2-<x0x1x2x3=d3},[<c=r0]
+vst1.8 {d2-d3},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x4x5x6x7
+# asm 1: vst1.8 {<x4x5x6x7=reg128#5%bot-<x4x5x6x7=reg128#5%top},[<c=int32#1]
+# asm 2: vst1.8 {<x4x5x6x7=d8-<x4x5x6x7=d9},[<c=r0]
+vst1.8 {d8-d9},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x8x9x10x11
+# asm 1: vst1.8 {<x8x9x10x11=reg128#6%bot-<x8x9x10x11=reg128#6%top},[<c=int32#1]
+# asm 2: vst1.8 {<x8x9x10x11=d10-<x8x9x10x11=d11},[<c=r0]
+vst1.8 {d10-d11},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: mem128[c] = x12x13x14x15
+# asm 1: vst1.8 {<x12x13x14x15=reg128#7%bot-<x12x13x14x15=reg128#7%top},[<c=int32#1]
+# asm 2: vst1.8 {<x12x13x14x15=d12-<x12x13x14x15=d13},[<c=r0]
+vst1.8 {d12-d13},[r0]
+
+# qhasm: c += 16
+# asm 1: add <c=int32#1,<c=int32#1,#16
+# asm 2: add <c=r0,<c=r0,#16
+add r0,r0,#16
+
+# qhasm: unsigned<? mlenlow - 64
+# asm 1: cmp <mlenlow=int32#3,#64
+# asm 2: cmp <mlenlow=r2,#64
+cmp r2,#64
+
+# qhasm: goto xmlenatleast64 if !unsigned<
+bhs ._xmlenatleast64
+
+# qhasm: i = 0
+# asm 1: ldr >i=int32#4,=0
+# asm 2: ldr >i=r3,=0
+ldr r3,=0
+
+# qhasm: m = c - 64
+# asm 1: sub >m=int32#2,<c=int32#1,#64
+# asm 2: sub >m=r1,<c=r0,#64
+sub r1,r0,#64
+
+# qhasm: c = savec
+# asm 1: ldr >c=int32#1,<savec=stack32#1
+# asm 2: ldr >c=r0,<savec=[sp,#64]
+ldr r0,[sp,#64]
+
+# qhasm: ccopy:
+._ccopy:
+
+# qhasm: ci = mem8[m + 0]
+# asm 1: ldrb >ci=int32#5,[<m=int32#2,#0]
+# asm 2: ldrb >ci=r4,[<m=r1,#0]
+ldrb r4,[r1,#0]
+
+# qhasm: mem8[c + 0] = ci
+# asm 1: strb <ci=int32#5,[<c=int32#1,#0]
+# asm 2: strb <ci=r4,[<c=r0,#0]
+strb r4,[r0,#0]
+
+# qhasm: m += 1
+# asm 1: add <m=int32#2,<m=int32#2,#1
+# asm 2: add <m=r1,<m=r1,#1
+add r1,r1,#1
+
+# qhasm: c += 1
+# asm 1: add <c=int32#1,<c=int32#1,#1
+# asm 2: add <c=r0,<c=r0,#1
+add r0,r0,#1
+
+# qhasm: i += 1
+# asm 1: add <i=int32#4,<i=int32#4,#1
+# asm 2: add <i=r3,<i=r3,#1
+add r3,r3,#1
+
+# qhasm: unsigned<? i - mlenlow
+# asm 1: cmp <i=int32#4,<mlenlow=int32#3
+# asm 2: cmp <i=r3,<mlenlow=r2
+cmp r3,r2
+
+# qhasm: goto ccopy if unsigned<
+blo ._ccopy
+
+# qhasm: xmlenatleast64:
+._xmlenatleast64:
+
+# qhasm: unsigned>? mlenlow -= 64
+# asm 1: subs <mlenlow=int32#3,<mlenlow=int32#3,#64
+# asm 2: subs <mlenlow=r2,<mlenlow=r2,#64
+subs r2,r2,#64
+
+# qhasm: goto mlenatleast1 if unsigned>
+bhi ._mlenatleast1
+
+# qhasm: done:
+._done:
+
+# qhasm: new caller_r4
+
+# qhasm: caller_r4 = stack_r4
+# asm 1: ldr >caller_r4=int32#5,<stack_r4=stack32#2
+# asm 2: ldr >caller_r4=r4,<stack_r4=[sp,#68]
+ldr r4,[sp,#68]
+
+# qhasm: new caller_q4
+
+# qhasm: new caller_q5
+
+# qhasm: new caller_q6
+
+# qhasm: new caller_q7
+
+# qhasm: caller_q4 bot = stack_q4 bot
+# asm 1: vldr <caller_q4=reg128#5%bot,<stack_q4=stack128#1
+# asm 2: vldr <caller_q4=d8,<stack_q4=[sp,#96]
+vldr d8,[sp,#96]
+
+# qhasm: caller_q4 top = stack_q4 top
+# asm 1: vldr <caller_q4=reg128#5%top,<stack_q4=stack128#1
+# asm 2: vldr <caller_q4=d9,<stack_q4=[sp,#104]
+vldr d9,[sp,#104]
+
+# qhasm: caller_q5 bot = stack_q5 bot
+# asm 1: vldr <caller_q5=reg128#6%bot,<stack_q5=stack128#2
+# asm 2: vldr <caller_q5=d10,<stack_q5=[sp,#112]
+vldr d10,[sp,#112]
+
+# qhasm: caller_q5 top = stack_q5 top
+# asm 1: vldr <caller_q5=reg128#6%top,<stack_q5=stack128#2
+# asm 2: vldr <caller_q5=d11,<stack_q5=[sp,#120]
+vldr d11,[sp,#120]
+
+# qhasm: caller_q6 bot = stack_q6 bot
+# asm 1: vldr <caller_q6=reg128#7%bot,<stack_q6=stack128#3
+# asm 2: vldr <caller_q6=d12,<stack_q6=[sp,#128]
+vldr d12,[sp,#128]
+
+# qhasm: caller_q6 top = stack_q6 top
+# asm 1: vldr <caller_q6=reg128#7%top,<stack_q6=stack128#3
+# asm 2: vldr <caller_q6=d13,<stack_q6=[sp,#136]
+vldr d13,[sp,#136]
+
+# qhasm: caller_q7 bot = stack_q7 bot
+# asm 1: vldr <caller_q7=reg128#8%bot,<stack_q7=stack128#4
+# asm 2: vldr <caller_q7=d14,<stack_q7=[sp,#144]
+vldr d14,[sp,#144]
+
+# qhasm: caller_q7 top = stack_q7 top
+# asm 1: vldr <caller_q7=reg128#8%top,<stack_q7=stack128#4
+# asm 2: vldr <caller_q7=d15,<stack_q7=[sp,#152]
+vldr d15,[sp,#152]
+
+# qhasm: int32 result
+
+# qhasm: result = 0
+# asm 1: ldr >result=int32#1,=0
+# asm 2: ldr >result=r0,=0
+ldr r0,=0
+
+# qhasm: return result
+add sp,sp,#256
+bx lr
diff --git a/ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dll b/ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dll
deleted file mode 100644
index d49d2913..00000000
--- a/ext/bin/tap-windows-ndis5/x64/WdfCoinstaller01011.dll
+++ /dev/null
Binary files differ
diff --git a/ext/bin/tap-windows-ndis5/x64/zttap200.cat b/ext/bin/tap-windows-ndis5/x64/zttap200.cat
deleted file mode 100644
index a3769e40..00000000
--- a/ext/bin/tap-windows-ndis5/x64/zttap200.cat
+++ /dev/null
Binary files differ
diff --git a/ext/bin/tap-windows-ndis5/x64/zttap200.inf b/ext/bin/tap-windows-ndis5/x64/zttap200.inf
deleted file mode 100644
index dc1a7422..00000000
--- a/ext/bin/tap-windows-ndis5/x64/zttap200.inf
+++ /dev/null
@@ -1,79 +0,0 @@
-[Version]
-Signature="$WINDOWS NT$"
-Class=Net
-ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}
-Provider=%Provider%
-CatalogFile=zttap200.cat
-DriverVer=01/23/2014,15.19.17.816
-
-[Strings]
-DeviceDescription = "ZeroTier One Virtual Network Port"
-Provider = "ZeroTier Networks LLC"
-
-; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back!
-[Manufacturer]
-%Provider%=zttap200,NTamd64
-
-[zttap200]
-%DeviceDescription%=zttap200.ndi,zttap200
-
-[ztTap200.NTamd64]
-%DeviceDescription%=zttap200.ndi,zttap200
-
-[zttap200.ndi]
-CopyFiles = zttap200.driver,zttap200.files
-AddReg = zttap200.reg
-AddReg = zttap200.params.reg
-Characteristics = 0x81
-
-[zttap200.ndi.Services]
-AddService = zttap200, 2, zttap200.service
-
-[zttap200.reg]
-HKR, Ndi, Service, 0, "zttap200"
-HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
-HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
-HKR, , Manufacturer, 0, "%Provider%"
-HKR, , ProductName, 0, "%DeviceDescription%"
-
-[zttap200.params.reg]
-HKR, Ndi\params\MTU, ParamDesc, 0, "MTU"
-HKR, Ndi\params\MTU, Type, 0, "int"
-HKR, Ndi\params\MTU, Default, 0, "2800"
-HKR, Ndi\params\MTU, Optional, 0, "0"
-HKR, Ndi\params\MTU, Min, 0, "100"
-HKR, Ndi\params\MTU, Max, 0, "2800"
-HKR, Ndi\params\MTU, Step, 0, "1"
-HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status"
-HKR, Ndi\params\MediaStatus, Type, 0, "enum"
-HKR, Ndi\params\MediaStatus, Default, 0, "0"
-HKR, Ndi\params\MediaStatus, Optional, 0, "0"
-HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled"
-HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected"
-HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address"
-HKR, Ndi\params\MAC, Type, 0, "edit"
-HKR, Ndi\params\MAC, Optional, 0, "1"
-
-[zttap200.service]
-DisplayName = %DeviceDescription%
-ServiceType = 1
-StartType = 3
-ErrorControl = 1
-LoadOrderGroup = NDIS
-ServiceBinary = %12%\zttap200.sys
-
-[SourceDisksNames]
-1 = %DeviceDescription%, zttap200.sys
-
-[SourceDisksFiles]
-zttap200.sys = 1
-
-[DestinationDirs]
-zttap200.files = 11
-zttap200.driver = 12
-
-[zttap200.files]
-;
-
-[zttap200.driver]
-zttap200.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK
diff --git a/ext/bin/tap-windows-ndis5/x64/zttap200.sys b/ext/bin/tap-windows-ndis5/x64/zttap200.sys
deleted file mode 100644
index 339351fb..00000000
--- a/ext/bin/tap-windows-ndis5/x64/zttap200.sys
+++ /dev/null
Binary files differ
diff --git a/ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dll b/ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dll
deleted file mode 100644
index e943ea45..00000000
--- a/ext/bin/tap-windows-ndis5/x86/WdfCoinstaller01011.dll
+++ /dev/null
Binary files differ
diff --git a/ext/bin/tap-windows-ndis5/x86/zttap200.cat b/ext/bin/tap-windows-ndis5/x86/zttap200.cat
deleted file mode 100644
index d90ecbbe..00000000
--- a/ext/bin/tap-windows-ndis5/x86/zttap200.cat
+++ /dev/null
Binary files differ
diff --git a/ext/bin/tap-windows-ndis5/x86/zttap200.inf b/ext/bin/tap-windows-ndis5/x86/zttap200.inf
deleted file mode 100644
index 99aac9f2..00000000
--- a/ext/bin/tap-windows-ndis5/x86/zttap200.inf
+++ /dev/null
@@ -1,76 +0,0 @@
-[Version]
-Signature="$WINDOWS NT$"
-Class=Net
-ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}
-Provider=%Provider%
-CatalogFile=zttap200.cat
-DriverVer=01/24/2014,17.25.51.226
-
-[Strings]
-DeviceDescription = "ZeroTier One Virtual Network Port"
-Provider = "ZeroTier Networks LLC"
-
-; To build for x86, take NTamd64 off this and off the named section manually, build, then put it back!
-[Manufacturer]
-%Provider%=zttap200
-
-[zttap200]
-%DeviceDescription%=zttap200.ndi,zttap200
-
-[zttap200.ndi]
-CopyFiles = zttap200.driver,zttap200.files
-AddReg = zttap200.reg
-AddReg = zttap200.params.reg
-Characteristics = 0x81
-
-[zttap200.ndi.Services]
-AddService = zttap200, 2, zttap200.service
-
-[zttap200.reg]
-HKR, Ndi, Service, 0, "zttap200"
-HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
-HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
-HKR, , Manufacturer, 0, "%Provider%"
-HKR, , ProductName, 0, "%DeviceDescription%"
-
-[zttap200.params.reg]
-HKR, Ndi\params\MTU, ParamDesc, 0, "MTU"
-HKR, Ndi\params\MTU, Type, 0, "int"
-HKR, Ndi\params\MTU, Default, 0, "2800"
-HKR, Ndi\params\MTU, Optional, 0, "0"
-HKR, Ndi\params\MTU, Min, 0, "100"
-HKR, Ndi\params\MTU, Max, 0, "2800"
-HKR, Ndi\params\MTU, Step, 0, "1"
-HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status"
-HKR, Ndi\params\MediaStatus, Type, 0, "enum"
-HKR, Ndi\params\MediaStatus, Default, 0, "0"
-HKR, Ndi\params\MediaStatus, Optional, 0, "0"
-HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled"
-HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected"
-HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address"
-HKR, Ndi\params\MAC, Type, 0, "edit"
-HKR, Ndi\params\MAC, Optional, 0, "1"
-
-[zttap200.service]
-DisplayName = %DeviceDescription%
-ServiceType = 1
-StartType = 3
-ErrorControl = 1
-LoadOrderGroup = NDIS
-ServiceBinary = %12%\zttap200.sys
-
-[SourceDisksNames]
-1 = %DeviceDescription%, zttap200.sys
-
-[SourceDisksFiles]
-zttap200.sys = 1
-
-[DestinationDirs]
-zttap200.files = 11
-zttap200.driver = 12
-
-[zttap200.files]
-;
-
-[zttap200.driver]
-zttap200.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK
diff --git a/ext/bin/tap-windows-ndis5/x86/zttap200.sys b/ext/bin/tap-windows-ndis5/x86/zttap200.sys
deleted file mode 100644
index b7b11fbe..00000000
--- a/ext/bin/tap-windows-ndis5/x86/zttap200.sys
+++ /dev/null
Binary files differ
diff --git a/ext/bin/tap-windows-ndis6/certutil.exe b/ext/bin/tap-windows-ndis6/certutil.exe
new file mode 100644
index 00000000..b9a0a09c
--- /dev/null
+++ b/ext/bin/tap-windows-ndis6/certutil.exe
Binary files differ
diff --git a/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi b/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi
index 818796f4..17fe08c2 100644
--- a/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi
+++ b/ext/bin/tap-windows-ndis6/x64/ZeroTierOne_NDIS6_x64.msi
Binary files differ
diff --git a/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi b/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi
index b9e2d7ea..415774c9 100644
--- a/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi
+++ b/ext/bin/tap-windows-ndis6/x86/ZeroTierOne_NDIS6_x86.msi
Binary files differ
diff --git a/ext/bin/tap-windows-ndis6/zttap300.cer b/ext/bin/tap-windows-ndis6/zttap300.cer
new file mode 100644
index 00000000..ef74e041
--- /dev/null
+++ b/ext/bin/tap-windows-ndis6/zttap300.cer
Binary files differ
diff --git a/ext/ed25519-amd64-asm/batch.c b/ext/ed25519-amd64-asm/batch.c
new file mode 100644
index 00000000..955392ea
--- /dev/null
+++ b/ext/ed25519-amd64-asm/batch.c
@@ -0,0 +1,94 @@
+#include "crypto_sign.h"
+
+#include "crypto_verify_32.h"
+#include "crypto_hash_sha512.h"
+#include "randombytes.h"
+
+#include "ge25519.h"
+#include "hram.h"
+
+#define MAXBATCH 64
+
+int crypto_sign_open_batch(
+ unsigned char* const m[],unsigned long long mlen[],
+ unsigned char* const sm[],const unsigned long long smlen[],
+ unsigned char* const pk[],
+ unsigned long long num
+ )
+{
+ int ret = 0;
+ unsigned long long i, j;
+ shortsc25519 r[MAXBATCH];
+ sc25519 scalars[2*MAXBATCH+1];
+ ge25519 points[2*MAXBATCH+1];
+ unsigned char hram[crypto_hash_sha512_BYTES];
+ unsigned long long batchsize;
+
+ for (i = 0;i < num;++i) mlen[i] = -1;
+
+ while (num >= 3) {
+ batchsize = num;
+ if (batchsize > MAXBATCH) batchsize = MAXBATCH;
+
+ for (i = 0;i < batchsize;++i)
+ if (smlen[i] < 64) goto fallback;
+
+ randombytes((unsigned char*)r,sizeof(shortsc25519) * batchsize);
+
+ /* Computing scalars[0] = ((r1s1 + r2s2 + ...)) */
+ for(i=0;i<batchsize;i++)
+ {
+ sc25519_from32bytes(&scalars[i], sm[i]+32);
+ sc25519_mul_shortsc(&scalars[i], &scalars[i], &r[i]);
+ }
+ for(i=1;i<batchsize;i++)
+ sc25519_add(&scalars[0], &scalars[0], &scalars[i]);
+
+ /* Computing scalars[1] ... scalars[batchsize] as r[i]*H(R[i],A[i],m[i]) */
+ for(i=0;i<batchsize;i++)
+ {
+ get_hram(hram, sm[i], pk[i], m[i], smlen[i]);
+ sc25519_from64bytes(&scalars[i+1],hram);
+ sc25519_mul_shortsc(&scalars[i+1],&scalars[i+1],&r[i]);
+ }
+ /* Setting scalars[batchsize+1] ... scalars[2*batchsize] to r[i] */
+ for(i=0;i<batchsize;i++)
+ sc25519_from_shortsc(&scalars[batchsize+i+1],&r[i]);
+
+ /* Computing points */
+ points[0] = ge25519_base;
+
+ for(i=0;i<batchsize;i++)
+ if (ge25519_unpackneg_vartime(&points[i+1], pk[i])) goto fallback;
+ for(i=0;i<batchsize;i++)
+ if (ge25519_unpackneg_vartime(&points[batchsize+i+1], sm[i])) goto fallback;
+
+ ge25519_multi_scalarmult_vartime(points, points, scalars, 2*batchsize+1);
+
+ if (ge25519_isneutral_vartime(points)) {
+ for(i=0;i<batchsize;i++)
+ {
+ for(j=0;j<smlen[i]-64;j++)
+ m[i][j] = sm[i][j + 64];
+ mlen[i] = smlen[i]-64;
+ }
+ } else {
+ fallback:
+
+ for (i = 0;i < batchsize;++i)
+ ret |= crypto_sign_open(m[i], &mlen[i], sm[i], smlen[i], pk[i]);
+ }
+
+ m += batchsize;
+ mlen += batchsize;
+ sm += batchsize;
+ smlen += batchsize;
+ pk += batchsize;
+ num -= batchsize;
+ }
+
+ for (i = 0;i < num;++i)
+ ret |= crypto_sign_open(m[i], &mlen[i], sm[i], smlen[i], pk[i]);
+
+ return ret;
+}
diff --git a/ext/ed25519-amd64-asm/choose_t.s b/ext/ed25519-amd64-asm/choose_t.s
new file mode 100644
index 00000000..f10d8b8b
--- /dev/null
+++ b/ext/ed25519-amd64-asm/choose_t.s
@@ -0,0 +1,1565 @@
+
+# qhasm: int64 tp
+
+# qhasm: int64 pos
+
+# qhasm: int64 b
+
+# qhasm: int64 basep
+
+# qhasm: input tp
+
+# qhasm: input pos
+
+# qhasm: input b
+
+# qhasm: input basep
+
+# qhasm: int64 mask
+
+# qhasm: int64 u
+
+# qhasm: int64 tysubx0
+
+# qhasm: int64 tysubx1
+
+# qhasm: int64 tysubx2
+
+# qhasm: int64 tysubx3
+
+# qhasm: int64 txaddy0
+
+# qhasm: int64 txaddy1
+
+# qhasm: int64 txaddy2
+
+# qhasm: int64 txaddy3
+
+# qhasm: int64 tt2d0
+
+# qhasm: int64 tt2d1
+
+# qhasm: int64 tt2d2
+
+# qhasm: int64 tt2d3
+
+# qhasm: int64 tt0
+
+# qhasm: int64 tt1
+
+# qhasm: int64 tt2
+
+# qhasm: int64 tt3
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: int64 t
+
+# qhasm: stack64 tp_stack
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_choose_t
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_choose_t
+.globl crypto_sign_ed25519_amd64_64_choose_t
+_crypto_sign_ed25519_amd64_64_choose_t:
+crypto_sign_ed25519_amd64_64_choose_t:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: tp_stack = tp
+# asm 1: movq <tp=int64#1,>tp_stack=stack64#8
+# asm 2: movq <tp=%rdi,>tp_stack=56(%rsp)
+movq %rdi,56(%rsp)
+
+# qhasm: pos *= 768
+# asm 1: imulq $768,<pos=int64#2,>pos=int64#1
+# asm 2: imulq $768,<pos=%rsi,>pos=%rdi
+imulq $768,%rsi,%rdi
+
+# qhasm: mask = b
+# asm 1: mov <b=int64#3,>mask=int64#2
+# asm 2: mov <b=%rdx,>mask=%rsi
+mov %rdx,%rsi
+
+# qhasm: (int64) mask >>= 7
+# asm 1: sar $7,<mask=int64#2
+# asm 2: sar $7,<mask=%rsi
+sar $7,%rsi
+
+# qhasm: u = b
+# asm 1: mov <b=int64#3,>u=int64#5
+# asm 2: mov <b=%rdx,>u=%r8
+mov %rdx,%r8
+
+# qhasm: u += mask
+# asm 1: add <mask=int64#2,<u=int64#5
+# asm 2: add <mask=%rsi,<u=%r8
+add %rsi,%r8
+
+# qhasm: u ^= mask
+# asm 1: xor <mask=int64#2,<u=int64#5
+# asm 2: xor <mask=%rsi,<u=%r8
+xor %rsi,%r8
+
+# qhasm: tysubx0 = 1
+# asm 1: mov $1,>tysubx0=int64#2
+# asm 2: mov $1,>tysubx0=%rsi
+mov $1,%rsi
+
+# qhasm: tysubx1 = 0
+# asm 1: mov $0,>tysubx1=int64#6
+# asm 2: mov $0,>tysubx1=%r9
+mov $0,%r9
+
+# qhasm: tysubx2 = 0
+# asm 1: mov $0,>tysubx2=int64#7
+# asm 2: mov $0,>tysubx2=%rax
+mov $0,%rax
+
+# qhasm: tysubx3 = 0
+# asm 1: mov $0,>tysubx3=int64#8
+# asm 2: mov $0,>tysubx3=%r10
+mov $0,%r10
+
+# qhasm: txaddy0 = 1
+# asm 1: mov $1,>txaddy0=int64#9
+# asm 2: mov $1,>txaddy0=%r11
+mov $1,%r11
+
+# qhasm: txaddy1 = 0
+# asm 1: mov $0,>txaddy1=int64#10
+# asm 2: mov $0,>txaddy1=%r12
+mov $0,%r12
+
+# qhasm: txaddy2 = 0
+# asm 1: mov $0,>txaddy2=int64#11
+# asm 2: mov $0,>txaddy2=%r13
+mov $0,%r13
+
+# qhasm: txaddy3 = 0
+# asm 1: mov $0,>txaddy3=int64#12
+# asm 2: mov $0,>txaddy3=%r14
+mov $0,%r14
+
+# qhasm: =? u - 1
+# asm 1: cmp $1,<u=int64#5
+# asm 2: cmp $1,<u=%r8
+cmp $1,%r8
+
+# qhasm: t = *(uint64 *)(basep + 0 + pos)
+# asm 1: movq 0(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 0(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 0(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 8 + pos)
+# asm 1: movq 8(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 8(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 8(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 16 + pos)
+# asm 1: movq 16(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 16(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 16(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 24 + pos)
+# asm 1: movq 24(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 24(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 24(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 32 + pos)
+# asm 1: movq 32(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 32(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 32(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 40 + pos)
+# asm 1: movq 40(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 40(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 40(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 48 + pos)
+# asm 1: movq 48(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 48(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 48(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 56 + pos)
+# asm 1: movq 56(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 56(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 56(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 2
+# asm 1: cmp $2,<u=int64#5
+# asm 2: cmp $2,<u=%r8
+cmp $2,%r8
+
+# qhasm: t = *(uint64 *)(basep + 96 + pos)
+# asm 1: movq 96(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 96(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 96(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 104 + pos)
+# asm 1: movq 104(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 104(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 104(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 112 + pos)
+# asm 1: movq 112(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 112(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 112(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 120 + pos)
+# asm 1: movq 120(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 120(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 120(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 128 + pos)
+# asm 1: movq 128(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 128(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 128(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 136 + pos)
+# asm 1: movq 136(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 136(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 136(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 144 + pos)
+# asm 1: movq 144(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 144(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 144(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 152 + pos)
+# asm 1: movq 152(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 152(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 152(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 3
+# asm 1: cmp $3,<u=int64#5
+# asm 2: cmp $3,<u=%r8
+cmp $3,%r8
+
+# qhasm: t = *(uint64 *)(basep + 192 + pos)
+# asm 1: movq 192(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 192(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 192(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 200 + pos)
+# asm 1: movq 200(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 200(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 200(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 208 + pos)
+# asm 1: movq 208(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 208(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 208(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 216 + pos)
+# asm 1: movq 216(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 216(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 216(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 224 + pos)
+# asm 1: movq 224(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 224(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 224(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 232 + pos)
+# asm 1: movq 232(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 232(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 232(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 240 + pos)
+# asm 1: movq 240(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 240(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 240(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 248 + pos)
+# asm 1: movq 248(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 248(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 248(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 4
+# asm 1: cmp $4,<u=int64#5
+# asm 2: cmp $4,<u=%r8
+cmp $4,%r8
+
+# qhasm: t = *(uint64 *)(basep + 288 + pos)
+# asm 1: movq 288(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 288(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 288(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 296 + pos)
+# asm 1: movq 296(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 296(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 296(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 304 + pos)
+# asm 1: movq 304(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 304(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 304(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 312 + pos)
+# asm 1: movq 312(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 312(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 312(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 320 + pos)
+# asm 1: movq 320(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 320(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 320(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 328 + pos)
+# asm 1: movq 328(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 328(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 328(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 336 + pos)
+# asm 1: movq 336(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 336(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 336(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 344 + pos)
+# asm 1: movq 344(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 344(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 344(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 5
+# asm 1: cmp $5,<u=int64#5
+# asm 2: cmp $5,<u=%r8
+cmp $5,%r8
+
+# qhasm: t = *(uint64 *)(basep + 384 + pos)
+# asm 1: movq 384(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 384(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 384(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 392 + pos)
+# asm 1: movq 392(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 392(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 392(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 400 + pos)
+# asm 1: movq 400(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 400(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 400(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 408 + pos)
+# asm 1: movq 408(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 408(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 408(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 416 + pos)
+# asm 1: movq 416(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 416(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 416(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 424 + pos)
+# asm 1: movq 424(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 424(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 424(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 432 + pos)
+# asm 1: movq 432(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 432(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 432(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 440 + pos)
+# asm 1: movq 440(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 440(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 440(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 6
+# asm 1: cmp $6,<u=int64#5
+# asm 2: cmp $6,<u=%r8
+cmp $6,%r8
+
+# qhasm: t = *(uint64 *)(basep + 480 + pos)
+# asm 1: movq 480(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 480(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 480(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 488 + pos)
+# asm 1: movq 488(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 488(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 488(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 496 + pos)
+# asm 1: movq 496(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 496(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 496(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 504 + pos)
+# asm 1: movq 504(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 504(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 504(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 512 + pos)
+# asm 1: movq 512(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 512(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 512(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 520 + pos)
+# asm 1: movq 520(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 520(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 520(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 528 + pos)
+# asm 1: movq 528(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 528(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 528(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 536 + pos)
+# asm 1: movq 536(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 536(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 536(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 7
+# asm 1: cmp $7,<u=int64#5
+# asm 2: cmp $7,<u=%r8
+cmp $7,%r8
+
+# qhasm: t = *(uint64 *)(basep + 576 + pos)
+# asm 1: movq 576(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 576(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 576(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 584 + pos)
+# asm 1: movq 584(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 584(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 584(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 592 + pos)
+# asm 1: movq 592(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 592(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 592(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 600 + pos)
+# asm 1: movq 600(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 600(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 600(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 608 + pos)
+# asm 1: movq 608(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 608(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 608(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 616 + pos)
+# asm 1: movq 616(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 616(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 616(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 624 + pos)
+# asm 1: movq 624(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 624(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 624(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 632 + pos)
+# asm 1: movq 632(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 632(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 632(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: =? u - 8
+# asm 1: cmp $8,<u=int64#5
+# asm 2: cmp $8,<u=%r8
+cmp $8,%r8
+
+# qhasm: t = *(uint64 *)(basep + 672 + pos)
+# asm 1: movq 672(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 672(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 672(%rcx,%rdi),%r15
+
+# qhasm: tysubx0 = t if =
+# asm 1: cmove <t=int64#13,<tysubx0=int64#2
+# asm 2: cmove <t=%r15,<tysubx0=%rsi
+cmove %r15,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 680 + pos)
+# asm 1: movq 680(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 680(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 680(%rcx,%rdi),%r15
+
+# qhasm: tysubx1 = t if =
+# asm 1: cmove <t=int64#13,<tysubx1=int64#6
+# asm 2: cmove <t=%r15,<tysubx1=%r9
+cmove %r15,%r9
+
+# qhasm: t = *(uint64 *)(basep + 688 + pos)
+# asm 1: movq 688(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 688(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 688(%rcx,%rdi),%r15
+
+# qhasm: tysubx2 = t if =
+# asm 1: cmove <t=int64#13,<tysubx2=int64#7
+# asm 2: cmove <t=%r15,<tysubx2=%rax
+cmove %r15,%rax
+
+# qhasm: t = *(uint64 *)(basep + 696 + pos)
+# asm 1: movq 696(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 696(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 696(%rcx,%rdi),%r15
+
+# qhasm: tysubx3 = t if =
+# asm 1: cmove <t=int64#13,<tysubx3=int64#8
+# asm 2: cmove <t=%r15,<tysubx3=%r10
+cmove %r15,%r10
+
+# qhasm: t = *(uint64 *)(basep + 704 + pos)
+# asm 1: movq 704(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 704(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 704(%rcx,%rdi),%r15
+
+# qhasm: txaddy0 = t if =
+# asm 1: cmove <t=int64#13,<txaddy0=int64#9
+# asm 2: cmove <t=%r15,<txaddy0=%r11
+cmove %r15,%r11
+
+# qhasm: t = *(uint64 *)(basep + 712 + pos)
+# asm 1: movq 712(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 712(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 712(%rcx,%rdi),%r15
+
+# qhasm: txaddy1 = t if =
+# asm 1: cmove <t=int64#13,<txaddy1=int64#10
+# asm 2: cmove <t=%r15,<txaddy1=%r12
+cmove %r15,%r12
+
+# qhasm: t = *(uint64 *)(basep + 720 + pos)
+# asm 1: movq 720(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 720(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 720(%rcx,%rdi),%r15
+
+# qhasm: txaddy2 = t if =
+# asm 1: cmove <t=int64#13,<txaddy2=int64#11
+# asm 2: cmove <t=%r15,<txaddy2=%r13
+cmove %r15,%r13
+
+# qhasm: t = *(uint64 *)(basep + 728 + pos)
+# asm 1: movq 728(<basep=int64#4,<pos=int64#1),>t=int64#13
+# asm 2: movq 728(<basep=%rcx,<pos=%rdi),>t=%r15
+movq 728(%rcx,%rdi),%r15
+
+# qhasm: txaddy3 = t if =
+# asm 1: cmove <t=int64#13,<txaddy3=int64#12
+# asm 2: cmove <t=%r15,<txaddy3=%r14
+cmove %r15,%r14
+
+# qhasm: signed<? b - 0
+# asm 1: cmp $0,<b=int64#3
+# asm 2: cmp $0,<b=%rdx
+cmp $0,%rdx
+
+# qhasm: t = tysubx0
+# asm 1: mov <tysubx0=int64#2,>t=int64#13
+# asm 2: mov <tysubx0=%rsi,>t=%r15
+mov %rsi,%r15
+
+# qhasm: tysubx0 = txaddy0 if signed<
+# asm 1: cmovl <txaddy0=int64#9,<tysubx0=int64#2
+# asm 2: cmovl <txaddy0=%r11,<tysubx0=%rsi
+cmovl %r11,%rsi
+
+# qhasm: txaddy0 = t if signed<
+# asm 1: cmovl <t=int64#13,<txaddy0=int64#9
+# asm 2: cmovl <t=%r15,<txaddy0=%r11
+cmovl %r15,%r11
+
+# qhasm: t = tysubx1
+# asm 1: mov <tysubx1=int64#6,>t=int64#13
+# asm 2: mov <tysubx1=%r9,>t=%r15
+mov %r9,%r15
+
+# qhasm: tysubx1 = txaddy1 if signed<
+# asm 1: cmovl <txaddy1=int64#10,<tysubx1=int64#6
+# asm 2: cmovl <txaddy1=%r12,<tysubx1=%r9
+cmovl %r12,%r9
+
+# qhasm: txaddy1 = t if signed<
+# asm 1: cmovl <t=int64#13,<txaddy1=int64#10
+# asm 2: cmovl <t=%r15,<txaddy1=%r12
+cmovl %r15,%r12
+
+# qhasm: t = tysubx2
+# asm 1: mov <tysubx2=int64#7,>t=int64#13
+# asm 2: mov <tysubx2=%rax,>t=%r15
+mov %rax,%r15
+
+# qhasm: tysubx2 = txaddy2 if signed<
+# asm 1: cmovl <txaddy2=int64#11,<tysubx2=int64#7
+# asm 2: cmovl <txaddy2=%r13,<tysubx2=%rax
+cmovl %r13,%rax
+
+# qhasm: txaddy2 = t if signed<
+# asm 1: cmovl <t=int64#13,<txaddy2=int64#11
+# asm 2: cmovl <t=%r15,<txaddy2=%r13
+cmovl %r15,%r13
+
+# qhasm: t = tysubx3
+# asm 1: mov <tysubx3=int64#8,>t=int64#13
+# asm 2: mov <tysubx3=%r10,>t=%r15
+mov %r10,%r15
+
+# qhasm: tysubx3 = txaddy3 if signed<
+# asm 1: cmovl <txaddy3=int64#12,<tysubx3=int64#8
+# asm 2: cmovl <txaddy3=%r14,<tysubx3=%r10
+cmovl %r14,%r10
+
+# qhasm: txaddy3 = t if signed<
+# asm 1: cmovl <t=int64#13,<txaddy3=int64#12
+# asm 2: cmovl <t=%r15,<txaddy3=%r14
+cmovl %r15,%r14
+
+# qhasm: tp = tp_stack
+# asm 1: movq <tp_stack=stack64#8,>tp=int64#13
+# asm 2: movq <tp_stack=56(%rsp),>tp=%r15
+movq 56(%rsp),%r15
+
+# qhasm: *(uint64 *)(tp + 0) = tysubx0
+# asm 1: movq <tysubx0=int64#2,0(<tp=int64#13)
+# asm 2: movq <tysubx0=%rsi,0(<tp=%r15)
+movq %rsi,0(%r15)
+
+# qhasm: *(uint64 *)(tp + 8) = tysubx1
+# asm 1: movq <tysubx1=int64#6,8(<tp=int64#13)
+# asm 2: movq <tysubx1=%r9,8(<tp=%r15)
+movq %r9,8(%r15)
+
+# qhasm: *(uint64 *)(tp + 16) = tysubx2
+# asm 1: movq <tysubx2=int64#7,16(<tp=int64#13)
+# asm 2: movq <tysubx2=%rax,16(<tp=%r15)
+movq %rax,16(%r15)
+
+# qhasm: *(uint64 *)(tp + 24) = tysubx3
+# asm 1: movq <tysubx3=int64#8,24(<tp=int64#13)
+# asm 2: movq <tysubx3=%r10,24(<tp=%r15)
+movq %r10,24(%r15)
+
+# qhasm: *(uint64 *)(tp + 32) = txaddy0
+# asm 1: movq <txaddy0=int64#9,32(<tp=int64#13)
+# asm 2: movq <txaddy0=%r11,32(<tp=%r15)
+movq %r11,32(%r15)
+
+# qhasm: *(uint64 *)(tp + 40) = txaddy1
+# asm 1: movq <txaddy1=int64#10,40(<tp=int64#13)
+# asm 2: movq <txaddy1=%r12,40(<tp=%r15)
+movq %r12,40(%r15)
+
+# qhasm: *(uint64 *)(tp + 48) = txaddy2
+# asm 1: movq <txaddy2=int64#11,48(<tp=int64#13)
+# asm 2: movq <txaddy2=%r13,48(<tp=%r15)
+movq %r13,48(%r15)
+
+# qhasm: *(uint64 *)(tp + 56) = txaddy3
+# asm 1: movq <txaddy3=int64#12,56(<tp=int64#13)
+# asm 2: movq <txaddy3=%r14,56(<tp=%r15)
+movq %r14,56(%r15)
+
+# qhasm: tt2d0 = 0
+# asm 1: mov $0,>tt2d0=int64#2
+# asm 2: mov $0,>tt2d0=%rsi
+mov $0,%rsi
+
+# qhasm: tt2d1 = 0
+# asm 1: mov $0,>tt2d1=int64#6
+# asm 2: mov $0,>tt2d1=%r9
+mov $0,%r9
+
+# qhasm: tt2d2 = 0
+# asm 1: mov $0,>tt2d2=int64#7
+# asm 2: mov $0,>tt2d2=%rax
+mov $0,%rax
+
+# qhasm: tt2d3 = 0
+# asm 1: mov $0,>tt2d3=int64#8
+# asm 2: mov $0,>tt2d3=%r10
+mov $0,%r10
+
+# qhasm: =? u - 1
+# asm 1: cmp $1,<u=int64#5
+# asm 2: cmp $1,<u=%r8
+cmp $1,%r8
+
+# qhasm: t = *(uint64 *)(basep + 64 + pos)
+# asm 1: movq 64(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 64(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 64(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 72 + pos)
+# asm 1: movq 72(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 72(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 72(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 80 + pos)
+# asm 1: movq 80(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 80(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 80(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 88 + pos)
+# asm 1: movq 88(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 88(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 88(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 2
+# asm 1: cmp $2,<u=int64#5
+# asm 2: cmp $2,<u=%r8
+cmp $2,%r8
+
+# qhasm: t = *(uint64 *)(basep + 160 + pos)
+# asm 1: movq 160(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 160(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 160(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 168 + pos)
+# asm 1: movq 168(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 168(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 168(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 176 + pos)
+# asm 1: movq 176(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 176(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 176(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 184 + pos)
+# asm 1: movq 184(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 184(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 184(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 3
+# asm 1: cmp $3,<u=int64#5
+# asm 2: cmp $3,<u=%r8
+cmp $3,%r8
+
+# qhasm: t = *(uint64 *)(basep + 256 + pos)
+# asm 1: movq 256(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 256(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 256(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 264 + pos)
+# asm 1: movq 264(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 264(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 264(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 272 + pos)
+# asm 1: movq 272(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 272(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 272(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 280 + pos)
+# asm 1: movq 280(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 280(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 280(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 4
+# asm 1: cmp $4,<u=int64#5
+# asm 2: cmp $4,<u=%r8
+cmp $4,%r8
+
+# qhasm: t = *(uint64 *)(basep + 352 + pos)
+# asm 1: movq 352(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 352(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 352(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 360 + pos)
+# asm 1: movq 360(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 360(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 360(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 368 + pos)
+# asm 1: movq 368(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 368(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 368(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 376 + pos)
+# asm 1: movq 376(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 376(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 376(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 5
+# asm 1: cmp $5,<u=int64#5
+# asm 2: cmp $5,<u=%r8
+cmp $5,%r8
+
+# qhasm: t = *(uint64 *)(basep + 448 + pos)
+# asm 1: movq 448(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 448(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 448(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 456 + pos)
+# asm 1: movq 456(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 456(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 456(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 464 + pos)
+# asm 1: movq 464(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 464(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 464(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 472 + pos)
+# asm 1: movq 472(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 472(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 472(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 6
+# asm 1: cmp $6,<u=int64#5
+# asm 2: cmp $6,<u=%r8
+cmp $6,%r8
+
+# qhasm: t = *(uint64 *)(basep + 544 + pos)
+# asm 1: movq 544(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 544(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 544(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 552 + pos)
+# asm 1: movq 552(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 552(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 552(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 560 + pos)
+# asm 1: movq 560(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 560(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 560(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 568 + pos)
+# asm 1: movq 568(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 568(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 568(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 7
+# asm 1: cmp $7,<u=int64#5
+# asm 2: cmp $7,<u=%r8
+cmp $7,%r8
+
+# qhasm: t = *(uint64 *)(basep + 640 + pos)
+# asm 1: movq 640(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 640(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 640(%rcx,%rdi),%r11
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#9,<tt2d0=int64#2
+# asm 2: cmove <t=%r11,<tt2d0=%rsi
+cmove %r11,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 648 + pos)
+# asm 1: movq 648(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 648(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 648(%rcx,%rdi),%r11
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#9,<tt2d1=int64#6
+# asm 2: cmove <t=%r11,<tt2d1=%r9
+cmove %r11,%r9
+
+# qhasm: t = *(uint64 *)(basep + 656 + pos)
+# asm 1: movq 656(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 656(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 656(%rcx,%rdi),%r11
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#9,<tt2d2=int64#7
+# asm 2: cmove <t=%r11,<tt2d2=%rax
+cmove %r11,%rax
+
+# qhasm: t = *(uint64 *)(basep + 664 + pos)
+# asm 1: movq 664(<basep=int64#4,<pos=int64#1),>t=int64#9
+# asm 2: movq 664(<basep=%rcx,<pos=%rdi),>t=%r11
+movq 664(%rcx,%rdi),%r11
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#9,<tt2d3=int64#8
+# asm 2: cmove <t=%r11,<tt2d3=%r10
+cmove %r11,%r10
+
+# qhasm: =? u - 8
+# asm 1: cmp $8,<u=int64#5
+# asm 2: cmp $8,<u=%r8
+cmp $8,%r8
+
+# qhasm: t = *(uint64 *)(basep + 736 + pos)
+# asm 1: movq 736(<basep=int64#4,<pos=int64#1),>t=int64#5
+# asm 2: movq 736(<basep=%rcx,<pos=%rdi),>t=%r8
+movq 736(%rcx,%rdi),%r8
+
+# qhasm: tt2d0 = t if =
+# asm 1: cmove <t=int64#5,<tt2d0=int64#2
+# asm 2: cmove <t=%r8,<tt2d0=%rsi
+cmove %r8,%rsi
+
+# qhasm: t = *(uint64 *)(basep + 744 + pos)
+# asm 1: movq 744(<basep=int64#4,<pos=int64#1),>t=int64#5
+# asm 2: movq 744(<basep=%rcx,<pos=%rdi),>t=%r8
+movq 744(%rcx,%rdi),%r8
+
+# qhasm: tt2d1 = t if =
+# asm 1: cmove <t=int64#5,<tt2d1=int64#6
+# asm 2: cmove <t=%r8,<tt2d1=%r9
+cmove %r8,%r9
+
+# qhasm: t = *(uint64 *)(basep + 752 + pos)
+# asm 1: movq 752(<basep=int64#4,<pos=int64#1),>t=int64#5
+# asm 2: movq 752(<basep=%rcx,<pos=%rdi),>t=%r8
+movq 752(%rcx,%rdi),%r8
+
+# qhasm: tt2d2 = t if =
+# asm 1: cmove <t=int64#5,<tt2d2=int64#7
+# asm 2: cmove <t=%r8,<tt2d2=%rax
+cmove %r8,%rax
+
+# qhasm: t = *(uint64 *)(basep + 760 + pos)
+# asm 1: movq 760(<basep=int64#4,<pos=int64#1),>t=int64#1
+# asm 2: movq 760(<basep=%rcx,<pos=%rdi),>t=%rdi
+movq 760(%rcx,%rdi),%rdi
+
+# qhasm: tt2d3 = t if =
+# asm 1: cmove <t=int64#1,<tt2d3=int64#8
+# asm 2: cmove <t=%rdi,<tt2d3=%r10
+cmove %rdi,%r10
+
+# qhasm: tt0 = 0
+# asm 1: mov $0,>tt0=int64#1
+# asm 2: mov $0,>tt0=%rdi
+mov $0,%rdi
+
+# qhasm: tt1 = 0
+# asm 1: mov $0,>tt1=int64#4
+# asm 2: mov $0,>tt1=%rcx
+mov $0,%rcx
+
+# qhasm: tt2 = 0
+# asm 1: mov $0,>tt2=int64#5
+# asm 2: mov $0,>tt2=%r8
+mov $0,%r8
+
+# qhasm: tt3 = 0
+# asm 1: mov $0,>tt3=int64#9
+# asm 2: mov $0,>tt3=%r11
+mov $0,%r11
+
+# qhasm: carry? tt0 -= tt2d0
+# asm 1: sub <tt2d0=int64#2,<tt0=int64#1
+# asm 2: sub <tt2d0=%rsi,<tt0=%rdi
+sub %rsi,%rdi
+
+# qhasm: carry? tt1 -= tt2d1 - carry
+# asm 1: sbb <tt2d1=int64#6,<tt1=int64#4
+# asm 2: sbb <tt2d1=%r9,<tt1=%rcx
+sbb %r9,%rcx
+
+# qhasm: carry? tt2 -= tt2d2 - carry
+# asm 1: sbb <tt2d2=int64#7,<tt2=int64#5
+# asm 2: sbb <tt2d2=%rax,<tt2=%r8
+sbb %rax,%r8
+
+# qhasm: carry? tt3 -= tt2d3 - carry
+# asm 1: sbb <tt2d3=int64#8,<tt3=int64#9
+# asm 2: sbb <tt2d3=%r10,<tt3=%r11
+sbb %r10,%r11
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#10
+# asm 2: mov $0,>subt0=%r12
+mov $0,%r12
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#11
+# asm 2: mov $38,>subt1=%r13
+mov $38,%r13
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#10,<subt1=int64#11
+# asm 2: cmovae <subt0=%r12,<subt1=%r13
+cmovae %r12,%r13
+
+# qhasm: carry? tt0 -= subt1
+# asm 1: sub <subt1=int64#11,<tt0=int64#1
+# asm 2: sub <subt1=%r13,<tt0=%rdi
+sub %r13,%rdi
+
+# qhasm: carry? tt1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#10,<tt1=int64#4
+# asm 2: sbb <subt0=%r12,<tt1=%rcx
+sbb %r12,%rcx
+
+# qhasm: carry? tt2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#10,<tt2=int64#5
+# asm 2: sbb <subt0=%r12,<tt2=%r8
+sbb %r12,%r8
+
+# qhasm: carry? tt3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#10,<tt3=int64#9
+# asm 2: sbb <subt0=%r12,<tt3=%r11
+sbb %r12,%r11
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#11,<subt0=int64#10
+# asm 2: cmovc <subt1=%r13,<subt0=%r12
+cmovc %r13,%r12
+
+# qhasm: tt0 -= subt0
+# asm 1: sub <subt0=int64#10,<tt0=int64#1
+# asm 2: sub <subt0=%r12,<tt0=%rdi
+sub %r12,%rdi
+
+# qhasm: signed<? b - 0
+# asm 1: cmp $0,<b=int64#3
+# asm 2: cmp $0,<b=%rdx
+cmp $0,%rdx
+
+# qhasm: tt2d0 = tt0 if signed<
+# asm 1: cmovl <tt0=int64#1,<tt2d0=int64#2
+# asm 2: cmovl <tt0=%rdi,<tt2d0=%rsi
+cmovl %rdi,%rsi
+
+# qhasm: tt2d1 = tt1 if signed<
+# asm 1: cmovl <tt1=int64#4,<tt2d1=int64#6
+# asm 2: cmovl <tt1=%rcx,<tt2d1=%r9
+cmovl %rcx,%r9
+
+# qhasm: tt2d2 = tt2 if signed<
+# asm 1: cmovl <tt2=int64#5,<tt2d2=int64#7
+# asm 2: cmovl <tt2=%r8,<tt2d2=%rax
+cmovl %r8,%rax
+
+# qhasm: tt2d3 = tt3 if signed<
+# asm 1: cmovl <tt3=int64#9,<tt2d3=int64#8
+# asm 2: cmovl <tt3=%r11,<tt2d3=%r10
+cmovl %r11,%r10
+
+# qhasm: *(uint64 *)(tp + 64) = tt2d0
+# asm 1: movq <tt2d0=int64#2,64(<tp=int64#13)
+# asm 2: movq <tt2d0=%rsi,64(<tp=%r15)
+movq %rsi,64(%r15)
+
+# qhasm: *(uint64 *)(tp + 72) = tt2d1
+# asm 1: movq <tt2d1=int64#6,72(<tp=int64#13)
+# asm 2: movq <tt2d1=%r9,72(<tp=%r15)
+movq %r9,72(%r15)
+
+# qhasm: *(uint64 *)(tp + 80) = tt2d2
+# asm 1: movq <tt2d2=int64#7,80(<tp=int64#13)
+# asm 2: movq <tt2d2=%rax,80(<tp=%r15)
+movq %rax,80(%r15)
+
+# qhasm: *(uint64 *)(tp + 88) = tt2d3
+# asm 1: movq <tt2d3=int64#8,88(<tp=int64#13)
+# asm 2: movq <tt2d3=%r10,88(<tp=%r15)
+movq %r10,88(%r15)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/consts.s b/ext/ed25519-amd64-asm/consts.s
new file mode 100644
index 00000000..c272383f
--- /dev/null
+++ b/ext/ed25519-amd64-asm/consts.s
@@ -0,0 +1,39 @@
+.data
+
+.globl crypto_sign_ed25519_amd64_64_121666
+.globl crypto_sign_ed25519_amd64_64_MU0
+.globl crypto_sign_ed25519_amd64_64_MU1
+.globl crypto_sign_ed25519_amd64_64_MU2
+.globl crypto_sign_ed25519_amd64_64_MU3
+.globl crypto_sign_ed25519_amd64_64_MU4
+.globl crypto_sign_ed25519_amd64_64_ORDER0
+.globl crypto_sign_ed25519_amd64_64_ORDER1
+.globl crypto_sign_ed25519_amd64_64_ORDER2
+.globl crypto_sign_ed25519_amd64_64_ORDER3
+.globl crypto_sign_ed25519_amd64_64_EC2D0
+.globl crypto_sign_ed25519_amd64_64_EC2D1
+.globl crypto_sign_ed25519_amd64_64_EC2D2
+.globl crypto_sign_ed25519_amd64_64_EC2D3
+.globl crypto_sign_ed25519_amd64_64_38
+
+.p2align 4
+
+crypto_sign_ed25519_amd64_64_121666: .quad 121666
+
+crypto_sign_ed25519_amd64_64_MU0: .quad 0xED9CE5A30A2C131B
+crypto_sign_ed25519_amd64_64_MU1: .quad 0x2106215D086329A7
+crypto_sign_ed25519_amd64_64_MU2: .quad 0xFFFFFFFFFFFFFFEB
+crypto_sign_ed25519_amd64_64_MU3: .quad 0xFFFFFFFFFFFFFFFF
+crypto_sign_ed25519_amd64_64_MU4: .quad 0x000000000000000F
+
+crypto_sign_ed25519_amd64_64_ORDER0: .quad 0x5812631A5CF5D3ED
+crypto_sign_ed25519_amd64_64_ORDER1: .quad 0x14DEF9DEA2F79CD6
+crypto_sign_ed25519_amd64_64_ORDER2: .quad 0x0000000000000000
+crypto_sign_ed25519_amd64_64_ORDER3: .quad 0x1000000000000000
+
+crypto_sign_ed25519_amd64_64_EC2D0: .quad 0xEBD69B9426B2F146
+crypto_sign_ed25519_amd64_64_EC2D1: .quad 0x00E0149A8283B156
+crypto_sign_ed25519_amd64_64_EC2D2: .quad 0x198E80F2EEF3D130
+crypto_sign_ed25519_amd64_64_EC2D3: .quad 0xA406D9DC56DFFCE7
+
+crypto_sign_ed25519_amd64_64_38: .quad 38
diff --git a/ext/ed25519-amd64-asm/fe25519.h b/ext/ed25519-amd64-asm/fe25519.h
new file mode 100644
index 00000000..33ffabbe
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519.h
@@ -0,0 +1,64 @@
+#ifndef FE25519_H
+#define FE25519_H
+
+#define fe25519 crypto_sign_ed25519_amd64_64_fe25519
+#define fe25519_freeze crypto_sign_ed25519_amd64_64_fe25519_freeze
+#define fe25519_unpack crypto_sign_ed25519_amd64_64_fe25519_unpack
+#define fe25519_pack crypto_sign_ed25519_amd64_64_fe25519_pack
+#define fe25519_iszero_vartime crypto_sign_ed25519_amd64_64_fe25519_iszero_vartime
+#define fe25519_iseq_vartime crypto_sign_ed25519_amd64_64_fe25519_iseq_vartime
+#define fe25519_cmov crypto_sign_ed25519_amd64_64_fe25519_cmov
+#define fe25519_setint crypto_sign_ed25519_amd64_64_fe25519_setint
+#define fe25519_neg crypto_sign_ed25519_amd64_64_fe25519_neg
+#define fe25519_getparity crypto_sign_ed25519_amd64_64_fe25519_getparity
+#define fe25519_add crypto_sign_ed25519_amd64_64_fe25519_add
+#define fe25519_sub crypto_sign_ed25519_amd64_64_fe25519_sub
+#define fe25519_mul crypto_sign_ed25519_amd64_64_fe25519_mul
+#define fe25519_mul121666 crypto_sign_ed25519_amd64_64_fe25519_mul121666
+#define fe25519_square crypto_sign_ed25519_amd64_64_fe25519_square
+#define fe25519_invert crypto_sign_ed25519_amd64_64_fe25519_invert
+#define fe25519_pow2523 crypto_sign_ed25519_amd64_64_fe25519_pow2523
+
+typedef struct
+{
+ unsigned long long v[4];
+}
+fe25519;
+
+void fe25519_freeze(fe25519 *r);
+
+void fe25519_unpack(fe25519 *r, const unsigned char x[32]);
+
+void fe25519_pack(unsigned char r[32], const fe25519 *x);
+
+void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b);
+
+void fe25519_cswap(fe25519 *r, fe25519 *x, unsigned char b);
+
+void fe25519_setint(fe25519 *r, unsigned int v);
+
+void fe25519_neg(fe25519 *r, const fe25519 *x);
+
+unsigned char fe25519_getparity(const fe25519 *x);
+
+int fe25519_iszero_vartime(const fe25519 *x);
+
+int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y);
+
+void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y);
+
+void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y);
+
+void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y);
+
+void fe25519_mul121666(fe25519 *r, const fe25519 *x);
+
+void fe25519_square(fe25519 *r, const fe25519 *x);
+
+void fe25519_pow(fe25519 *r, const fe25519 *x, const unsigned char *e);
+
+void fe25519_invert(fe25519 *r, const fe25519 *x);
+
+void fe25519_pow2523(fe25519 *r, const fe25519 *x);
+
+#endif
diff --git a/ext/ed25519-amd64-asm/fe25519_add.s b/ext/ed25519-amd64-asm/fe25519_add.s
new file mode 100644
index 00000000..b2e56252
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_add.s
@@ -0,0 +1,189 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 addt0
+
+# qhasm: int64 addt1
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_add
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_fe25519_add
+.globl crypto_sign_ed25519_amd64_64_fe25519_add
+_crypto_sign_ed25519_amd64_64_fe25519_add:
+crypto_sign_ed25519_amd64_64_fe25519_add:
+mov %rsp,%r11
+and $31,%r11
+add $0,%r11
+sub %r11,%rsp
+
+# qhasm: r0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>r0=int64#4
+# asm 2: movq 0(<xp=%rsi),>r0=%rcx
+movq 0(%rsi),%rcx
+
+# qhasm: r1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>r1=int64#5
+# asm 2: movq 8(<xp=%rsi),>r1=%r8
+movq 8(%rsi),%r8
+
+# qhasm: r2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>r2=int64#6
+# asm 2: movq 16(<xp=%rsi),>r2=%r9
+movq 16(%rsi),%r9
+
+# qhasm: r3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>r3=int64#2
+# asm 2: movq 24(<xp=%rsi),>r3=%rsi
+movq 24(%rsi),%rsi
+
+# qhasm: carry? r0 += *(uint64 *)(yp + 0)
+# asm 1: addq 0(<yp=int64#3),<r0=int64#4
+# asm 2: addq 0(<yp=%rdx),<r0=%rcx
+addq 0(%rdx),%rcx
+
+# qhasm: carry? r1 += *(uint64 *)(yp + 8) + carry
+# asm 1: adcq 8(<yp=int64#3),<r1=int64#5
+# asm 2: adcq 8(<yp=%rdx),<r1=%r8
+adcq 8(%rdx),%r8
+
+# qhasm: carry? r2 += *(uint64 *)(yp + 16) + carry
+# asm 1: adcq 16(<yp=int64#3),<r2=int64#6
+# asm 2: adcq 16(<yp=%rdx),<r2=%r9
+adcq 16(%rdx),%r9
+
+# qhasm: carry? r3 += *(uint64 *)(yp + 24) + carry
+# asm 1: adcq 24(<yp=int64#3),<r3=int64#2
+# asm 2: adcq 24(<yp=%rdx),<r3=%rsi
+adcq 24(%rdx),%rsi
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#3
+# asm 2: mov $0,>addt0=%rdx
+mov $0,%rdx
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#7
+# asm 2: mov $38,>addt1=%rax
+mov $38,%rax
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#3,<addt1=int64#7
+# asm 2: cmovae <addt0=%rdx,<addt1=%rax
+cmovae %rdx,%rax
+
+# qhasm: carry? r0 += addt1
+# asm 1: add <addt1=int64#7,<r0=int64#4
+# asm 2: add <addt1=%rax,<r0=%rcx
+add %rax,%rcx
+
+# qhasm: carry? r1 += addt0 + carry
+# asm 1: adc <addt0=int64#3,<r1=int64#5
+# asm 2: adc <addt0=%rdx,<r1=%r8
+adc %rdx,%r8
+
+# qhasm: carry? r2 += addt0 + carry
+# asm 1: adc <addt0=int64#3,<r2=int64#6
+# asm 2: adc <addt0=%rdx,<r2=%r9
+adc %rdx,%r9
+
+# qhasm: carry? r3 += addt0 + carry
+# asm 1: adc <addt0=int64#3,<r3=int64#2
+# asm 2: adc <addt0=%rdx,<r3=%rsi
+adc %rdx,%rsi
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#7,<addt0=int64#3
+# asm 2: cmovc <addt1=%rax,<addt0=%rdx
+cmovc %rax,%rdx
+
+# qhasm: r0 += addt0
+# asm 1: add <addt0=int64#3,<r0=int64#4
+# asm 2: add <addt0=%rdx,<r0=%rcx
+add %rdx,%rcx
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#4,0(<rp=int64#1)
+# asm 2: movq <r0=%rcx,0(<rp=%rdi)
+movq %rcx,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#5,8(<rp=int64#1)
+# asm 2: movq <r1=%r8,8(<rp=%rdi)
+movq %r8,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#6,16(<rp=int64#1)
+# asm 2: movq <r2=%r9,16(<rp=%rdi)
+movq %r9,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#2,24(<rp=int64#1)
+# asm 2: movq <r3=%rsi,24(<rp=%rdi)
+movq %rsi,24(%rdi)
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/fe25519_freeze.s b/ext/ed25519-amd64-asm/fe25519_freeze.s
new file mode 100644
index 00000000..dea29021
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_freeze.s
@@ -0,0 +1,322 @@
+
+# qhasm: int64 rp
+
+# qhasm: input rp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 two63
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_freeze
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_fe25519_freeze
+.globl crypto_sign_ed25519_amd64_64_fe25519_freeze
+_crypto_sign_ed25519_amd64_64_fe25519_freeze:
+crypto_sign_ed25519_amd64_64_fe25519_freeze:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: r0 = *(uint64 *) (rp + 0)
+# asm 1: movq 0(<rp=int64#1),>r0=int64#2
+# asm 2: movq 0(<rp=%rdi),>r0=%rsi
+movq 0(%rdi),%rsi
+
+# qhasm: r1 = *(uint64 *) (rp + 8)
+# asm 1: movq 8(<rp=int64#1),>r1=int64#3
+# asm 2: movq 8(<rp=%rdi),>r1=%rdx
+movq 8(%rdi),%rdx
+
+# qhasm: r2 = *(uint64 *) (rp + 16)
+# asm 1: movq 16(<rp=int64#1),>r2=int64#4
+# asm 2: movq 16(<rp=%rdi),>r2=%rcx
+movq 16(%rdi),%rcx
+
+# qhasm: r3 = *(uint64 *) (rp + 24)
+# asm 1: movq 24(<rp=int64#1),>r3=int64#5
+# asm 2: movq 24(<rp=%rdi),>r3=%r8
+movq 24(%rdi),%r8
+
+# qhasm: t0 = r0
+# asm 1: mov <r0=int64#2,>t0=int64#6
+# asm 2: mov <r0=%rsi,>t0=%r9
+mov %rsi,%r9
+
+# qhasm: t1 = r1
+# asm 1: mov <r1=int64#3,>t1=int64#7
+# asm 2: mov <r1=%rdx,>t1=%rax
+mov %rdx,%rax
+
+# qhasm: t2 = r2
+# asm 1: mov <r2=int64#4,>t2=int64#8
+# asm 2: mov <r2=%rcx,>t2=%r10
+mov %rcx,%r10
+
+# qhasm: t3 = r3
+# asm 1: mov <r3=int64#5,>t3=int64#9
+# asm 2: mov <r3=%r8,>t3=%r11
+mov %r8,%r11
+
+# qhasm: two63 = 1
+# asm 1: mov $1,>two63=int64#10
+# asm 2: mov $1,>two63=%r12
+mov $1,%r12
+
+# qhasm: two63 <<= 63
+# asm 1: shl $63,<two63=int64#10
+# asm 2: shl $63,<two63=%r12
+shl $63,%r12
+
+# qhasm: carry? t0 += 19
+# asm 1: add $19,<t0=int64#6
+# asm 2: add $19,<t0=%r9
+add $19,%r9
+
+# qhasm: carry? t1 += 0 + carry
+# asm 1: adc $0,<t1=int64#7
+# asm 2: adc $0,<t1=%rax
+adc $0,%rax
+
+# qhasm: carry? t2 += 0 + carry
+# asm 1: adc $0,<t2=int64#8
+# asm 2: adc $0,<t2=%r10
+adc $0,%r10
+
+# qhasm: carry? t3 += two63 + carry
+# asm 1: adc <two63=int64#10,<t3=int64#9
+# asm 2: adc <two63=%r12,<t3=%r11
+adc %r12,%r11
+
+# qhasm: r0 = t0 if carry
+# asm 1: cmovc <t0=int64#6,<r0=int64#2
+# asm 2: cmovc <t0=%r9,<r0=%rsi
+cmovc %r9,%rsi
+
+# qhasm: r1 = t1 if carry
+# asm 1: cmovc <t1=int64#7,<r1=int64#3
+# asm 2: cmovc <t1=%rax,<r1=%rdx
+cmovc %rax,%rdx
+
+# qhasm: r2 = t2 if carry
+# asm 1: cmovc <t2=int64#8,<r2=int64#4
+# asm 2: cmovc <t2=%r10,<r2=%rcx
+cmovc %r10,%rcx
+
+# qhasm: r3 = t3 if carry
+# asm 1: cmovc <t3=int64#9,<r3=int64#5
+# asm 2: cmovc <t3=%r11,<r3=%r8
+cmovc %r11,%r8
+
+# qhasm: t0 = r0
+# asm 1: mov <r0=int64#2,>t0=int64#6
+# asm 2: mov <r0=%rsi,>t0=%r9
+mov %rsi,%r9
+
+# qhasm: t1 = r1
+# asm 1: mov <r1=int64#3,>t1=int64#7
+# asm 2: mov <r1=%rdx,>t1=%rax
+mov %rdx,%rax
+
+# qhasm: t2 = r2
+# asm 1: mov <r2=int64#4,>t2=int64#8
+# asm 2: mov <r2=%rcx,>t2=%r10
+mov %rcx,%r10
+
+# qhasm: t3 = r3
+# asm 1: mov <r3=int64#5,>t3=int64#9
+# asm 2: mov <r3=%r8,>t3=%r11
+mov %r8,%r11
+
+# qhasm: carry? t0 += 19
+# asm 1: add $19,<t0=int64#6
+# asm 2: add $19,<t0=%r9
+add $19,%r9
+
+# qhasm: carry? t1 += 0 + carry
+# asm 1: adc $0,<t1=int64#7
+# asm 2: adc $0,<t1=%rax
+adc $0,%rax
+
+# qhasm: carry? t2 += 0 + carry
+# asm 1: adc $0,<t2=int64#8
+# asm 2: adc $0,<t2=%r10
+adc $0,%r10
+
+# qhasm: carry? t3 += two63 + carry
+# asm 1: adc <two63=int64#10,<t3=int64#9
+# asm 2: adc <two63=%r12,<t3=%r11
+adc %r12,%r11
+
+# qhasm: r0 = t0 if carry
+# asm 1: cmovc <t0=int64#6,<r0=int64#2
+# asm 2: cmovc <t0=%r9,<r0=%rsi
+cmovc %r9,%rsi
+
+# qhasm: r1 = t1 if carry
+# asm 1: cmovc <t1=int64#7,<r1=int64#3
+# asm 2: cmovc <t1=%rax,<r1=%rdx
+cmovc %rax,%rdx
+
+# qhasm: r2 = t2 if carry
+# asm 1: cmovc <t2=int64#8,<r2=int64#4
+# asm 2: cmovc <t2=%r10,<r2=%rcx
+cmovc %r10,%rcx
+
+# qhasm: r3 = t3 if carry
+# asm 1: cmovc <t3=int64#9,<r3=int64#5
+# asm 2: cmovc <t3=%r11,<r3=%r8
+cmovc %r11,%r8
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#2,0(<rp=int64#1)
+# asm 2: movq <r0=%rsi,0(<rp=%rdi)
+movq %rsi,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#3,8(<rp=int64#1)
+# asm 2: movq <r1=%rdx,8(<rp=%rdi)
+movq %rdx,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#4,16(<rp=int64#1)
+# asm 2: movq <r2=%rcx,16(<rp=%rdi)
+movq %rcx,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#5,24(<rp=int64#1)
+# asm 2: movq <r3=%r8,24(<rp=%rdi)
+movq %r8,24(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/fe25519_getparity.c b/ext/ed25519-amd64-asm/fe25519_getparity.c
new file mode 100644
index 00000000..a003ec8f
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_getparity.c
@@ -0,0 +1,8 @@
+#include "fe25519.h"
+
+unsigned char fe25519_getparity(const fe25519 *x)
+{
+ fe25519 t = *x;
+ fe25519_freeze(&t);
+ return (unsigned char)t.v[0] & 1;
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_invert.c b/ext/ed25519-amd64-asm/fe25519_invert.c
new file mode 100644
index 00000000..a46d141f
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_invert.c
@@ -0,0 +1,60 @@
+#include "fe25519.h"
+
+void fe25519_invert(fe25519 *r, const fe25519 *x)
+{
+ fe25519 z2;
+ fe25519 z9;
+ fe25519 z11;
+ fe25519 z2_5_0;
+ fe25519 z2_10_0;
+ fe25519 z2_20_0;
+ fe25519 z2_50_0;
+ fe25519 z2_100_0;
+ fe25519 t;
+ int i;
+
+ /* 2 */ fe25519_square(&z2,x);
+ /* 4 */ fe25519_square(&t,&z2);
+ /* 8 */ fe25519_square(&t,&t);
+ /* 9 */ fe25519_mul(&z9,&t,x);
+ /* 11 */ fe25519_mul(&z11,&z9,&z2);
+ /* 22 */ fe25519_square(&t,&z11);
+ /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9);
+
+ /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0);
+ /* 2^20 - 2^10 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); }
+ /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0);
+
+ /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0);
+ /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
+ /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0);
+
+ /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0);
+ /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); }
+ /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0);
+
+ /* 2^41 - 2^1 */ fe25519_square(&t,&t);
+ /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
+ /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0);
+
+ /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0);
+ /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
+ /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0);
+
+ /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0);
+ /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); }
+ /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0);
+
+ /* 2^201 - 2^1 */ fe25519_square(&t,&t);
+ /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
+ /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0);
+
+ /* 2^251 - 2^1 */ fe25519_square(&t,&t);
+ /* 2^252 - 2^2 */ fe25519_square(&t,&t);
+ /* 2^253 - 2^3 */ fe25519_square(&t,&t);
+
+ /* 2^254 - 2^4 */ fe25519_square(&t,&t);
+
+ /* 2^255 - 2^5 */ fe25519_square(&t,&t);
+ /* 2^255 - 21 */ fe25519_mul(r,&t,&z11);
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_iseq.c b/ext/ed25519-amd64-asm/fe25519_iseq.c
new file mode 100644
index 00000000..bf72f8c9
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_iseq.c
@@ -0,0 +1,14 @@
+#include "fe25519.h"
+
+int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
+{
+ fe25519 t1 = *x;
+ fe25519 t2 = *y;
+ fe25519_freeze(&t1);
+ fe25519_freeze(&t2);
+ if(t1.v[0] != t2.v[0]) return 0;
+ if(t1.v[1] != t2.v[1]) return 0;
+ if(t1.v[2] != t2.v[2]) return 0;
+ if(t1.v[3] != t2.v[3]) return 0;
+ return 1;
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_iszero.c b/ext/ed25519-amd64-asm/fe25519_iszero.c
new file mode 100644
index 00000000..99e4dafa
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_iszero.c
@@ -0,0 +1,12 @@
+#include "fe25519.h"
+
+int fe25519_iszero_vartime(const fe25519 *x)
+{
+ fe25519 t = *x;
+ fe25519_freeze(&t);
+ if (t.v[0]) return 0;
+ if (t.v[1]) return 0;
+ if (t.v[2]) return 0;
+ if (t.v[3]) return 0;
+ return 1;
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_mul.s b/ext/ed25519-amd64-asm/fe25519_mul.s
new file mode 100644
index 00000000..14784281
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_mul.s
@@ -0,0 +1,865 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_mul
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_fe25519_mul
+.globl crypto_sign_ed25519_amd64_64_fe25519_mul
+_crypto_sign_ed25519_amd64_64_fe25519_mul:
+crypto_sign_ed25519_amd64_64_fe25519_mul:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: yp = yp
+# asm 1: mov <yp=int64#3,>yp=int64#4
+# asm 2: mov <yp=%rdx,>yp=%rcx
+mov %rdx,%rcx
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>mulx0=int64#10
+# asm 2: movq 0(<xp=%rsi),>mulx0=%r12
+movq 0(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(yp + 0)
+# asm 1: movq 0(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<yp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: r0 = mulrax
+# asm 1: mov <mulrax=int64#7,>r0=int64#11
+# asm 2: mov <mulrax=%rax,>r0=%r13
+mov %rax,%r13
+
+# qhasm: r1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>r1=int64#12
+# asm 2: mov <mulrdx=%rdx,>r1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(yp + 8)
+# asm 1: movq 8(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<yp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? r1 += mulrax
+# asm 1: add <mulrax=int64#7,<r1=int64#12
+# asm 2: add <mulrax=%rax,<r1=%r14
+add %rax,%r14
+
+# qhasm: r2 = 0
+# asm 1: mov $0,>r2=int64#13
+# asm 2: mov $0,>r2=%r15
+mov $0,%r15
+
+# qhasm: r2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<r2=int64#13
+# asm 2: adc <mulrdx=%rdx,<r2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(yp + 16)
+# asm 1: movq 16(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<yp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? r2 += mulrax
+# asm 1: add <mulrax=int64#7,<r2=int64#13
+# asm 2: add <mulrax=%rax,<r2=%r15
+add %rax,%r15
+
+# qhasm: r3 = 0
+# asm 1: mov $0,>r3=int64#14
+# asm 2: mov $0,>r3=%rbx
+mov $0,%rbx
+
+# qhasm: r3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<r3=int64#14
+# asm 2: adc <mulrdx=%rdx,<r3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(yp + 24)
+# asm 1: movq 24(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<yp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? r3 += mulrax
+# asm 1: add <mulrax=int64#7,<r3=int64#14
+# asm 2: add <mulrax=%rax,<r3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>mulx1=int64#10
+# asm 2: movq 8(<xp=%rsi),>mulx1=%r12
+movq 8(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(yp + 0)
+# asm 1: movq 0(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<yp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? r1 += mulrax
+# asm 1: add <mulrax=int64#7,<r1=int64#12
+# asm 2: add <mulrax=%rax,<r1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(yp + 8)
+# asm 1: movq 8(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<yp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? r2 += mulrax
+# asm 1: add <mulrax=int64#7,<r2=int64#13
+# asm 2: add <mulrax=%rax,<r2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? r2 += mulc
+# asm 1: add <mulc=int64#15,<r2=int64#13
+# asm 2: add <mulc=%rbp,<r2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(yp + 16)
+# asm 1: movq 16(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<yp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? r3 += mulrax
+# asm 1: add <mulrax=int64#7,<r3=int64#14
+# asm 2: add <mulrax=%rax,<r3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? r3 += mulc
+# asm 1: add <mulc=int64#15,<r3=int64#14
+# asm 2: add <mulc=%rbp,<r3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(yp + 24)
+# asm 1: movq 24(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<yp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>mulx2=int64#10
+# asm 2: movq 16(<xp=%rsi),>mulx2=%r12
+movq 16(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(yp + 0)
+# asm 1: movq 0(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<yp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? r2 += mulrax
+# asm 1: add <mulrax=int64#7,<r2=int64#13
+# asm 2: add <mulrax=%rax,<r2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(yp + 8)
+# asm 1: movq 8(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<yp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? r3 += mulrax
+# asm 1: add <mulrax=int64#7,<r3=int64#14
+# asm 2: add <mulrax=%rax,<r3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? r3 += mulc
+# asm 1: add <mulc=int64#15,<r3=int64#14
+# asm 2: add <mulc=%rbp,<r3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(yp + 16)
+# asm 1: movq 16(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<yp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(yp + 24)
+# asm 1: movq 24(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<yp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>mulx3=int64#2
+# asm 2: movq 24(<xp=%rsi),>mulx3=%rsi
+movq 24(%rsi),%rsi
+
+# qhasm: mulrax = *(uint64 *)(yp + 0)
+# asm 1: movq 0(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<yp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? r3 += mulrax
+# asm 1: add <mulrax=int64#7,<r3=int64#14
+# asm 2: add <mulrax=%rax,<r3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(yp + 8)
+# asm 1: movq 8(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<yp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#10,<mulr4=int64#5
+# asm 2: add <mulc=%r12,<mulr4=%r8
+add %r12,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(yp + 16)
+# asm 1: movq 16(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<yp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#10,<mulr5=int64#6
+# asm 2: add <mulc=%r12,<mulr5=%r9
+add %r12,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(yp + 24)
+# asm 1: movq 24(<yp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<yp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#10,<mulr6=int64#8
+# asm 2: add <mulc=%r12,<mulr6=%r10
+add %r12,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? r0 += mulr4
+# asm 1: add <mulr4=int64#2,<r0=int64#11
+# asm 2: add <mulr4=%rsi,<r0=%r13
+add %rsi,%r13
+
+# qhasm: carry? r1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<r1=int64#12
+# asm 2: adc <mulr5=%rcx,<r1=%r14
+adc %rcx,%r14
+
+# qhasm: carry? r2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<r2=int64#13
+# asm 2: adc <mulr6=%r8,<r2=%r15
+adc %r8,%r15
+
+# qhasm: carry? r3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<r3=int64#14
+# asm 2: adc <mulr7=%r9,<r3=%rbx
+adc %r9,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? r0 += mulr8
+# asm 1: add <mulr8=int64#3,<r0=int64#11
+# asm 2: add <mulr8=%rdx,<r0=%r13
+add %rdx,%r13
+
+# qhasm: carry? r1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<r1=int64#12
+# asm 2: adc <mulzero=%rsi,<r1=%r14
+adc %rsi,%r14
+
+# qhasm: carry? r2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<r2=int64#13
+# asm 2: adc <mulzero=%rsi,<r2=%r15
+adc %rsi,%r15
+
+# qhasm: carry? r3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<r3=int64#14
+# asm 2: adc <mulzero=%rsi,<r3=%rbx
+adc %rsi,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: r0 += mulzero
+# asm 1: add <mulzero=int64#2,<r0=int64#11
+# asm 2: add <mulzero=%rsi,<r0=%r13
+add %rsi,%r13
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#12,8(<rp=int64#1)
+# asm 2: movq <r1=%r14,8(<rp=%rdi)
+movq %r14,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#13,16(<rp=int64#1)
+# asm 2: movq <r2=%r15,16(<rp=%rdi)
+movq %r15,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#14,24(<rp=int64#1)
+# asm 2: movq <r3=%rbx,24(<rp=%rdi)
+movq %rbx,24(%rdi)
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#11,0(<rp=int64#1)
+# asm 2: movq <r0=%r13,0(<rp=%rdi)
+movq %r13,0(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/fe25519_neg.c b/ext/ed25519-amd64-asm/fe25519_neg.c
new file mode 100644
index 00000000..235b209d
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_neg.c
@@ -0,0 +1,8 @@
+#include "fe25519.h"
+
+void fe25519_neg(fe25519 *r, const fe25519 *x)
+{
+ fe25519 t;
+ fe25519_setint(&t,0);
+ fe25519_sub(r,&t,x);
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_pack.c b/ext/ed25519-amd64-asm/fe25519_pack.c
new file mode 100644
index 00000000..caf51853
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_pack.c
@@ -0,0 +1,13 @@
+#include "fe25519.h"
+
+/* Assumes input x being reduced below 2^255 */
+void fe25519_pack(unsigned char r[32], const fe25519 *x)
+{
+ int i;
+ fe25519 t;
+ t = *x;
+ fe25519_freeze(&t);
+ /* assuming little-endian */
+ for(i=0;i<32;i++) r[i] = i[(unsigned char *)&t.v];
+}
+
diff --git a/ext/ed25519-amd64-asm/fe25519_pow2523.c b/ext/ed25519-amd64-asm/fe25519_pow2523.c
new file mode 100644
index 00000000..60042a0a
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_pow2523.c
@@ -0,0 +1,55 @@
+#include "fe25519.h"
+
+void fe25519_pow2523(fe25519 *r, const fe25519 *x)
+{
+ fe25519 z2;
+ fe25519 z9;
+ fe25519 z11;
+ fe25519 z2_5_0;
+ fe25519 z2_10_0;
+ fe25519 z2_20_0;
+ fe25519 z2_50_0;
+ fe25519 z2_100_0;
+ fe25519 t;
+ int i;
+
+ /* 2 */ fe25519_square(&z2,x);
+ /* 4 */ fe25519_square(&t,&z2);
+ /* 8 */ fe25519_square(&t,&t);
+ /* 9 */ fe25519_mul(&z9,&t,x);
+ /* 11 */ fe25519_mul(&z11,&z9,&z2);
+ /* 22 */ fe25519_square(&t,&z11);
+ /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9);
+
+ /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0);
+ /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); }
+ /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0);
+
+ /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0);
+ /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
+ /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0);
+
+ /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0);
+ /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); }
+ /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0);
+
+ /* 2^41 - 2^1 */ fe25519_square(&t,&t);
+ /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
+ /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0);
+
+ /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0);
+ /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
+ /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0);
+
+ /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0);
+ /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); }
+ /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0);
+
+ /* 2^201 - 2^1 */ fe25519_square(&t,&t);
+ /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
+ /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0);
+
+ /* 2^251 - 2^1 */ fe25519_square(&t,&t);
+ /* 2^252 - 2^2 */ fe25519_square(&t,&t);
+ /* 2^252 - 3 */ fe25519_mul(r,&t,x);
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_setint.c b/ext/ed25519-amd64-asm/fe25519_setint.c
new file mode 100644
index 00000000..585c4bdd
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_setint.c
@@ -0,0 +1,9 @@
+#include "fe25519.h"
+
+void fe25519_setint(fe25519 *r, unsigned int v)
+{
+ r->v[0] = v;
+ r->v[1] = 0;
+ r->v[2] = 0;
+ r->v[3] = 0;
+}
diff --git a/ext/ed25519-amd64-asm/fe25519_square.s b/ext/ed25519-amd64-asm/fe25519_square.s
new file mode 100644
index 00000000..a74d9e88
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_square.s
@@ -0,0 +1,639 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 squarer4
+
+# qhasm: int64 squarer5
+
+# qhasm: int64 squarer6
+
+# qhasm: int64 squarer7
+
+# qhasm: int64 squarer8
+
+# qhasm: int64 squarerax
+
+# qhasm: int64 squarerdx
+
+# qhasm: int64 squaret1
+
+# qhasm: int64 squaret2
+
+# qhasm: int64 squaret3
+
+# qhasm: int64 squarec
+
+# qhasm: int64 squarezero
+
+# qhasm: int64 squarei38
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_square
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_fe25519_square
+.globl crypto_sign_ed25519_amd64_64_fe25519_square
+_crypto_sign_ed25519_amd64_64_fe25519_square:
+crypto_sign_ed25519_amd64_64_fe25519_square:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 8(<xp=%rsi),>squarerax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0)
+# asm 1: mulq 0(<xp=int64#2)
+# asm 2: mulq 0(<xp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: r1 = squarerax
+# asm 1: mov <squarerax=int64#7,>r1=int64#5
+# asm 2: mov <squarerax=%rax,>r1=%r8
+mov %rax,%r8
+
+# qhasm: r2 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>r2=int64#6
+# asm 2: mov <squarerdx=%rdx,>r2=%r9
+mov %rdx,%r9
+
+# qhasm: squarerax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 16(<xp=%rsi),>squarerax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 8)
+# asm 1: mulq 8(<xp=int64#2)
+# asm 2: mulq 8(<xp=%rsi)
+mulq 8(%rsi)
+
+# qhasm: r3 = squarerax
+# asm 1: mov <squarerax=int64#7,>r3=int64#8
+# asm 2: mov <squarerax=%rax,>r3=%r10
+mov %rax,%r10
+
+# qhasm: squarer4 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer4=int64#9
+# asm 2: mov <squarerdx=%rdx,>squarer4=%r11
+mov %rdx,%r11
+
+# qhasm: squarerax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<xp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 16)
+# asm 1: mulq 16(<xp=int64#2)
+# asm 2: mulq 16(<xp=%rsi)
+mulq 16(%rsi)
+
+# qhasm: squarer5 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer5=int64#10
+# asm 2: mov <squarerax=%rax,>squarer5=%r12
+mov %rax,%r12
+
+# qhasm: squarer6 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer6=int64#11
+# asm 2: mov <squarerdx=%rdx,>squarer6=%r13
+mov %rdx,%r13
+
+# qhasm: squarerax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 16(<xp=%rsi),>squarerax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0)
+# asm 1: mulq 0(<xp=int64#2)
+# asm 2: mulq 0(<xp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: carry? r2 += squarerax
+# asm 1: add <squarerax=int64#7,<r2=int64#6
+# asm 2: add <squarerax=%rax,<r2=%r9
+add %rax,%r9
+
+# qhasm: carry? r3 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<r3=int64#8
+# asm 2: adc <squarerdx=%rdx,<r3=%r10
+adc %rdx,%r10
+
+# qhasm: squarer4 += 0 + carry
+# asm 1: adc $0,<squarer4=int64#9
+# asm 2: adc $0,<squarer4=%r11
+adc $0,%r11
+
+# qhasm: squarerax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<xp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 8)
+# asm 1: mulq 8(<xp=int64#2)
+# asm 2: mulq 8(<xp=%rsi)
+mulq 8(%rsi)
+
+# qhasm: carry? squarer4 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer4=int64#9
+# asm 2: add <squarerax=%rax,<squarer4=%r11
+add %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarerax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<xp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0)
+# asm 1: mulq 0(<xp=int64#2)
+# asm 2: mulq 0(<xp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: carry? r3 += squarerax
+# asm 1: add <squarerax=int64#7,<r3=int64#8
+# asm 2: add <squarerax=%rax,<r3=%r10
+add %rax,%r10
+
+# qhasm: carry? squarer4 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer4=int64#9
+# asm 2: adc <squarerdx=%rdx,<squarer4=%r11
+adc %rdx,%r11
+
+# qhasm: carry? squarer5 += 0 + carry
+# asm 1: adc $0,<squarer5=int64#10
+# asm 2: adc $0,<squarer5=%r12
+adc $0,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: carry? r1 += r1
+# asm 1: add <r1=int64#5,<r1=int64#5
+# asm 2: add <r1=%r8,<r1=%r8
+add %r8,%r8
+
+# qhasm: carry? r2 += r2 + carry
+# asm 1: adc <r2=int64#6,<r2=int64#6
+# asm 2: adc <r2=%r9,<r2=%r9
+adc %r9,%r9
+
+# qhasm: carry? r3 += r3 + carry
+# asm 1: adc <r3=int64#8,<r3=int64#8
+# asm 2: adc <r3=%r10,<r3=%r10
+adc %r10,%r10
+
+# qhasm: carry? squarer4 += squarer4 + carry
+# asm 1: adc <squarer4=int64#9,<squarer4=int64#9
+# asm 2: adc <squarer4=%r11,<squarer4=%r11
+adc %r11,%r11
+
+# qhasm: carry? squarer5 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<squarer5=int64#10
+# asm 2: adc <squarer5=%r12,<squarer5=%r12
+adc %r12,%r12
+
+# qhasm: carry? squarer6 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<squarer6=int64#11
+# asm 2: adc <squarer6=%r13,<squarer6=%r13
+adc %r13,%r13
+
+# qhasm: squarer7 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<squarer7=int64#4
+# asm 2: adc <squarer7=%rcx,<squarer7=%rcx
+adc %rcx,%rcx
+
+# qhasm: squarerax = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 0(<xp=%rsi),>squarerax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 0)
+# asm 1: mulq 0(<xp=int64#2)
+# asm 2: mulq 0(<xp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: r0 = squarerax
+# asm 1: mov <squarerax=int64#7,>r0=int64#12
+# asm 2: mov <squarerax=%rax,>r0=%r14
+mov %rax,%r14
+
+# qhasm: squaret1 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret1=int64#13
+# asm 2: mov <squarerdx=%rdx,>squaret1=%r15
+mov %rdx,%r15
+
+# qhasm: squarerax = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 8(<xp=%rsi),>squarerax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 8)
+# asm 1: mulq 8(<xp=int64#2)
+# asm 2: mulq 8(<xp=%rsi)
+mulq 8(%rsi)
+
+# qhasm: squaret2 = squarerax
+# asm 1: mov <squarerax=int64#7,>squaret2=int64#14
+# asm 2: mov <squarerax=%rax,>squaret2=%rbx
+mov %rax,%rbx
+
+# qhasm: squaret3 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret3=int64#15
+# asm 2: mov <squarerdx=%rdx,>squaret3=%rbp
+mov %rdx,%rbp
+
+# qhasm: squarerax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 16(<xp=%rsi),>squarerax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 16)
+# asm 1: mulq 16(<xp=int64#2)
+# asm 2: mulq 16(<xp=%rsi)
+mulq 16(%rsi)
+
+# qhasm: carry? r1 += squaret1
+# asm 1: add <squaret1=int64#13,<r1=int64#5
+# asm 2: add <squaret1=%r15,<r1=%r8
+add %r15,%r8
+
+# qhasm: carry? r2 += squaret2 + carry
+# asm 1: adc <squaret2=int64#14,<r2=int64#6
+# asm 2: adc <squaret2=%rbx,<r2=%r9
+adc %rbx,%r9
+
+# qhasm: carry? r3 += squaret3 + carry
+# asm 1: adc <squaret3=int64#15,<r3=int64#8
+# asm 2: adc <squaret3=%rbp,<r3=%r10
+adc %rbp,%r10
+
+# qhasm: carry? squarer4 += squarerax + carry
+# asm 1: adc <squarerax=int64#7,<squarer4=int64#9
+# asm 2: adc <squarerax=%rax,<squarer4=%r11
+adc %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<xp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(xp + 24)
+# asm 1: mulq 24(<xp=int64#2)
+# asm 2: mulq 24(<xp=%rsi)
+mulq 24(%rsi)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: squarerax = squarer4
+# asm 1: mov <squarer4=int64#9,>squarerax=int64#7
+# asm 2: mov <squarer4=%r11,>squarerax=%rax
+mov %r11,%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: squarer4 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer4=int64#2
+# asm 2: mov <squarerax=%rax,>squarer4=%rsi
+mov %rax,%rsi
+
+# qhasm: squarerax = squarer5
+# asm 1: mov <squarer5=int64#10,>squarerax=int64#7
+# asm 2: mov <squarer5=%r12,>squarerax=%rax
+mov %r12,%rax
+
+# qhasm: squarer5 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer5=int64#9
+# asm 2: mov <squarerdx=%rdx,>squarer5=%r11
+mov %rdx,%r11
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer5 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer5=int64#9
+# asm 2: add <squarerax=%rax,<squarer5=%r11
+add %rax,%r11
+
+# qhasm: squarerax = squarer6
+# asm 1: mov <squarer6=int64#11,>squarerax=int64#7
+# asm 2: mov <squarer6=%r13,>squarerax=%rax
+mov %r13,%rax
+
+# qhasm: squarer6 = 0
+# asm 1: mov $0,>squarer6=int64#10
+# asm 2: mov $0,>squarer6=%r12
+mov $0,%r12
+
+# qhasm: squarer6 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer6=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer6=%r12
+adc %rdx,%r12
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#10
+# asm 2: add <squarerax=%rax,<squarer6=%r12
+add %rax,%r12
+
+# qhasm: squarerax = squarer7
+# asm 1: mov <squarer7=int64#4,>squarerax=int64#7
+# asm 2: mov <squarer7=%rcx,>squarerax=%rax
+mov %rcx,%rax
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer7 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer7=int64#4
+# asm 2: add <squarerax=%rax,<squarer7=%rcx
+add %rax,%rcx
+
+# qhasm: squarer8 = 0
+# asm 1: mov $0,>squarer8=int64#7
+# asm 2: mov $0,>squarer8=%rax
+mov $0,%rax
+
+# qhasm: squarer8 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer8=int64#7
+# asm 2: adc <squarerdx=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? r0 += squarer4
+# asm 1: add <squarer4=int64#2,<r0=int64#12
+# asm 2: add <squarer4=%rsi,<r0=%r14
+add %rsi,%r14
+
+# qhasm: carry? r1 += squarer5 + carry
+# asm 1: adc <squarer5=int64#9,<r1=int64#5
+# asm 2: adc <squarer5=%r11,<r1=%r8
+adc %r11,%r8
+
+# qhasm: carry? r2 += squarer6 + carry
+# asm 1: adc <squarer6=int64#10,<r2=int64#6
+# asm 2: adc <squarer6=%r12,<r2=%r9
+adc %r12,%r9
+
+# qhasm: carry? r3 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<r3=int64#8
+# asm 2: adc <squarer7=%rcx,<r3=%r10
+adc %rcx,%r10
+
+# qhasm: squarezero = 0
+# asm 1: mov $0,>squarezero=int64#2
+# asm 2: mov $0,>squarezero=%rsi
+mov $0,%rsi
+
+# qhasm: squarer8 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<squarer8=int64#7
+# asm 2: adc <squarezero=%rsi,<squarer8=%rax
+adc %rsi,%rax
+
+# qhasm: squarer8 *= 38
+# asm 1: imulq $38,<squarer8=int64#7,>squarer8=int64#3
+# asm 2: imulq $38,<squarer8=%rax,>squarer8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? r0 += squarer8
+# asm 1: add <squarer8=int64#3,<r0=int64#12
+# asm 2: add <squarer8=%rdx,<r0=%r14
+add %rdx,%r14
+
+# qhasm: carry? r1 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<r1=int64#5
+# asm 2: adc <squarezero=%rsi,<r1=%r8
+adc %rsi,%r8
+
+# qhasm: carry? r2 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<r2=int64#6
+# asm 2: adc <squarezero=%rsi,<r2=%r9
+adc %rsi,%r9
+
+# qhasm: carry? r3 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<r3=int64#8
+# asm 2: adc <squarezero=%rsi,<r3=%r10
+adc %rsi,%r10
+
+# qhasm: squarezero += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<squarezero=int64#2
+# asm 2: adc <squarezero=%rsi,<squarezero=%rsi
+adc %rsi,%rsi
+
+# qhasm: squarezero *= 38
+# asm 1: imulq $38,<squarezero=int64#2,>squarezero=int64#2
+# asm 2: imulq $38,<squarezero=%rsi,>squarezero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: r0 += squarezero
+# asm 1: add <squarezero=int64#2,<r0=int64#12
+# asm 2: add <squarezero=%rsi,<r0=%r14
+add %rsi,%r14
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#5,8(<rp=int64#1)
+# asm 2: movq <r1=%r8,8(<rp=%rdi)
+movq %r8,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#6,16(<rp=int64#1)
+# asm 2: movq <r2=%r9,16(<rp=%rdi)
+movq %r9,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#8,24(<rp=int64#1)
+# asm 2: movq <r3=%r10,24(<rp=%rdi)
+movq %r10,24(%rdi)
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#12,0(<rp=int64#1)
+# asm 2: movq <r0=%r14,0(<rp=%rdi)
+movq %r14,0(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/fe25519_sub.s b/ext/ed25519-amd64-asm/fe25519_sub.s
new file mode 100644
index 00000000..0b395bce
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_sub.s
@@ -0,0 +1,189 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_fe25519_sub
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_fe25519_sub
+.globl crypto_sign_ed25519_amd64_64_fe25519_sub
+_crypto_sign_ed25519_amd64_64_fe25519_sub:
+crypto_sign_ed25519_amd64_64_fe25519_sub:
+mov %rsp,%r11
+and $31,%r11
+add $0,%r11
+sub %r11,%rsp
+
+# qhasm: r0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>r0=int64#4
+# asm 2: movq 0(<xp=%rsi),>r0=%rcx
+movq 0(%rsi),%rcx
+
+# qhasm: r1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>r1=int64#5
+# asm 2: movq 8(<xp=%rsi),>r1=%r8
+movq 8(%rsi),%r8
+
+# qhasm: r2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>r2=int64#6
+# asm 2: movq 16(<xp=%rsi),>r2=%r9
+movq 16(%rsi),%r9
+
+# qhasm: r3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>r3=int64#2
+# asm 2: movq 24(<xp=%rsi),>r3=%rsi
+movq 24(%rsi),%rsi
+
+# qhasm: carry? r0 -= *(uint64 *)(yp + 0)
+# asm 1: subq 0(<yp=int64#3),<r0=int64#4
+# asm 2: subq 0(<yp=%rdx),<r0=%rcx
+subq 0(%rdx),%rcx
+
+# qhasm: carry? r1 -= *(uint64 *)(yp + 8) - carry
+# asm 1: sbbq 8(<yp=int64#3),<r1=int64#5
+# asm 2: sbbq 8(<yp=%rdx),<r1=%r8
+sbbq 8(%rdx),%r8
+
+# qhasm: carry? r2 -= *(uint64 *)(yp + 16) - carry
+# asm 1: sbbq 16(<yp=int64#3),<r2=int64#6
+# asm 2: sbbq 16(<yp=%rdx),<r2=%r9
+sbbq 16(%rdx),%r9
+
+# qhasm: carry? r3 -= *(uint64 *)(yp + 24) - carry
+# asm 1: sbbq 24(<yp=int64#3),<r3=int64#2
+# asm 2: sbbq 24(<yp=%rdx),<r3=%rsi
+sbbq 24(%rdx),%rsi
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#3
+# asm 2: mov $0,>subt0=%rdx
+mov $0,%rdx
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#7
+# asm 2: mov $38,>subt1=%rax
+mov $38,%rax
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#3,<subt1=int64#7
+# asm 2: cmovae <subt0=%rdx,<subt1=%rax
+cmovae %rdx,%rax
+
+# qhasm: carry? r0 -= subt1
+# asm 1: sub <subt1=int64#7,<r0=int64#4
+# asm 2: sub <subt1=%rax,<r0=%rcx
+sub %rax,%rcx
+
+# qhasm: carry? r1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#3,<r1=int64#5
+# asm 2: sbb <subt0=%rdx,<r1=%r8
+sbb %rdx,%r8
+
+# qhasm: carry? r2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#3,<r2=int64#6
+# asm 2: sbb <subt0=%rdx,<r2=%r9
+sbb %rdx,%r9
+
+# qhasm: carry? r3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#3,<r3=int64#2
+# asm 2: sbb <subt0=%rdx,<r3=%rsi
+sbb %rdx,%rsi
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#7,<subt0=int64#3
+# asm 2: cmovc <subt1=%rax,<subt0=%rdx
+cmovc %rax,%rdx
+
+# qhasm: r0 -= subt0
+# asm 1: sub <subt0=int64#3,<r0=int64#4
+# asm 2: sub <subt0=%rdx,<r0=%rcx
+sub %rdx,%rcx
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#4,0(<rp=int64#1)
+# asm 2: movq <r0=%rcx,0(<rp=%rdi)
+movq %rcx,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#5,8(<rp=int64#1)
+# asm 2: movq <r1=%r8,8(<rp=%rdi)
+movq %r8,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#6,16(<rp=int64#1)
+# asm 2: movq <r2=%r9,16(<rp=%rdi)
+movq %r9,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#2,24(<rp=int64#1)
+# asm 2: movq <r3=%rsi,24(<rp=%rdi)
+movq %rsi,24(%rdi)
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/fe25519_unpack.c b/ext/ed25519-amd64-asm/fe25519_unpack.c
new file mode 100644
index 00000000..b3b0f4d5
--- /dev/null
+++ b/ext/ed25519-amd64-asm/fe25519_unpack.c
@@ -0,0 +1,11 @@
+#include "fe25519.h"
+
+void fe25519_unpack(fe25519 *r, const unsigned char x[32])
+{
+ /* assuming little-endian */
+ r->v[0] = *(unsigned long long *)x;
+ r->v[1] = *(((unsigned long long *)x)+1);
+ r->v[2] = *(((unsigned long long *)x)+2);
+ r->v[3] = *(((unsigned long long *)x)+3);
+ r->v[3] &= 0x7fffffffffffffffULL;
+}
diff --git a/ext/ed25519-amd64-asm/ge25519.h b/ext/ed25519-amd64-asm/ge25519.h
new file mode 100644
index 00000000..0b15136b
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519.h
@@ -0,0 +1,95 @@
+#ifndef GE25519_H
+#define GE25519_H
+
+#include "fe25519.h"
+#include "sc25519.h"
+
+#define ge25519 crypto_sign_ed25519_amd64_64_ge25519
+#define ge25519_base crypto_sign_ed25519_amd64_64_ge25519_base
+#define ge25519_unpackneg_vartime crypto_sign_ed25519_amd64_64_unpackneg_vartime
+#define ge25519_pack crypto_sign_ed25519_amd64_64_pack
+#define ge25519_isneutral_vartime crypto_sign_ed25519_amd64_64_isneutral_vartime
+#define ge25519_add crypto_sign_ed25519_amd64_64_ge25519_add
+#define ge25519_double crypto_sign_ed25519_amd64_64_ge25519_double
+#define ge25519_double_scalarmult_vartime crypto_sign_ed25519_amd64_64_double_scalarmult_vartime
+#define ge25519_multi_scalarmult_vartime crypto_sign_ed25519_amd64_64_ge25519_multi_scalarmult_vartime
+#define ge25519_scalarmult_base crypto_sign_ed25519_amd64_64_scalarmult_base
+#define ge25519_p1p1_to_p2 crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2
+#define ge25519_p1p1_to_p3 crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3
+#define ge25519_add_p1p1 crypto_sign_ed25519_amd64_64_ge25519_add_p1p1
+#define ge25519_dbl_p1p1 crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1
+#define choose_t crypto_sign_ed25519_amd64_64_choose_t
+#define ge25519_nielsadd2 crypto_sign_ed25519_amd64_64_ge25519_nielsadd2
+#define ge25519_nielsadd_p1p1 crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1
+#define ge25519_pnielsadd_p1p1 crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1
+
+
+#define ge25519_p3 ge25519
+
+typedef struct
+{
+ fe25519 x;
+ fe25519 y;
+ fe25519 z;
+ fe25519 t;
+} ge25519;
+
+typedef struct
+{
+ fe25519 x;
+ fe25519 z;
+ fe25519 y;
+ fe25519 t;
+} ge25519_p1p1;
+
+typedef struct
+{
+ fe25519 x;
+ fe25519 y;
+ fe25519 z;
+} ge25519_p2;
+
+typedef struct
+{
+ fe25519 ysubx;
+ fe25519 xaddy;
+ fe25519 t2d;
+} ge25519_niels;
+
+typedef struct
+{
+ fe25519 ysubx;
+ fe25519 xaddy;
+ fe25519 z;
+ fe25519 t2d;
+} ge25519_pniels;
+
+extern void ge25519_p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p);
+extern void ge25519_p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p);
+extern void ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q);
+extern void ge25519_dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p);
+extern void choose_t(ge25519_niels *t, unsigned long long pos, signed long long b, const ge25519_niels *base_multiples);
+extern void ge25519_nielsadd2(ge25519_p3 *r, const ge25519_niels *q);
+extern void ge25519_nielsadd_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_niels *q);
+extern void ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_pniels *q);
+
+extern const ge25519 ge25519_base;
+
+extern int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]);
+
+extern void ge25519_pack(unsigned char r[32], const ge25519 *p);
+
+extern int ge25519_isneutral_vartime(const ge25519 *p);
+
+extern void ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q);
+
+extern void ge25519_double(ge25519 *r, const ge25519 *p);
+
+/* computes [s1]p1 + [s2]ge25519_base */
+extern void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const sc25519 *s2);
+
+extern void ge25519_multi_scalarmult_vartime(ge25519 *r, ge25519 *p, sc25519 *s, const unsigned long long npoints);
+
+extern void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s);
+
+#endif
diff --git a/ext/ed25519-amd64-asm/ge25519_add.c b/ext/ed25519-amd64-asm/ge25519_add.c
new file mode 100644
index 00000000..c4d1c68a
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_add.c
@@ -0,0 +1,8 @@
+#include "ge25519.h"
+
+void ge25519_add(ge25519_p3 *r, const ge25519_p3 *p, const ge25519_p3 *q)
+{
+ ge25519_p1p1 grp1p1;
+ ge25519_add_p1p1(&grp1p1, p, q);
+ ge25519_p1p1_to_p3(r, &grp1p1);
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_add_p1p1.s b/ext/ed25519-amd64-asm/ge25519_add_p1p1.s
new file mode 100644
index 00000000..0cb13898
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_add_p1p1.s
@@ -0,0 +1,4554 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 pp
+
+# qhasm: int64 qp
+
+# qhasm: input rp
+
+# qhasm: input pp
+
+# qhasm: input qp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 a0
+
+# qhasm: int64 a1
+
+# qhasm: int64 a2
+
+# qhasm: int64 a3
+
+# qhasm: stack64 a0_stack
+
+# qhasm: stack64 a1_stack
+
+# qhasm: stack64 a2_stack
+
+# qhasm: stack64 a3_stack
+
+# qhasm: int64 b0
+
+# qhasm: int64 b1
+
+# qhasm: int64 b2
+
+# qhasm: int64 b3
+
+# qhasm: stack64 b0_stack
+
+# qhasm: stack64 b1_stack
+
+# qhasm: stack64 b2_stack
+
+# qhasm: stack64 b3_stack
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: stack64 c0_stack
+
+# qhasm: stack64 c1_stack
+
+# qhasm: stack64 c2_stack
+
+# qhasm: stack64 c3_stack
+
+# qhasm: int64 d0
+
+# qhasm: int64 d1
+
+# qhasm: int64 d2
+
+# qhasm: int64 d3
+
+# qhasm: stack64 d0_stack
+
+# qhasm: stack64 d1_stack
+
+# qhasm: stack64 d2_stack
+
+# qhasm: stack64 d3_stack
+
+# qhasm: int64 t10
+
+# qhasm: int64 t11
+
+# qhasm: int64 t12
+
+# qhasm: int64 t13
+
+# qhasm: stack64 t10_stack
+
+# qhasm: stack64 t11_stack
+
+# qhasm: stack64 t12_stack
+
+# qhasm: stack64 t13_stack
+
+# qhasm: int64 t20
+
+# qhasm: int64 t21
+
+# qhasm: int64 t22
+
+# qhasm: int64 t23
+
+# qhasm: stack64 t20_stack
+
+# qhasm: stack64 t21_stack
+
+# qhasm: stack64 t22_stack
+
+# qhasm: stack64 t23_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 rt0
+
+# qhasm: int64 rt1
+
+# qhasm: int64 rt2
+
+# qhasm: int64 rt3
+
+# qhasm: int64 x0
+
+# qhasm: int64 x1
+
+# qhasm: int64 x2
+
+# qhasm: int64 x3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: int64 addt0
+
+# qhasm: int64 addt1
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_add_p1p1
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_add_p1p1
+.globl crypto_sign_ed25519_amd64_64_ge25519_add_p1p1
+_crypto_sign_ed25519_amd64_64_ge25519_add_p1p1:
+crypto_sign_ed25519_amd64_64_ge25519_add_p1p1:
+mov %rsp,%r11
+and $31,%r11
+add $192,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: qp = qp
+# asm 1: mov <qp=int64#3,>qp=int64#4
+# asm 2: mov <qp=%rdx,>qp=%rcx
+mov %rdx,%rcx
+
+# qhasm: a0 = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>a0=int64#3
+# asm 2: movq 32(<pp=%rsi),>a0=%rdx
+movq 32(%rsi),%rdx
+
+# qhasm: a1 = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>a1=int64#5
+# asm 2: movq 40(<pp=%rsi),>a1=%r8
+movq 40(%rsi),%r8
+
+# qhasm: a2 = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>a2=int64#6
+# asm 2: movq 48(<pp=%rsi),>a2=%r9
+movq 48(%rsi),%r9
+
+# qhasm: a3 = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>a3=int64#7
+# asm 2: movq 56(<pp=%rsi),>a3=%rax
+movq 56(%rsi),%rax
+
+# qhasm: b0 = a0
+# asm 1: mov <a0=int64#3,>b0=int64#8
+# asm 2: mov <a0=%rdx,>b0=%r10
+mov %rdx,%r10
+
+# qhasm: b1 = a1
+# asm 1: mov <a1=int64#5,>b1=int64#9
+# asm 2: mov <a1=%r8,>b1=%r11
+mov %r8,%r11
+
+# qhasm: b2 = a2
+# asm 1: mov <a2=int64#6,>b2=int64#10
+# asm 2: mov <a2=%r9,>b2=%r12
+mov %r9,%r12
+
+# qhasm: b3 = a3
+# asm 1: mov <a3=int64#7,>b3=int64#11
+# asm 2: mov <a3=%rax,>b3=%r13
+mov %rax,%r13
+
+# qhasm: carry? a0 -= *(uint64 *)(pp + 0)
+# asm 1: subq 0(<pp=int64#2),<a0=int64#3
+# asm 2: subq 0(<pp=%rsi),<a0=%rdx
+subq 0(%rsi),%rdx
+
+# qhasm: carry? a1 -= *(uint64 *)(pp + 8) - carry
+# asm 1: sbbq 8(<pp=int64#2),<a1=int64#5
+# asm 2: sbbq 8(<pp=%rsi),<a1=%r8
+sbbq 8(%rsi),%r8
+
+# qhasm: carry? a2 -= *(uint64 *)(pp + 16) - carry
+# asm 1: sbbq 16(<pp=int64#2),<a2=int64#6
+# asm 2: sbbq 16(<pp=%rsi),<a2=%r9
+sbbq 16(%rsi),%r9
+
+# qhasm: carry? a3 -= *(uint64 *)(pp + 24) - carry
+# asm 1: sbbq 24(<pp=int64#2),<a3=int64#7
+# asm 2: sbbq 24(<pp=%rsi),<a3=%rax
+sbbq 24(%rsi),%rax
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#12
+# asm 2: mov $0,>subt0=%r14
+mov $0,%r14
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#13
+# asm 2: mov $38,>subt1=%r15
+mov $38,%r15
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#12,<subt1=int64#13
+# asm 2: cmovae <subt0=%r14,<subt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? a0 -= subt1
+# asm 1: sub <subt1=int64#13,<a0=int64#3
+# asm 2: sub <subt1=%r15,<a0=%rdx
+sub %r15,%rdx
+
+# qhasm: carry? a1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a1=int64#5
+# asm 2: sbb <subt0=%r14,<a1=%r8
+sbb %r14,%r8
+
+# qhasm: carry? a2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a2=int64#6
+# asm 2: sbb <subt0=%r14,<a2=%r9
+sbb %r14,%r9
+
+# qhasm: carry? a3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a3=int64#7
+# asm 2: sbb <subt0=%r14,<a3=%rax
+sbb %r14,%rax
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#13,<subt0=int64#12
+# asm 2: cmovc <subt1=%r15,<subt0=%r14
+cmovc %r15,%r14
+
+# qhasm: a0 -= subt0
+# asm 1: sub <subt0=int64#12,<a0=int64#3
+# asm 2: sub <subt0=%r14,<a0=%rdx
+sub %r14,%rdx
+
+# qhasm: carry? b0 += *(uint64 *)(pp + 0)
+# asm 1: addq 0(<pp=int64#2),<b0=int64#8
+# asm 2: addq 0(<pp=%rsi),<b0=%r10
+addq 0(%rsi),%r10
+
+# qhasm: carry? b1 += *(uint64 *)(pp + 8) + carry
+# asm 1: adcq 8(<pp=int64#2),<b1=int64#9
+# asm 2: adcq 8(<pp=%rsi),<b1=%r11
+adcq 8(%rsi),%r11
+
+# qhasm: carry? b2 += *(uint64 *)(pp + 16) + carry
+# asm 1: adcq 16(<pp=int64#2),<b2=int64#10
+# asm 2: adcq 16(<pp=%rsi),<b2=%r12
+adcq 16(%rsi),%r12
+
+# qhasm: carry? b3 += *(uint64 *)(pp + 24) + carry
+# asm 1: adcq 24(<pp=int64#2),<b3=int64#11
+# asm 2: adcq 24(<pp=%rsi),<b3=%r13
+adcq 24(%rsi),%r13
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#12
+# asm 2: mov $0,>addt0=%r14
+mov $0,%r14
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#13
+# asm 2: mov $38,>addt1=%r15
+mov $38,%r15
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#12,<addt1=int64#13
+# asm 2: cmovae <addt0=%r14,<addt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? b0 += addt1
+# asm 1: add <addt1=int64#13,<b0=int64#8
+# asm 2: add <addt1=%r15,<b0=%r10
+add %r15,%r10
+
+# qhasm: carry? b1 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b1=int64#9
+# asm 2: adc <addt0=%r14,<b1=%r11
+adc %r14,%r11
+
+# qhasm: carry? b2 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b2=int64#10
+# asm 2: adc <addt0=%r14,<b2=%r12
+adc %r14,%r12
+
+# qhasm: carry? b3 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b3=int64#11
+# asm 2: adc <addt0=%r14,<b3=%r13
+adc %r14,%r13
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#13,<addt0=int64#12
+# asm 2: cmovc <addt1=%r15,<addt0=%r14
+cmovc %r15,%r14
+
+# qhasm: b0 += addt0
+# asm 1: add <addt0=int64#12,<b0=int64#8
+# asm 2: add <addt0=%r14,<b0=%r10
+add %r14,%r10
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#3,>a0_stack=stack64#8
+# asm 2: movq <a0=%rdx,>a0_stack=56(%rsp)
+movq %rdx,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#5,>a1_stack=stack64#9
+# asm 2: movq <a1=%r8,>a1_stack=64(%rsp)
+movq %r8,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#6,>a2_stack=stack64#10
+# asm 2: movq <a2=%r9,>a2_stack=72(%rsp)
+movq %r9,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#7,>a3_stack=stack64#11
+# asm 2: movq <a3=%rax,>a3_stack=80(%rsp)
+movq %rax,80(%rsp)
+
+# qhasm: b0_stack = b0
+# asm 1: movq <b0=int64#8,>b0_stack=stack64#12
+# asm 2: movq <b0=%r10,>b0_stack=88(%rsp)
+movq %r10,88(%rsp)
+
+# qhasm: b1_stack = b1
+# asm 1: movq <b1=int64#9,>b1_stack=stack64#13
+# asm 2: movq <b1=%r11,>b1_stack=96(%rsp)
+movq %r11,96(%rsp)
+
+# qhasm: b2_stack = b2
+# asm 1: movq <b2=int64#10,>b2_stack=stack64#14
+# asm 2: movq <b2=%r12,>b2_stack=104(%rsp)
+movq %r12,104(%rsp)
+
+# qhasm: b3_stack = b3
+# asm 1: movq <b3=int64#11,>b3_stack=stack64#15
+# asm 2: movq <b3=%r13,>b3_stack=112(%rsp)
+movq %r13,112(%rsp)
+
+# qhasm: t10 = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>t10=int64#3
+# asm 2: movq 32(<qp=%rcx),>t10=%rdx
+movq 32(%rcx),%rdx
+
+# qhasm: t11 = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>t11=int64#5
+# asm 2: movq 40(<qp=%rcx),>t11=%r8
+movq 40(%rcx),%r8
+
+# qhasm: t12 = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>t12=int64#6
+# asm 2: movq 48(<qp=%rcx),>t12=%r9
+movq 48(%rcx),%r9
+
+# qhasm: t13 = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>t13=int64#7
+# asm 2: movq 56(<qp=%rcx),>t13=%rax
+movq 56(%rcx),%rax
+
+# qhasm: t20 = t10
+# asm 1: mov <t10=int64#3,>t20=int64#8
+# asm 2: mov <t10=%rdx,>t20=%r10
+mov %rdx,%r10
+
+# qhasm: t21 = t11
+# asm 1: mov <t11=int64#5,>t21=int64#9
+# asm 2: mov <t11=%r8,>t21=%r11
+mov %r8,%r11
+
+# qhasm: t22 = t12
+# asm 1: mov <t12=int64#6,>t22=int64#10
+# asm 2: mov <t12=%r9,>t22=%r12
+mov %r9,%r12
+
+# qhasm: t23 = t13
+# asm 1: mov <t13=int64#7,>t23=int64#11
+# asm 2: mov <t13=%rax,>t23=%r13
+mov %rax,%r13
+
+# qhasm: carry? t10 -= *(uint64 *) (qp + 0)
+# asm 1: subq 0(<qp=int64#4),<t10=int64#3
+# asm 2: subq 0(<qp=%rcx),<t10=%rdx
+subq 0(%rcx),%rdx
+
+# qhasm: carry? t11 -= *(uint64 *) (qp + 8) - carry
+# asm 1: sbbq 8(<qp=int64#4),<t11=int64#5
+# asm 2: sbbq 8(<qp=%rcx),<t11=%r8
+sbbq 8(%rcx),%r8
+
+# qhasm: carry? t12 -= *(uint64 *) (qp + 16) - carry
+# asm 1: sbbq 16(<qp=int64#4),<t12=int64#6
+# asm 2: sbbq 16(<qp=%rcx),<t12=%r9
+sbbq 16(%rcx),%r9
+
+# qhasm: carry? t13 -= *(uint64 *) (qp + 24) - carry
+# asm 1: sbbq 24(<qp=int64#4),<t13=int64#7
+# asm 2: sbbq 24(<qp=%rcx),<t13=%rax
+sbbq 24(%rcx),%rax
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#12
+# asm 2: mov $0,>subt0=%r14
+mov $0,%r14
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#13
+# asm 2: mov $38,>subt1=%r15
+mov $38,%r15
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#12,<subt1=int64#13
+# asm 2: cmovae <subt0=%r14,<subt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? t10 -= subt1
+# asm 1: sub <subt1=int64#13,<t10=int64#3
+# asm 2: sub <subt1=%r15,<t10=%rdx
+sub %r15,%rdx
+
+# qhasm: carry? t11 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<t11=int64#5
+# asm 2: sbb <subt0=%r14,<t11=%r8
+sbb %r14,%r8
+
+# qhasm: carry? t12 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<t12=int64#6
+# asm 2: sbb <subt0=%r14,<t12=%r9
+sbb %r14,%r9
+
+# qhasm: carry? t13 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<t13=int64#7
+# asm 2: sbb <subt0=%r14,<t13=%rax
+sbb %r14,%rax
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#13,<subt0=int64#12
+# asm 2: cmovc <subt1=%r15,<subt0=%r14
+cmovc %r15,%r14
+
+# qhasm: t10 -= subt0
+# asm 1: sub <subt0=int64#12,<t10=int64#3
+# asm 2: sub <subt0=%r14,<t10=%rdx
+sub %r14,%rdx
+
+# qhasm: carry? t20 += *(uint64 *) (qp + 0)
+# asm 1: addq 0(<qp=int64#4),<t20=int64#8
+# asm 2: addq 0(<qp=%rcx),<t20=%r10
+addq 0(%rcx),%r10
+
+# qhasm: carry? t21 += *(uint64 *) (qp + 8) + carry
+# asm 1: adcq 8(<qp=int64#4),<t21=int64#9
+# asm 2: adcq 8(<qp=%rcx),<t21=%r11
+adcq 8(%rcx),%r11
+
+# qhasm: carry? t22 += *(uint64 *) (qp + 16) + carry
+# asm 1: adcq 16(<qp=int64#4),<t22=int64#10
+# asm 2: adcq 16(<qp=%rcx),<t22=%r12
+adcq 16(%rcx),%r12
+
+# qhasm: carry? t23 += *(uint64 *) (qp + 24) + carry
+# asm 1: adcq 24(<qp=int64#4),<t23=int64#11
+# asm 2: adcq 24(<qp=%rcx),<t23=%r13
+adcq 24(%rcx),%r13
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#12
+# asm 2: mov $0,>addt0=%r14
+mov $0,%r14
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#13
+# asm 2: mov $38,>addt1=%r15
+mov $38,%r15
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#12,<addt1=int64#13
+# asm 2: cmovae <addt0=%r14,<addt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? t20 += addt1
+# asm 1: add <addt1=int64#13,<t20=int64#8
+# asm 2: add <addt1=%r15,<t20=%r10
+add %r15,%r10
+
+# qhasm: carry? t21 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<t21=int64#9
+# asm 2: adc <addt0=%r14,<t21=%r11
+adc %r14,%r11
+
+# qhasm: carry? t22 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<t22=int64#10
+# asm 2: adc <addt0=%r14,<t22=%r12
+adc %r14,%r12
+
+# qhasm: carry? t23 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<t23=int64#11
+# asm 2: adc <addt0=%r14,<t23=%r13
+adc %r14,%r13
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#13,<addt0=int64#12
+# asm 2: cmovc <addt1=%r15,<addt0=%r14
+cmovc %r15,%r14
+
+# qhasm: t20 += addt0
+# asm 1: add <addt0=int64#12,<t20=int64#8
+# asm 2: add <addt0=%r14,<t20=%r10
+add %r14,%r10
+
+# qhasm: t10_stack = t10
+# asm 1: movq <t10=int64#3,>t10_stack=stack64#16
+# asm 2: movq <t10=%rdx,>t10_stack=120(%rsp)
+movq %rdx,120(%rsp)
+
+# qhasm: t11_stack = t11
+# asm 1: movq <t11=int64#5,>t11_stack=stack64#17
+# asm 2: movq <t11=%r8,>t11_stack=128(%rsp)
+movq %r8,128(%rsp)
+
+# qhasm: t12_stack = t12
+# asm 1: movq <t12=int64#6,>t12_stack=stack64#18
+# asm 2: movq <t12=%r9,>t12_stack=136(%rsp)
+movq %r9,136(%rsp)
+
+# qhasm: t13_stack = t13
+# asm 1: movq <t13=int64#7,>t13_stack=stack64#19
+# asm 2: movq <t13=%rax,>t13_stack=144(%rsp)
+movq %rax,144(%rsp)
+
+# qhasm: t20_stack = t20
+# asm 1: movq <t20=int64#8,>t20_stack=stack64#20
+# asm 2: movq <t20=%r10,>t20_stack=152(%rsp)
+movq %r10,152(%rsp)
+
+# qhasm: t21_stack = t21
+# asm 1: movq <t21=int64#9,>t21_stack=stack64#21
+# asm 2: movq <t21=%r11,>t21_stack=160(%rsp)
+movq %r11,160(%rsp)
+
+# qhasm: t22_stack = t22
+# asm 1: movq <t22=int64#10,>t22_stack=stack64#22
+# asm 2: movq <t22=%r12,>t22_stack=168(%rsp)
+movq %r12,168(%rsp)
+
+# qhasm: t23_stack = t23
+# asm 1: movq <t23=int64#11,>t23_stack=stack64#23
+# asm 2: movq <t23=%r13,>t23_stack=176(%rsp)
+movq %r13,176(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = a0_stack
+# asm 1: movq <a0_stack=stack64#8,>mulx0=int64#10
+# asm 2: movq <a0_stack=56(%rsp),>mulx0=%r12
+movq 56(%rsp),%r12
+
+# qhasm: mulrax = t10_stack
+# asm 1: movq <t10_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <t10_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: a0 = mulrax
+# asm 1: mov <mulrax=int64#7,>a0=int64#11
+# asm 2: mov <mulrax=%rax,>a0=%r13
+mov %rax,%r13
+
+# qhasm: a1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>a1=int64#12
+# asm 2: mov <mulrdx=%rdx,>a1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = t11_stack
+# asm 1: movq <t11_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <t11_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#12
+# asm 2: add <mulrax=%rax,<a1=%r14
+add %rax,%r14
+
+# qhasm: a2 = 0
+# asm 1: mov $0,>a2=int64#13
+# asm 2: mov $0,>a2=%r15
+mov $0,%r15
+
+# qhasm: a2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a2=int64#13
+# asm 2: adc <mulrdx=%rdx,<a2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = t12_stack
+# asm 1: movq <t12_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <t12_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: a3 = 0
+# asm 1: mov $0,>a3=int64#14
+# asm 2: mov $0,>a3=%rbx
+mov $0,%rbx
+
+# qhasm: a3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a3=int64#14
+# asm 2: adc <mulrdx=%rdx,<a3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = t13_stack
+# asm 1: movq <t13_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <t13_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = a1_stack
+# asm 1: movq <a1_stack=stack64#9,>mulx1=int64#10
+# asm 2: movq <a1_stack=64(%rsp),>mulx1=%r12
+movq 64(%rsp),%r12
+
+# qhasm: mulrax = t10_stack
+# asm 1: movq <t10_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <t10_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#12
+# asm 2: add <mulrax=%rax,<a1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t11_stack
+# asm 1: movq <t11_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <t11_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a2 += mulc
+# asm 1: add <mulc=int64#15,<a2=int64#13
+# asm 2: add <mulc=%rbp,<a2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t12_stack
+# asm 1: movq <t12_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <t12_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#15,<a3=int64#14
+# asm 2: add <mulc=%rbp,<a3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t13_stack
+# asm 1: movq <t13_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <t13_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = a2_stack
+# asm 1: movq <a2_stack=stack64#10,>mulx2=int64#10
+# asm 2: movq <a2_stack=72(%rsp),>mulx2=%r12
+movq 72(%rsp),%r12
+
+# qhasm: mulrax = t10_stack
+# asm 1: movq <t10_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <t10_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t11_stack
+# asm 1: movq <t11_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <t11_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#15,<a3=int64#14
+# asm 2: add <mulc=%rbp,<a3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t12_stack
+# asm 1: movq <t12_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <t12_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t13_stack
+# asm 1: movq <t13_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <t13_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = a3_stack
+# asm 1: movq <a3_stack=stack64#11,>mulx3=int64#10
+# asm 2: movq <a3_stack=80(%rsp),>mulx3=%r12
+movq 80(%rsp),%r12
+
+# qhasm: mulrax = t10_stack
+# asm 1: movq <t10_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <t10_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t11_stack
+# asm 1: movq <t11_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <t11_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t12_stack
+# asm 1: movq <t12_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <t12_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t13_stack
+# asm 1: movq <t13_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <t13_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? a0 += mulr4
+# asm 1: add <mulr4=int64#5,<a0=int64#11
+# asm 2: add <mulr4=%r8,<a0=%r13
+add %r8,%r13
+
+# qhasm: carry? a1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<a1=int64#12
+# asm 2: adc <mulr5=%r9,<a1=%r14
+adc %r9,%r14
+
+# qhasm: carry? a2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<a2=int64#13
+# asm 2: adc <mulr6=%r10,<a2=%r15
+adc %r10,%r15
+
+# qhasm: carry? a3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<a3=int64#14
+# asm 2: adc <mulr7=%r11,<a3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? a0 += mulr8
+# asm 1: add <mulr8=int64#5,<a0=int64#11
+# asm 2: add <mulr8=%r8,<a0=%r13
+add %r8,%r13
+
+# qhasm: carry? a1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a1=int64#12
+# asm 2: adc <mulzero=%rdx,<a1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? a2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a2=int64#13
+# asm 2: adc <mulzero=%rdx,<a2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? a3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a3=int64#14
+# asm 2: adc <mulzero=%rdx,<a3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: a0 += mulzero
+# asm 1: add <mulzero=int64#3,<a0=int64#11
+# asm 2: add <mulzero=%rdx,<a0=%r13
+add %rdx,%r13
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#11,>a0_stack=stack64#8
+# asm 2: movq <a0=%r13,>a0_stack=56(%rsp)
+movq %r13,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#12,>a1_stack=stack64#9
+# asm 2: movq <a1=%r14,>a1_stack=64(%rsp)
+movq %r14,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#13,>a2_stack=stack64#10
+# asm 2: movq <a2=%r15,>a2_stack=72(%rsp)
+movq %r15,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#14,>a3_stack=stack64#11
+# asm 2: movq <a3=%rbx,>a3_stack=80(%rsp)
+movq %rbx,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = b0_stack
+# asm 1: movq <b0_stack=stack64#12,>mulx0=int64#10
+# asm 2: movq <b0_stack=88(%rsp),>mulx0=%r12
+movq 88(%rsp),%r12
+
+# qhasm: mulrax = t20_stack
+# asm 1: movq <t20_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <t20_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: rx0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rx0=int64#11
+# asm 2: mov <mulrax=%rax,>rx0=%r13
+mov %rax,%r13
+
+# qhasm: rx1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rx1=int64#12
+# asm 2: mov <mulrdx=%rdx,>rx1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = t21_stack
+# asm 1: movq <t21_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <t21_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#12
+# asm 2: add <mulrax=%rax,<rx1=%r14
+add %rax,%r14
+
+# qhasm: rx2 = 0
+# asm 1: mov $0,>rx2=int64#13
+# asm 2: mov $0,>rx2=%r15
+mov $0,%r15
+
+# qhasm: rx2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx2=int64#13
+# asm 2: adc <mulrdx=%rdx,<rx2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = t22_stack
+# asm 1: movq <t22_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <t22_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#13
+# asm 2: add <mulrax=%rax,<rx2=%r15
+add %rax,%r15
+
+# qhasm: rx3 = 0
+# asm 1: mov $0,>rx3=int64#14
+# asm 2: mov $0,>rx3=%rbx
+mov $0,%rbx
+
+# qhasm: rx3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx3=int64#14
+# asm 2: adc <mulrdx=%rdx,<rx3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = t23_stack
+# asm 1: movq <t23_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <t23_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = b1_stack
+# asm 1: movq <b1_stack=stack64#13,>mulx1=int64#10
+# asm 2: movq <b1_stack=96(%rsp),>mulx1=%r12
+movq 96(%rsp),%r12
+
+# qhasm: mulrax = t20_stack
+# asm 1: movq <t20_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <t20_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#12
+# asm 2: add <mulrax=%rax,<rx1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t21_stack
+# asm 1: movq <t21_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <t21_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#13
+# asm 2: add <mulrax=%rax,<rx2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx2 += mulc
+# asm 1: add <mulc=int64#15,<rx2=int64#13
+# asm 2: add <mulc=%rbp,<rx2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t22_stack
+# asm 1: movq <t22_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <t22_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#15,<rx3=int64#14
+# asm 2: add <mulc=%rbp,<rx3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t23_stack
+# asm 1: movq <t23_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <t23_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = b2_stack
+# asm 1: movq <b2_stack=stack64#14,>mulx2=int64#10
+# asm 2: movq <b2_stack=104(%rsp),>mulx2=%r12
+movq 104(%rsp),%r12
+
+# qhasm: mulrax = t20_stack
+# asm 1: movq <t20_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <t20_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#13
+# asm 2: add <mulrax=%rax,<rx2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t21_stack
+# asm 1: movq <t21_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <t21_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#15,<rx3=int64#14
+# asm 2: add <mulc=%rbp,<rx3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t22_stack
+# asm 1: movq <t22_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <t22_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t23_stack
+# asm 1: movq <t23_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <t23_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = b3_stack
+# asm 1: movq <b3_stack=stack64#15,>mulx3=int64#10
+# asm 2: movq <b3_stack=112(%rsp),>mulx3=%r12
+movq 112(%rsp),%r12
+
+# qhasm: mulrax = t20_stack
+# asm 1: movq <t20_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <t20_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t21_stack
+# asm 1: movq <t21_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <t21_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t22_stack
+# asm 1: movq <t22_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <t22_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = t23_stack
+# asm 1: movq <t23_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <t23_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rx0 += mulr4
+# asm 1: add <mulr4=int64#5,<rx0=int64#11
+# asm 2: add <mulr4=%r8,<rx0=%r13
+add %r8,%r13
+
+# qhasm: carry? rx1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<rx1=int64#12
+# asm 2: adc <mulr5=%r9,<rx1=%r14
+adc %r9,%r14
+
+# qhasm: carry? rx2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<rx2=int64#13
+# asm 2: adc <mulr6=%r10,<rx2=%r15
+adc %r10,%r15
+
+# qhasm: carry? rx3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<rx3=int64#14
+# asm 2: adc <mulr7=%r11,<rx3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? rx0 += mulr8
+# asm 1: add <mulr8=int64#5,<rx0=int64#11
+# asm 2: add <mulr8=%r8,<rx0=%r13
+add %r8,%r13
+
+# qhasm: carry? rx1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx1=int64#12
+# asm 2: adc <mulzero=%rdx,<rx1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? rx2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx2=int64#13
+# asm 2: adc <mulzero=%rdx,<rx2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? rx3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx3=int64#14
+# asm 2: adc <mulzero=%rdx,<rx3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: rx0 += mulzero
+# asm 1: add <mulzero=int64#3,<rx0=int64#11
+# asm 2: add <mulzero=%rdx,<rx0=%r13
+add %rdx,%r13
+
+# qhasm: ry0 = rx0
+# asm 1: mov <rx0=int64#11,>ry0=int64#3
+# asm 2: mov <rx0=%r13,>ry0=%rdx
+mov %r13,%rdx
+
+# qhasm: ry1 = rx1
+# asm 1: mov <rx1=int64#12,>ry1=int64#5
+# asm 2: mov <rx1=%r14,>ry1=%r8
+mov %r14,%r8
+
+# qhasm: ry2 = rx2
+# asm 1: mov <rx2=int64#13,>ry2=int64#6
+# asm 2: mov <rx2=%r15,>ry2=%r9
+mov %r15,%r9
+
+# qhasm: ry3 = rx3
+# asm 1: mov <rx3=int64#14,>ry3=int64#7
+# asm 2: mov <rx3=%rbx,>ry3=%rax
+mov %rbx,%rax
+
+# qhasm: carry? ry0 += a0_stack
+# asm 1: addq <a0_stack=stack64#8,<ry0=int64#3
+# asm 2: addq <a0_stack=56(%rsp),<ry0=%rdx
+addq 56(%rsp),%rdx
+
+# qhasm: carry? ry1 += a1_stack + carry
+# asm 1: adcq <a1_stack=stack64#9,<ry1=int64#5
+# asm 2: adcq <a1_stack=64(%rsp),<ry1=%r8
+adcq 64(%rsp),%r8
+
+# qhasm: carry? ry2 += a2_stack + carry
+# asm 1: adcq <a2_stack=stack64#10,<ry2=int64#6
+# asm 2: adcq <a2_stack=72(%rsp),<ry2=%r9
+adcq 72(%rsp),%r9
+
+# qhasm: carry? ry3 += a3_stack + carry
+# asm 1: adcq <a3_stack=stack64#11,<ry3=int64#7
+# asm 2: adcq <a3_stack=80(%rsp),<ry3=%rax
+adcq 80(%rsp),%rax
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#8
+# asm 2: mov $0,>addt0=%r10
+mov $0,%r10
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#9
+# asm 2: mov $38,>addt1=%r11
+mov $38,%r11
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#8,<addt1=int64#9
+# asm 2: cmovae <addt0=%r10,<addt1=%r11
+cmovae %r10,%r11
+
+# qhasm: carry? ry0 += addt1
+# asm 1: add <addt1=int64#9,<ry0=int64#3
+# asm 2: add <addt1=%r11,<ry0=%rdx
+add %r11,%rdx
+
+# qhasm: carry? ry1 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<ry1=int64#5
+# asm 2: adc <addt0=%r10,<ry1=%r8
+adc %r10,%r8
+
+# qhasm: carry? ry2 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<ry2=int64#6
+# asm 2: adc <addt0=%r10,<ry2=%r9
+adc %r10,%r9
+
+# qhasm: carry? ry3 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<ry3=int64#7
+# asm 2: adc <addt0=%r10,<ry3=%rax
+adc %r10,%rax
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#9,<addt0=int64#8
+# asm 2: cmovc <addt1=%r11,<addt0=%r10
+cmovc %r11,%r10
+
+# qhasm: ry0 += addt0
+# asm 1: add <addt0=int64#8,<ry0=int64#3
+# asm 2: add <addt0=%r10,<ry0=%rdx
+add %r10,%rdx
+
+# qhasm: carry? rx0 -= a0_stack
+# asm 1: subq <a0_stack=stack64#8,<rx0=int64#11
+# asm 2: subq <a0_stack=56(%rsp),<rx0=%r13
+subq 56(%rsp),%r13
+
+# qhasm: carry? rx1 -= a1_stack - carry
+# asm 1: sbbq <a1_stack=stack64#9,<rx1=int64#12
+# asm 2: sbbq <a1_stack=64(%rsp),<rx1=%r14
+sbbq 64(%rsp),%r14
+
+# qhasm: carry? rx2 -= a2_stack - carry
+# asm 1: sbbq <a2_stack=stack64#10,<rx2=int64#13
+# asm 2: sbbq <a2_stack=72(%rsp),<rx2=%r15
+sbbq 72(%rsp),%r15
+
+# qhasm: carry? rx3 -= a3_stack - carry
+# asm 1: sbbq <a3_stack=stack64#11,<rx3=int64#14
+# asm 2: sbbq <a3_stack=80(%rsp),<rx3=%rbx
+sbbq 80(%rsp),%rbx
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#8
+# asm 2: mov $0,>subt0=%r10
+mov $0,%r10
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#9
+# asm 2: mov $38,>subt1=%r11
+mov $38,%r11
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#8,<subt1=int64#9
+# asm 2: cmovae <subt0=%r10,<subt1=%r11
+cmovae %r10,%r11
+
+# qhasm: carry? rx0 -= subt1
+# asm 1: sub <subt1=int64#9,<rx0=int64#11
+# asm 2: sub <subt1=%r11,<rx0=%r13
+sub %r11,%r13
+
+# qhasm: carry? rx1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<rx1=int64#12
+# asm 2: sbb <subt0=%r10,<rx1=%r14
+sbb %r10,%r14
+
+# qhasm: carry? rx2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<rx2=int64#13
+# asm 2: sbb <subt0=%r10,<rx2=%r15
+sbb %r10,%r15
+
+# qhasm: carry? rx3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<rx3=int64#14
+# asm 2: sbb <subt0=%r10,<rx3=%rbx
+sbb %r10,%rbx
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#9,<subt0=int64#8
+# asm 2: cmovc <subt1=%r11,<subt0=%r10
+cmovc %r11,%r10
+
+# qhasm: rx0 -= subt0
+# asm 1: sub <subt0=int64#8,<rx0=int64#11
+# asm 2: sub <subt0=%r10,<rx0=%r13
+sub %r10,%r13
+
+# qhasm: *(uint64 *) (rp + 0) = rx0
+# asm 1: movq <rx0=int64#11,0(<rp=int64#1)
+# asm 2: movq <rx0=%r13,0(<rp=%rdi)
+movq %r13,0(%rdi)
+
+# qhasm: *(uint64 *) (rp + 8) = rx1
+# asm 1: movq <rx1=int64#12,8(<rp=int64#1)
+# asm 2: movq <rx1=%r14,8(<rp=%rdi)
+movq %r14,8(%rdi)
+
+# qhasm: *(uint64 *) (rp + 16) = rx2
+# asm 1: movq <rx2=int64#13,16(<rp=int64#1)
+# asm 2: movq <rx2=%r15,16(<rp=%rdi)
+movq %r15,16(%rdi)
+
+# qhasm: *(uint64 *) (rp + 24) = rx3
+# asm 1: movq <rx3=int64#14,24(<rp=int64#1)
+# asm 2: movq <rx3=%rbx,24(<rp=%rdi)
+movq %rbx,24(%rdi)
+
+# qhasm: *(uint64 *) (rp + 64) = ry0
+# asm 1: movq <ry0=int64#3,64(<rp=int64#1)
+# asm 2: movq <ry0=%rdx,64(<rp=%rdi)
+movq %rdx,64(%rdi)
+
+# qhasm: *(uint64 *) (rp + 72) = ry1
+# asm 1: movq <ry1=int64#5,72(<rp=int64#1)
+# asm 2: movq <ry1=%r8,72(<rp=%rdi)
+movq %r8,72(%rdi)
+
+# qhasm: *(uint64 *) (rp + 80) = ry2
+# asm 1: movq <ry2=int64#6,80(<rp=int64#1)
+# asm 2: movq <ry2=%r9,80(<rp=%rdi)
+movq %r9,80(%rdi)
+
+# qhasm: *(uint64 *) (rp + 88) = ry3
+# asm 1: movq <ry3=int64#7,88(<rp=int64#1)
+# asm 2: movq <ry3=%rax,88(<rp=%rdi)
+movq %rax,88(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulx0=int64#10
+# asm 2: movq 96(<pp=%rsi),>mulx0=%r12
+movq 96(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: c0 = mulrax
+# asm 1: mov <mulrax=int64#7,>c0=int64#11
+# asm 2: mov <mulrax=%rax,>c0=%r13
+mov %rax,%r13
+
+# qhasm: c1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>c1=int64#12
+# asm 2: mov <mulrdx=%rdx,>c1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: c2 = 0
+# asm 1: mov $0,>c2=int64#13
+# asm 2: mov $0,>c2=%r15
+mov $0,%r15
+
+# qhasm: c2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c2=int64#13
+# asm 2: adc <mulrdx=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: c3 = 0
+# asm 1: mov $0,>c3=int64#14
+# asm 2: mov $0,>c3=%rbx
+mov $0,%rbx
+
+# qhasm: c3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c3=int64#14
+# asm 2: adc <mulrdx=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulx1=int64#10
+# asm 2: movq 104(<pp=%rsi),>mulx1=%r12
+movq 104(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c2 += mulc
+# asm 1: add <mulc=int64#15,<c2=int64#13
+# asm 2: add <mulc=%rbp,<c2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulx2=int64#10
+# asm 2: movq 112(<pp=%rsi),>mulx2=%r12
+movq 112(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulx3=int64#10
+# asm 2: movq 120(<pp=%rsi),>mulx3=%r12
+movq 120(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? c0 += mulr4
+# asm 1: add <mulr4=int64#5,<c0=int64#11
+# asm 2: add <mulr4=%r8,<c0=%r13
+add %r8,%r13
+
+# qhasm: carry? c1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<c1=int64#12
+# asm 2: adc <mulr5=%r9,<c1=%r14
+adc %r9,%r14
+
+# qhasm: carry? c2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<c2=int64#13
+# asm 2: adc <mulr6=%r10,<c2=%r15
+adc %r10,%r15
+
+# qhasm: carry? c3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<c3=int64#14
+# asm 2: adc <mulr7=%r11,<c3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? c0 += mulr8
+# asm 1: add <mulr8=int64#5,<c0=int64#11
+# asm 2: add <mulr8=%r8,<c0=%r13
+add %r8,%r13
+
+# qhasm: carry? c1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c1=int64#12
+# asm 2: adc <mulzero=%rdx,<c1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? c2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c2=int64#13
+# asm 2: adc <mulzero=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? c3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c3=int64#14
+# asm 2: adc <mulzero=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: c0 += mulzero
+# asm 1: add <mulzero=int64#3,<c0=int64#11
+# asm 2: add <mulzero=%rdx,<c0=%r13
+add %rdx,%r13
+
+# qhasm: c0_stack = c0
+# asm 1: movq <c0=int64#11,>c0_stack=stack64#8
+# asm 2: movq <c0=%r13,>c0_stack=56(%rsp)
+movq %r13,56(%rsp)
+
+# qhasm: c1_stack = c1
+# asm 1: movq <c1=int64#12,>c1_stack=stack64#9
+# asm 2: movq <c1=%r14,>c1_stack=64(%rsp)
+movq %r14,64(%rsp)
+
+# qhasm: c2_stack = c2
+# asm 1: movq <c2=int64#13,>c2_stack=stack64#10
+# asm 2: movq <c2=%r15,>c2_stack=72(%rsp)
+movq %r15,72(%rsp)
+
+# qhasm: c3_stack = c3
+# asm 1: movq <c3=int64#14,>c3_stack=stack64#11
+# asm 2: movq <c3=%rbx,>c3_stack=80(%rsp)
+movq %rbx,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = c0_stack
+# asm 1: movq <c0_stack=stack64#8,>mulx0=int64#10
+# asm 2: movq <c0_stack=56(%rsp),>mulx0=%r12
+movq 56(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: c0 = mulrax
+# asm 1: mov <mulrax=int64#7,>c0=int64#11
+# asm 2: mov <mulrax=%rax,>c0=%r13
+mov %rax,%r13
+
+# qhasm: c1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>c1=int64#12
+# asm 2: mov <mulrdx=%rdx,>c1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D1
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: c2 = 0
+# asm 1: mov $0,>c2=int64#13
+# asm 2: mov $0,>c2=%r15
+mov $0,%r15
+
+# qhasm: c2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c2=int64#13
+# asm 2: adc <mulrdx=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D2
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: c3 = 0
+# asm 1: mov $0,>c3=int64#14
+# asm 2: mov $0,>c3=%rbx
+mov $0,%rbx
+
+# qhasm: c3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c3=int64#14
+# asm 2: adc <mulrdx=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D3
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = c1_stack
+# asm 1: movq <c1_stack=stack64#9,>mulx1=int64#10
+# asm 2: movq <c1_stack=64(%rsp),>mulx1=%r12
+movq 64(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D1
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c2 += mulc
+# asm 1: add <mulc=int64#15,<c2=int64#13
+# asm 2: add <mulc=%rbp,<c2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D2
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D3
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = c2_stack
+# asm 1: movq <c2_stack=stack64#10,>mulx2=int64#10
+# asm 2: movq <c2_stack=72(%rsp),>mulx2=%r12
+movq 72(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D1
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D2
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D3
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = c3_stack
+# asm 1: movq <c3_stack=stack64#11,>mulx3=int64#10
+# asm 2: movq <c3_stack=80(%rsp),>mulx3=%r12
+movq 80(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D0
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D0,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D0(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D1
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D1,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D1(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D2
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D2,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D2(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)&crypto_sign_ed25519_amd64_64_EC2D3
+# asm 1: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=int64#7
+# asm 2: movq crypto_sign_ed25519_amd64_64_EC2D3,>mulrax=%rax
+movq crypto_sign_ed25519_amd64_64_EC2D3(%rip),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? c0 += mulr4
+# asm 1: add <mulr4=int64#5,<c0=int64#11
+# asm 2: add <mulr4=%r8,<c0=%r13
+add %r8,%r13
+
+# qhasm: carry? c1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<c1=int64#12
+# asm 2: adc <mulr5=%r9,<c1=%r14
+adc %r9,%r14
+
+# qhasm: carry? c2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<c2=int64#13
+# asm 2: adc <mulr6=%r10,<c2=%r15
+adc %r10,%r15
+
+# qhasm: carry? c3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<c3=int64#14
+# asm 2: adc <mulr7=%r11,<c3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? c0 += mulr8
+# asm 1: add <mulr8=int64#5,<c0=int64#11
+# asm 2: add <mulr8=%r8,<c0=%r13
+add %r8,%r13
+
+# qhasm: carry? c1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c1=int64#12
+# asm 2: adc <mulzero=%rdx,<c1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? c2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c2=int64#13
+# asm 2: adc <mulzero=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? c3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c3=int64#14
+# asm 2: adc <mulzero=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: c0 += mulzero
+# asm 1: add <mulzero=int64#3,<c0=int64#11
+# asm 2: add <mulzero=%rdx,<c0=%r13
+add %rdx,%r13
+
+# qhasm: c0_stack = c0
+# asm 1: movq <c0=int64#11,>c0_stack=stack64#8
+# asm 2: movq <c0=%r13,>c0_stack=56(%rsp)
+movq %r13,56(%rsp)
+
+# qhasm: c1_stack = c1
+# asm 1: movq <c1=int64#12,>c1_stack=stack64#9
+# asm 2: movq <c1=%r14,>c1_stack=64(%rsp)
+movq %r14,64(%rsp)
+
+# qhasm: c2_stack = c2
+# asm 1: movq <c2=int64#13,>c2_stack=stack64#10
+# asm 2: movq <c2=%r15,>c2_stack=72(%rsp)
+movq %r15,72(%rsp)
+
+# qhasm: c3_stack = c3
+# asm 1: movq <c3=int64#14,>c3_stack=stack64#11
+# asm 2: movq <c3=%rbx,>c3_stack=80(%rsp)
+movq %rbx,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulx0=int64#10
+# asm 2: movq 64(<pp=%rsi),>mulx0=%r12
+movq 64(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: rt0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rt0=int64#11
+# asm 2: mov <mulrax=%rax,>rt0=%r13
+mov %rax,%r13
+
+# qhasm: rt1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rt1=int64#12
+# asm 2: mov <mulrdx=%rdx,>rt1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#12
+# asm 2: add <mulrax=%rax,<rt1=%r14
+add %rax,%r14
+
+# qhasm: rt2 = 0
+# asm 1: mov $0,>rt2=int64#13
+# asm 2: mov $0,>rt2=%r15
+mov $0,%r15
+
+# qhasm: rt2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt2=int64#13
+# asm 2: adc <mulrdx=%rdx,<rt2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#13
+# asm 2: add <mulrax=%rax,<rt2=%r15
+add %rax,%r15
+
+# qhasm: rt3 = 0
+# asm 1: mov $0,>rt3=int64#14
+# asm 2: mov $0,>rt3=%rbx
+mov $0,%rbx
+
+# qhasm: rt3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt3=int64#14
+# asm 2: adc <mulrdx=%rdx,<rt3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulx1=int64#10
+# asm 2: movq 72(<pp=%rsi),>mulx1=%r12
+movq 72(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#12
+# asm 2: add <mulrax=%rax,<rt1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#13
+# asm 2: add <mulrax=%rax,<rt2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt2 += mulc
+# asm 1: add <mulc=int64#15,<rt2=int64#13
+# asm 2: add <mulc=%rbp,<rt2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#15,<rt3=int64#14
+# asm 2: add <mulc=%rbp,<rt3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulx2=int64#10
+# asm 2: movq 80(<pp=%rsi),>mulx2=%r12
+movq 80(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#13
+# asm 2: add <mulrax=%rax,<rt2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#15,<rt3=int64#14
+# asm 2: add <mulc=%rbp,<rt3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulx3=int64#2
+# asm 2: movq 88(<pp=%rsi),>mulx3=%rsi
+movq 88(%rsi),%rsi
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#10,<mulr4=int64#5
+# asm 2: add <mulc=%r12,<mulr4=%r8
+add %r12,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#10,<mulr5=int64#6
+# asm 2: add <mulc=%r12,<mulr5=%r9
+add %r12,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#10,<mulr6=int64#8
+# asm 2: add <mulc=%r12,<mulr6=%r10
+add %r12,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rt0 += mulr4
+# asm 1: add <mulr4=int64#2,<rt0=int64#11
+# asm 2: add <mulr4=%rsi,<rt0=%r13
+add %rsi,%r13
+
+# qhasm: carry? rt1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rt1=int64#12
+# asm 2: adc <mulr5=%rcx,<rt1=%r14
+adc %rcx,%r14
+
+# qhasm: carry? rt2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rt2=int64#13
+# asm 2: adc <mulr6=%r8,<rt2=%r15
+adc %r8,%r15
+
+# qhasm: carry? rt3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rt3=int64#14
+# asm 2: adc <mulr7=%r9,<rt3=%rbx
+adc %r9,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rt0 += mulr8
+# asm 1: add <mulr8=int64#3,<rt0=int64#11
+# asm 2: add <mulr8=%rdx,<rt0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rt1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt1=int64#12
+# asm 2: adc <mulzero=%rsi,<rt1=%r14
+adc %rsi,%r14
+
+# qhasm: carry? rt2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt2=int64#13
+# asm 2: adc <mulzero=%rsi,<rt2=%r15
+adc %rsi,%r15
+
+# qhasm: carry? rt3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt3=int64#14
+# asm 2: adc <mulzero=%rsi,<rt3=%rbx
+adc %rsi,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rt0 += mulzero
+# asm 1: add <mulzero=int64#2,<rt0=int64#11
+# asm 2: add <mulzero=%rsi,<rt0=%r13
+add %rsi,%r13
+
+# qhasm: carry? rt0 += rt0
+# asm 1: add <rt0=int64#11,<rt0=int64#11
+# asm 2: add <rt0=%r13,<rt0=%r13
+add %r13,%r13
+
+# qhasm: carry? rt1 += rt1 + carry
+# asm 1: adc <rt1=int64#12,<rt1=int64#12
+# asm 2: adc <rt1=%r14,<rt1=%r14
+adc %r14,%r14
+
+# qhasm: carry? rt2 += rt2 + carry
+# asm 1: adc <rt2=int64#13,<rt2=int64#13
+# asm 2: adc <rt2=%r15,<rt2=%r15
+adc %r15,%r15
+
+# qhasm: carry? rt3 += rt3 + carry
+# asm 1: adc <rt3=int64#14,<rt3=int64#14
+# asm 2: adc <rt3=%rbx,<rt3=%rbx
+adc %rbx,%rbx
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#2
+# asm 2: mov $0,>addt0=%rsi
+mov $0,%rsi
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#3
+# asm 2: mov $38,>addt1=%rdx
+mov $38,%rdx
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#2,<addt1=int64#3
+# asm 2: cmovae <addt0=%rsi,<addt1=%rdx
+cmovae %rsi,%rdx
+
+# qhasm: carry? rt0 += addt1
+# asm 1: add <addt1=int64#3,<rt0=int64#11
+# asm 2: add <addt1=%rdx,<rt0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rt1 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rt1=int64#12
+# asm 2: adc <addt0=%rsi,<rt1=%r14
+adc %rsi,%r14
+
+# qhasm: carry? rt2 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rt2=int64#13
+# asm 2: adc <addt0=%rsi,<rt2=%r15
+adc %rsi,%r15
+
+# qhasm: carry? rt3 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rt3=int64#14
+# asm 2: adc <addt0=%rsi,<rt3=%rbx
+adc %rsi,%rbx
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#3,<addt0=int64#2
+# asm 2: cmovc <addt1=%rdx,<addt0=%rsi
+cmovc %rdx,%rsi
+
+# qhasm: rt0 += addt0
+# asm 1: add <addt0=int64#2,<rt0=int64#11
+# asm 2: add <addt0=%rsi,<rt0=%r13
+add %rsi,%r13
+
+# qhasm: rz0 = rt0
+# asm 1: mov <rt0=int64#11,>rz0=int64#2
+# asm 2: mov <rt0=%r13,>rz0=%rsi
+mov %r13,%rsi
+
+# qhasm: rz1 = rt1
+# asm 1: mov <rt1=int64#12,>rz1=int64#3
+# asm 2: mov <rt1=%r14,>rz1=%rdx
+mov %r14,%rdx
+
+# qhasm: rz2 = rt2
+# asm 1: mov <rt2=int64#13,>rz2=int64#4
+# asm 2: mov <rt2=%r15,>rz2=%rcx
+mov %r15,%rcx
+
+# qhasm: rz3 = rt3
+# asm 1: mov <rt3=int64#14,>rz3=int64#5
+# asm 2: mov <rt3=%rbx,>rz3=%r8
+mov %rbx,%r8
+
+# qhasm: carry? rz0 += c0_stack
+# asm 1: addq <c0_stack=stack64#8,<rz0=int64#2
+# asm 2: addq <c0_stack=56(%rsp),<rz0=%rsi
+addq 56(%rsp),%rsi
+
+# qhasm: carry? rz1 += c1_stack + carry
+# asm 1: adcq <c1_stack=stack64#9,<rz1=int64#3
+# asm 2: adcq <c1_stack=64(%rsp),<rz1=%rdx
+adcq 64(%rsp),%rdx
+
+# qhasm: carry? rz2 += c2_stack + carry
+# asm 1: adcq <c2_stack=stack64#10,<rz2=int64#4
+# asm 2: adcq <c2_stack=72(%rsp),<rz2=%rcx
+adcq 72(%rsp),%rcx
+
+# qhasm: carry? rz3 += c3_stack + carry
+# asm 1: adcq <c3_stack=stack64#11,<rz3=int64#5
+# asm 2: adcq <c3_stack=80(%rsp),<rz3=%r8
+adcq 80(%rsp),%r8
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#6
+# asm 2: mov $0,>addt0=%r9
+mov $0,%r9
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#7
+# asm 2: mov $38,>addt1=%rax
+mov $38,%rax
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#6,<addt1=int64#7
+# asm 2: cmovae <addt0=%r9,<addt1=%rax
+cmovae %r9,%rax
+
+# qhasm: carry? rz0 += addt1
+# asm 1: add <addt1=int64#7,<rz0=int64#2
+# asm 2: add <addt1=%rax,<rz0=%rsi
+add %rax,%rsi
+
+# qhasm: carry? rz1 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<rz1=int64#3
+# asm 2: adc <addt0=%r9,<rz1=%rdx
+adc %r9,%rdx
+
+# qhasm: carry? rz2 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<rz2=int64#4
+# asm 2: adc <addt0=%r9,<rz2=%rcx
+adc %r9,%rcx
+
+# qhasm: carry? rz3 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<rz3=int64#5
+# asm 2: adc <addt0=%r9,<rz3=%r8
+adc %r9,%r8
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#7,<addt0=int64#6
+# asm 2: cmovc <addt1=%rax,<addt0=%r9
+cmovc %rax,%r9
+
+# qhasm: rz0 += addt0
+# asm 1: add <addt0=int64#6,<rz0=int64#2
+# asm 2: add <addt0=%r9,<rz0=%rsi
+add %r9,%rsi
+
+# qhasm: carry? rt0 -= c0_stack
+# asm 1: subq <c0_stack=stack64#8,<rt0=int64#11
+# asm 2: subq <c0_stack=56(%rsp),<rt0=%r13
+subq 56(%rsp),%r13
+
+# qhasm: carry? rt1 -= c1_stack - carry
+# asm 1: sbbq <c1_stack=stack64#9,<rt1=int64#12
+# asm 2: sbbq <c1_stack=64(%rsp),<rt1=%r14
+sbbq 64(%rsp),%r14
+
+# qhasm: carry? rt2 -= c2_stack - carry
+# asm 1: sbbq <c2_stack=stack64#10,<rt2=int64#13
+# asm 2: sbbq <c2_stack=72(%rsp),<rt2=%r15
+sbbq 72(%rsp),%r15
+
+# qhasm: carry? rt3 -= c3_stack - carry
+# asm 1: sbbq <c3_stack=stack64#11,<rt3=int64#14
+# asm 2: sbbq <c3_stack=80(%rsp),<rt3=%rbx
+sbbq 80(%rsp),%rbx
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#6
+# asm 2: mov $0,>subt0=%r9
+mov $0,%r9
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#7
+# asm 2: mov $38,>subt1=%rax
+mov $38,%rax
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#6,<subt1=int64#7
+# asm 2: cmovae <subt0=%r9,<subt1=%rax
+cmovae %r9,%rax
+
+# qhasm: carry? rt0 -= subt1
+# asm 1: sub <subt1=int64#7,<rt0=int64#11
+# asm 2: sub <subt1=%rax,<rt0=%r13
+sub %rax,%r13
+
+# qhasm: carry? rt1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#6,<rt1=int64#12
+# asm 2: sbb <subt0=%r9,<rt1=%r14
+sbb %r9,%r14
+
+# qhasm: carry? rt2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#6,<rt2=int64#13
+# asm 2: sbb <subt0=%r9,<rt2=%r15
+sbb %r9,%r15
+
+# qhasm: carry? rt3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#6,<rt3=int64#14
+# asm 2: sbb <subt0=%r9,<rt3=%rbx
+sbb %r9,%rbx
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#7,<subt0=int64#6
+# asm 2: cmovc <subt1=%rax,<subt0=%r9
+cmovc %rax,%r9
+
+# qhasm: rt0 -= subt0
+# asm 1: sub <subt0=int64#6,<rt0=int64#11
+# asm 2: sub <subt0=%r9,<rt0=%r13
+sub %r9,%r13
+
+# qhasm: *(uint64 *)(rp + 32) = rz0
+# asm 1: movq <rz0=int64#2,32(<rp=int64#1)
+# asm 2: movq <rz0=%rsi,32(<rp=%rdi)
+movq %rsi,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = rz1
+# asm 1: movq <rz1=int64#3,40(<rp=int64#1)
+# asm 2: movq <rz1=%rdx,40(<rp=%rdi)
+movq %rdx,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = rz2
+# asm 1: movq <rz2=int64#4,48(<rp=int64#1)
+# asm 2: movq <rz2=%rcx,48(<rp=%rdi)
+movq %rcx,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = rz3
+# asm 1: movq <rz3=int64#5,56(<rp=int64#1)
+# asm 2: movq <rz3=%r8,56(<rp=%rdi)
+movq %r8,56(%rdi)
+
+# qhasm: *(uint64 *)(rp + 96) = rt0
+# asm 1: movq <rt0=int64#11,96(<rp=int64#1)
+# asm 2: movq <rt0=%r13,96(<rp=%rdi)
+movq %r13,96(%rdi)
+
+# qhasm: *(uint64 *)(rp + 104) = rt1
+# asm 1: movq <rt1=int64#12,104(<rp=int64#1)
+# asm 2: movq <rt1=%r14,104(<rp=%rdi)
+movq %r14,104(%rdi)
+
+# qhasm: *(uint64 *)(rp + 112) = rt2
+# asm 1: movq <rt2=int64#13,112(<rp=int64#1)
+# asm 2: movq <rt2=%r15,112(<rp=%rdi)
+movq %r15,112(%rdi)
+
+# qhasm: *(uint64 *)(rp + 120) = rt3
+# asm 1: movq <rt3=int64#14,120(<rp=int64#1)
+# asm 2: movq <rt3=%rbx,120(<rp=%rdi)
+movq %rbx,120(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_base.c b/ext/ed25519-amd64-asm/ge25519_base.c
new file mode 100644
index 00000000..a7ae9786
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_base.c
@@ -0,0 +1,7 @@
+#include "ge25519.h"
+
+const ge25519 ge25519_base = {{{0xC9562D608F25D51A, 0x692CC7609525A7B2, 0xC0A4E231FDD6DC5C, 0x216936D3CD6E53FE}},
+ {{0x6666666666666658, 0x6666666666666666, 0x6666666666666666, 0x6666666666666666}},
+ {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 000000000000000000}},
+ {{0x6DDE8AB3A5B7DDA3, 0x20F09F80775152F5, 0x66EA4E8E64ABE37D, 0x67875F0FD78B7665}}};
+
diff --git a/ext/ed25519-amd64-asm/ge25519_base_niels.data b/ext/ed25519-amd64-asm/ge25519_base_niels.data
new file mode 100644
index 00000000..8e3300cf
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_base_niels.data
@@ -0,0 +1,1536 @@
+{{{0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267}},
+ {{0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65}},
+ {{0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca}}},
+{{{0x8a99a56042b4d5a8, 0x8f2b810c4e60acf6, 0xe09e236bb16e37aa, 0x6bb595a669c92555}},
+ {{0x9224e7fc933c71d7, 0x9f469d967a0ff5b5, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e}},
+ {{0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8}}},
+{{{0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62}},
+ {{0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4}},
+ {{0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21}}},
+{{{0x95fe050a056818bf, 0x327e89715660faa9, 0xc3e8e3cd06a05073, 0x27933f4c7445a49a}},
+ {{0x287351b98efc099f, 0x6765c6f47dfd2538, 0xca348d3dfb0a9265, 0x680e910321e58727}},
+ {{0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18}}},
+{{{0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3}},
+ {{0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb}},
+ {{0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98}}},
+{{{0x499806b67b7d8ca4, 0x575be28427d22739, 0xbb085ce7204553b9, 0x38b64c41ae417884}},
+ {{0x3a0ceeeb77157131, 0x9b27158900c8af88, 0x8065b668da59a736, 0x51e57bb6a2cc38bd}},
+ {{0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f}}},
+{{{0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0}},
+ {{0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e}},
+ {{0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37}}},
+{{{0xe2a75dedf39234d9, 0x963d7680e1b558f9, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3}},
+ {{0x59b7596604dd3e8f, 0x6cb30377e288702c, 0xb1339c665ed9c323, 0x0915e76061bce52f}},
+ {{0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2}}},
+{{{0x7ec851ca553e2df3, 0xa71284cba64878b3, 0xe6b5e4193288d1e7, 0x4cf210ec5a9a8883}},
+ {{0x322d04a52d9021f6, 0xb9c19f3375c6bf9c, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61}},
+ {{0x9f867c7d968acaab, 0x5f54258e27092729, 0xd0a7d34bea180975, 0x21b546a3374126e1}}},
+{{{0xa94ff858a2888343, 0xce0ed4565313ed3c, 0xf55c3dcfb5bf34fa, 0x0a653ca5c9eab371}},
+ {{0x490a7a45d185218f, 0x9a15377846049335, 0x0060ea09cc31e1f6, 0x7e041577f86ee965}},
+ {{0x66b2a496ce5b67f3, 0xff5492d8bd569796, 0x503cec294a592cd0, 0x566943650813acb2}}},
+{{{0xb818db0c26620798, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4}},
+ {{0x5672f9eb1dabb69d, 0xba70b535afe853fc, 0x47ac0f752796d66d, 0x32a5351794117275}},
+ {{0xd3a644a6df648437, 0x703b6559880fbfdd, 0xcb852540ad3a1aa5, 0x0900b3f78e4c6468}}},
+{{{0x0a851b9f679d651b, 0xe108cb61033342f2, 0xd601f57fe88b30a3, 0x371f3acaed2dd714}},
+ {{0xed280fbec816ad31, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c}},
+ {{0xd560005efbf0bcad, 0x8eb70f2ed1870c5e, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670}}},
+{{{0x4138a434dcb8fa95, 0x870cf67d6c96840b, 0xde388574297be82c, 0x7c814db27262a55a}},
+ {{0xbaf875e4c93da0dd, 0xb93282a771b9294d, 0x80d63fb7f4c6c460, 0x6de9c73dea66c181}},
+ {{0x478904d5a04df8f2, 0xfafbae4ab10142d3, 0xf6c8ac63555d0998, 0x5aac4a412f90b104}}},
+{{{0xc64f326b3ac92908, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2}},
+ {{0x603a0d0abd7f5134, 0x8089c932e1d3ae46, 0xdf2591398798bd63, 0x1c145cd274ba0235}},
+ {{0x32e8386475f3d743, 0x365b8baf6ae5d9ef, 0x825238b6385b681e, 0x234929c1167d65e1}}},
+{{{0x984decaba077ade8, 0x383f77ad19eb389d, 0xc7ec6b7e2954d794, 0x59c77b3aeb7c3a7a}},
+ {{0x48145cc21d099fcf, 0x4535c192cc28d7e5, 0x80e7c1e548247e01, 0x4a5f28743b2973ee}},
+ {{0xd3add725225ccf62, 0x911a3381b2152c5d, 0xd8b39fad5b08f87d, 0x6f05606b4799fe3b}}},
+{{{0x9ffe9e92177ba962, 0x98aee71d0de5cae1, 0x3ff4ae942d831044, 0x714de12e58533ac8}},
+ {{0x5b433149f91b6483, 0xadb5dc655a2cbf62, 0x87fa8412632827b3, 0x60895e91ab49f8d8}},
+ {{0xe9ecf2ed0cf86c18, 0xb46d06120735dfd4, 0xbc9da09804b96be7, 0x73e2e62fd96dc26b}}},
+{{{0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9}},
+ {{0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39}},
+ {{0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0}}},
+{{{0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09}},
+ {{0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef}},
+ {{0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c}}},
+{{{0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9}},
+ {{0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a}},
+ {{0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c}}},
+{{{0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173}},
+ {{0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e}},
+ {{0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04}}},
+{{{0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999}},
+ {{0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c}},
+ {{0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56}}},
+{{{0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced}},
+ {{0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4}},
+ {{0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6}}},
+{{{0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f}},
+ {{0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8}},
+ {{0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151}}},
+{{{0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3}},
+ {{0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a}},
+ {{0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213}}},
+{{{0x9267806c567c49d8, 0x066d04ccca791e6a, 0xa69f5645e3cc394b, 0x5c95b686a0788cd2}},
+ {{0x97d980e0aa39f7d2, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362}},
+ {{0x2ac519c10d14a954, 0xeaf474b494b5fa90, 0xe6af8382a9f87a5a, 0x0dea6db1879be094}}},
+{{{0xaa66bf547344e5ab, 0xda1258888f1b4309, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd}},
+ {{0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb}},
+ {{0x52151362793408cf, 0xeb0f170319963d94, 0xa833b2fa883d9466, 0x093a7fa775003c78}}},
+{{{0xe5107de63a16d7be, 0xa377ffdc9af332cf, 0x70d5bf18440b677f, 0x6a252b19a4a31403}},
+ {{0xb8e9604460a91286, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e}},
+ {{0x9ed919d5d36990f3, 0x5213aebbdb4eb9f2, 0xc708ea054cb99135, 0x58ded57f72260e56}}},
+{{{0x78e79dade9413d77, 0xf257f9d59729e67d, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c}},
+ {{0xda6d53265b0fd48b, 0x8960823193bfa988, 0xd78ac93261d57e28, 0x79f2942d3a5c8143}},
+ {{0x97da2f25b6c88de9, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5}}},
+{{{0x9acca683a7016bfe, 0x90505f4df2c50b6d, 0x6b610d5fcce435aa, 0x19a10d446198ff96}},
+ {{0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0}},
+ {{0x560a2cd687dce6ca, 0x7f3568c48664cf4d, 0x8741e95222803a38, 0x483bdab1595653fc}}},
+{{{0xfa780f148734fa49, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe}},
+ {{0xd6cf4d0ab4da80f6, 0x82483e45f8307fe0, 0x05005269ae6f9da4, 0x1c7052909cf7877a}},
+ {{0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840}}},
+{{{0x9db7c4d0248e1eb0, 0xe07697e14d74bf52, 0x1e6a9b173c562354, 0x7fa7c21f795a4965}},
+ {{0x8bdf1fb9be8c0ec8, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a}},
+ {{0xe9eb02c4db31f67f, 0xed25fd8910bcfb2b, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce}}},
+{{{0x360692f8087d8e31, 0xf4dcc637d27163f7, 0x25a4e62065ea5963, 0x659bf72e5ac160d9}},
+ {{0x9aafb9b05ee38c5b, 0xbf9d2d4e071a13c7, 0x8eee6e6de933290a, 0x1c3bab17ae109717}},
+ {{0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990}}},
+{{{0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7}},
+ {{0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d}},
+ {{0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464}}},
+{{{0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2}},
+ {{0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030}},
+ {{0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80}}},
+{{{0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4}},
+ {{0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9}},
+ {{0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b}}},
+{{{0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5}},
+ {{0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481}},
+ {{0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8}}},
+{{{0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb}},
+ {{0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b}},
+ {{0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf}}},
+{{{0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74}},
+ {{0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b}},
+ {{0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6}}},
+{{{0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29}},
+ {{0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3}},
+ {{0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc}}},
+{{{0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83}},
+ {{0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c}},
+ {{0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2}}},
+{{{0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed}},
+ {{0x3906c72aed261ae5, 0x9ab68fd988e100f7, 0xf5e9059af3360197, 0x0e53dc78bf2b6d47}},
+ {{0xb90829bf7971877a, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5}}},
+{{{0xd11ff05154b260ce, 0xd86dc38e72f95270, 0x601fcd0d267cc138, 0x2b67916429e90ccd}},
+ {{0xa98285d187eaffdb, 0xa5b4fbbbd8d0a864, 0xb658f27f022663f7, 0x3bbc2b22d99ce282}},
+ {{0xb917c952583c0a58, 0x653ff9b80fe4c6f3, 0x9b0da7d7bcdf3c0c, 0x43a0eeb6ab54d60e}}},
+{{{0x396966a46d4a5487, 0xf811a18aac2bb3ba, 0x66e4685b5628b26b, 0x70a477029d929b92}},
+ {{0x3ac6322357875fe8, 0xd9d4f4ecf5fbcb8f, 0x8dee8493382bb620, 0x50c5eaa14c799fdc}},
+ {{0xdd0edc8bd6f2fb3c, 0x54c63aa79cc7b7a0, 0xae0b032b2c8d9f1a, 0x6f9ce107602967fb}}},
+{{{0xad1054b1cde1c22a, 0xc4a8e90248eb32df, 0x5f3e7b33accdc0ea, 0x72364713fc79963e}},
+ {{0x139693063520e0b5, 0x437fcf7c88ea03fe, 0xf7d4c40bd3c959bc, 0x699154d1f893ded9}},
+ {{0x315d5c75b4b27526, 0xcccb842d0236daa5, 0x22f0c8a3345fee8e, 0x73975a617d39dbed}}},
+{{{0xe4024df96375da10, 0x78d3251a1830c870, 0x902b1948658cd91c, 0x7e18b10b29b7438a}},
+ {{0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d}},
+ {{0x9071d9132b6beb2f, 0x0f26e9ad28418247, 0xeab91ec9bdec925d, 0x4be65bc8f48af2de}}},
+{{{0x78487feba36e7028, 0x5f3f13001dd8ce34, 0x934fb12d4b30c489, 0x056c244d397f0a2b}},
+ {{0x1d50fba257c26234, 0x7bd4823adeb0678b, 0xc2b0dc6ea6538af5, 0x5665eec6351da73e}},
+ {{0xdb3ee00943bfb210, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938}}},
+{{{0x549e342ac07fb34b, 0x02d8220821373d93, 0xbc262d70acd1f567, 0x7a92c9fdfbcac784}},
+ {{0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8}},
+ {{0x65bd1bea70f801de, 0x1befb7c0fe49e28a, 0xa86306cdb1b2ae4a, 0x3b7ac0cd265c2a09}}},
+{{{0x822bee438c01bcec, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b}},
+ {{0xf0d54e4f22ed39a7, 0xa2aae91e5608150a, 0xf421b2e9eddae875, 0x31bc531d6b7de992}},
+ {{0xdf3d134da980f971, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e}}},
+{{{0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d}},
+ {{0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9}},
+ {{0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf}}},
+{{{0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785}},
+ {{0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a}},
+ {{0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823}}},
+{{{0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee}},
+ {{0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5}},
+ {{0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790}}},
+{{{0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7}},
+ {{0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068}},
+ {{0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375}}},
+{{{0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a}},
+ {{0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252}},
+ {{0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76}}},
+{{{0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21}},
+ {{0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b}},
+ {{0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111}}},
+{{{0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40}},
+ {{0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445}},
+ {{0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c}}},
+{{{0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4}},
+ {{0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245}},
+ {{0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6}}},
+{{{0xd833d7beec2a4c38, 0x2c9162830acc20ed, 0xe93a47aa92df7581, 0x702d67a3333c4a81}},
+ {{0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, 0xbcac008a78eda015, 0x2cb8b3a5b483b03f}},
+ {{0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d}}},
+{{{0x59f73c773fefee9d, 0xb3f1ef89c1cf989d, 0xe35dfb42e02e545f, 0x5766120b47a1b47c}},
+ {{0x91925dccbd83157d, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b}},
+ {{0xdb20ba0fb8b6b7ff, 0xb732c3b677511fa1, 0xa92b51c099f02d89, 0x4f3875ad489ca5f1}}},
+{{{0xc7fc762f4932ab22, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081}},
+ {{0x79ed13f6ee73eec0, 0xa5c6526d69110bb1, 0xe48928c38603860c, 0x722a1446fd7059f5}},
+ {{0xd0959fe9a8cf8819, 0xd0a995508475a99c, 0x6eac173320b09cc5, 0x628ecf04331b1095}}},
+{{{0x98bcb118a9d0ddbc, 0xee449e3408b4802b, 0x87089226b8a6b104, 0x685f349a45c7915d}},
+ {{0x9b41acf85c74ccf1, 0xb673318108265251, 0x99c92aed11adb147, 0x7a47d70d34ecb40f}},
+ {{0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, 0xa17aa1752ff8f5ed, 0x11ded9020e01fdc0}}},
+{{{0x890e7809caefe704, 0x8728296de30e8c6c, 0x4c5cd2a392aeb1c9, 0x194263d15771531f}},
+ {{0x471f95b03bea93b7, 0x0552d7d43313abd3, 0xbd9370e2e17e3f7b, 0x7b120f1db20e5bec}},
+ {{0x17d2fb3d86502d7a, 0xb564d84450a69352, 0x7da962c8a60ed75d, 0x00d0f85b318736aa}}},
+{{{0x978b142e777c84fd, 0xf402644705a8c062, 0xa67ad51be7e612c7, 0x2f7b459698dd6a33}},
+ {{0xa6753c1efd7621c1, 0x69c0b4a7445671f5, 0x971f527405b23c11, 0x387bc74851a8c7cd}},
+ {{0x81894b4d4a52a9a8, 0xadd93e12f6b8832f, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd}}},
+{{{0x2e8f1f0091910c1f, 0xa4df4fe0bff2e12c, 0x60c6560aee927438, 0x6338283facefc8fa}},
+ {{0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b}},
+ {{0x9e630d2c7f191ee4, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5}}},
+{{{0x85683916c11a1897, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6}},
+ {{0xc0accf90b4d3b66d, 0xa7059de561732e60, 0x033d1f7870c6b0ba, 0x584161cd26d946e4}},
+ {{0xbbf2b1a072d27ca2, 0xbf393c59fbdec704, 0xe98dbbcee262b81e, 0x02eebd0b3029b589}}},
+{{{0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0}},
+ {{0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c}},
+ {{0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366}}},
+{{{0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943}},
+ {{0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff}},
+ {{0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812}}},
+{{{0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab}},
+ {{0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b}},
+ {{0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd}}},
+{{{0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1}},
+ {{0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9}},
+ {{0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e}}},
+{{{0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840}},
+ {{0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e}},
+ {{0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272}}},
+{{{0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5}},
+ {{0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4}},
+ {{0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab}}},
+{{{0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b}},
+ {{0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447}},
+ {{0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494}}},
+{{{0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3}},
+ {{0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8}},
+ {{0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03}}},
+{{{0xf8ae4d2ad8453902, 0x7018058ee8db2d1d, 0xaab3995fc7d2c11e, 0x53b16d2324ccca79}},
+ {{0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510}},
+ {{0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5}}},
+{{{0xbb0d18fd029c6421, 0xbc2d142189298f02, 0x8347f8e68b250e96, 0x7b9f2fe8032d71c9}},
+ {{0xdd63589386f86d9c, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb}},
+ {{0xd87823cd319e0780, 0xefc4cfc1897775c5, 0x4854fb129a0ab3f7, 0x12c49d417238c371}}},
+{{{0x0950b533ffe83769, 0x21861c1d8e1d6bd1, 0xf022d8381302e510, 0x2509200c6391cab4}},
+ {{0x09b3a01783799542, 0x626dd08faad5ee3f, 0xba00bceeeb70149f, 0x1421b246a0a444c9}},
+ {{0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, 0xadba5e0c0b3eb9dc, 0x2ab5504448a49ce3}}},
+{{{0x2ed227266f0f5dec, 0x9824ee415ed50824, 0x807bec7c9468d415, 0x7093bae1b521e23f}},
+ {{0xdc07ac631c5d3afa, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d}},
+ {{0x6409e759d6722c41, 0xa674e1cf72bf729b, 0xbc0a24eb3c21e569, 0x390167d24ebacb23}}},
+{{{0x27f58e3bba353f1c, 0x4c47764dbf6a4361, 0xafbbc4e56e562650, 0x07db2ee6aae1a45d}},
+ {{0xd7bb054ba2f2120b, 0xe2b9ceaeb10589b7, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69}},
+ {{0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287}}},
+{{{0xe4ca40782cd27cb0, 0xdaf9c323fbe967bd, 0xb29bd34a8ad41e9e, 0x72810497626ede4d}},
+ {{0x32fee570fc386b73, 0xda8b0141da3a8cc7, 0x975ffd0ac8968359, 0x6ee809a1b132a855}},
+ {{0x9444bb31fcfd863a, 0x2fe3690a3e4e48c5, 0xdc29c867d088fa25, 0x13bd1e38d173292e}}},
+{{{0xd32b4cd8696149b5, 0xe55937d781d8aab7, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0}},
+ {{0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd}},
+ {{0x3630dfa1b802a6b0, 0x880f874742ad3bd5, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9}}},
+{{{0xd531b8bd2b7b9af6, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49}},
+ {{0x6eccd85278d941ed, 0x2254ae83d22f7843, 0xc522d02e7bbfcdb7, 0x681e3351bff0e4e2}},
+ {{0x8b64b59d83034f45, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b}}},
+{{{0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1}},
+ {{0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108}},
+ {{0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233}}},
+{{{0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d}},
+ {{0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7}},
+ {{0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307}}},
+{{{0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53}},
+ {{0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44}},
+ {{0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6}}},
+{{{0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355}},
+ {{0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd}},
+ {{0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80}}},
+{{{0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304}},
+ {{0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7}},
+ {{0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da}}},
+{{{0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2}},
+ {{0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784}},
+ {{0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c}}},
+{{{0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7}},
+ {{0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472}},
+ {{0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17}}},
+{{{0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4}},
+ {{0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5}},
+ {{0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2}}},
+{{{0xd550095bab6f4985, 0x04f4cd5b4fbfaf1a, 0x9d8e2ed12a0c7540, 0x2bc24e04b2212286}},
+ {{0x09d4b60b2fe09a14, 0xc384f0afdbb1747e, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a}},
+ {{0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5}}},
+{{{0x4bcef17f06ffca16, 0xde06e1db692ae16a, 0x0753702d614f42b0, 0x5f6041b45b9212d0}},
+ {{0xd1ab324e1b3a1273, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68}},
+ {{0x7d531574028c2705, 0x80317d69db0d75fe, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998}}},
+{{{0x1558967b9e6585a3, 0x97c99ce098e98b92, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa}},
+ {{0xf004be62a24d40dd, 0xba0659910452d41f, 0x81c45ee162a44234, 0x4cb829d8a22266ef}},
+ {{0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c}}},
+{{{0x8416ebd40b50babc, 0x1508722628208bee, 0xa3148fafb9c1c36d, 0x0d07daacd32d7d5d}},
+ {{0x3241c00e7d65318c, 0xe6bee5dcd0e86de7, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3}},
+ {{0xf9c2414a695aa3eb, 0xdaa42c4c05a68f21, 0x7c6c23987f93963e, 0x210e8cd30c3954e3}}},
+{{{0xac4201f210a71c06, 0x6a65e0aef3bfb021, 0xbc42c35c393632f7, 0x56ea8db1865f0742}},
+ {{0x2b50f16137fe6c26, 0xe102bcd856e404d8, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91}},
+ {{0xfff5fb4bcf535119, 0xf4989d79df1108a0, 0xbdfcea659a3ba325, 0x18a11f1174d1a6f2}}},
+{{{0x407375ab3f6bba29, 0x9ec3b6d8991e482e, 0x99c80e82e55f92e9, 0x307c13b6fb0c0ae1}},
+ {{0xfbd63cdad27a5f2c, 0xf00fc4bc8aa106d7, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85}},
+ {{0x24751021cb8ab5e7, 0xfc2344495c5010eb, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5}}},
+{{{0x033cc55ff1b82eb5, 0xb15ae36d411cae52, 0xba40b6198ffbacd3, 0x768edce1532e861f}},
+ {{0x9156fe6b89d8eacc, 0xe6b79451e23126a1, 0xbd7463d93944eb4e, 0x726373f6767203ae}},
+ {{0xe305ca72eb7ef68a, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd}}},
+{{{0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223}},
+ {{0x5e2702878af34ceb, 0x900b0409b946d6ae, 0x6512ebf7dabd8512, 0x61d9b76988258f81}},
+ {{0xa6c5a71349b7d94b, 0xa3f3d15823eb9446, 0x0416fbd277484834, 0x69d45e6f2c70812f}}},
+{{{0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908}},
+ {{0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93}},
+ {{0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3}}},
+{{{0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e}},
+ {{0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c}},
+ {{0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808}}},
+{{{0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22}},
+ {{0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8}},
+ {{0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969}}},
+{{{0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea}},
+ {{0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10}},
+ {{0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba}}},
+{{{0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03}},
+ {{0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c}},
+ {{0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92}}},
+{{{0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a}},
+ {{0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9}},
+ {{0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa}}},
+{{{0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7}},
+ {{0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9}},
+ {{0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a}}},
+{{{0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42}},
+ {{0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c}},
+ {{0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3}}},
+{{{0xe2790aae4d077c41, 0x8b938270db7469a3, 0x6eb632dc8abd16a2, 0x720814ecaa064b72}},
+ {{0x315c29c795115389, 0xd7e0e507862f74ce, 0x0c4a762185927432, 0x72de6c984a25a1e4}},
+ {{0xae9ab553bf6aa310, 0x050a50a9806d6e1b, 0x92bb7403adff5139, 0x0394d27645be618b}}},
+{{{0x4d572251857eedf4, 0xe3724edde19e93c5, 0x8a71420e0b797035, 0x3b3c833687abe743}},
+ {{0xf5396425b23545a4, 0x15a7a27e98fbb296, 0xab6c52bc636fdd86, 0x79d995a8419334ee}},
+ {{0xcd8a8ea61195dd75, 0xa504d8a81dd9a82f, 0x540dca81a35879b6, 0x60dd16a379c86a8a}}},
+{{{0x35a2c8487381e559, 0x596ffea6d78082cb, 0xcb9771ebdba7b653, 0x5a08b5019b4da685}},
+ {{0x3501d6f8153e47b8, 0xb7a9675414a2f60c, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a}},
+ {{0xc8d4ac04516ab786, 0x595af3215295b23d, 0xd6edd234db0230c1, 0x0929efe8825b41cc}}},
+{{{0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, 0x83604432238dde87, 0x1e3a5272f5c0753c}},
+ {{0x8b3172b7ad56651d, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f}},
+ {{0xd2918da78159a59c, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128}}},
+{{{0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, 0xf4cbf12942f5fe00, 0x01a13ff9bdbf0752}},
+ {{0x99852bc3852cfdb0, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99}},
+ {{0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, 0xd527bfcfeb778bf2, 0x303337da7012a3be}}},
+{{{0x955422228c1c9d7c, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b}},
+ {{0x976d3ccbfad2fdd1, 0xcb88839737a640a8, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b}},
+ {{0x0c003fbdc08d678d, 0x4d982fa37ead2b17, 0xc07e6bcdb2e582f1, 0x296c7291df412a44}}},
+{{{0x7903de2b33daf397, 0xd0ff0619c9a624b3, 0x8a1d252b555b3e18, 0x2b6d581c52e0b7c0}},
+ {{0xdfb23205dab8b59e, 0x465aeaa0c8092250, 0xd133c1189a725d18, 0x2327370261f117d1}},
+ {{0x3d0543d3623e7986, 0x679414c2c278a354, 0xae43f0cc726196f6, 0x7836c41f8245eaba}}},
+{{{0xe7a254db49e95a81, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38}},
+ {{0xca651e848011937c, 0xc6b0c46e6ef41a28, 0xb7021ba75f3f8d52, 0x119dff99ead7b9fd}},
+ {{0x43eadfcbf4b31d4d, 0xc6503f7411148892, 0xfeee68c5060d3b17, 0x329293b3dd4a0ac8}}},
+{{{0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232}},
+ {{0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35}},
+ {{0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4}}},
+{{{0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab}},
+ {{0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d}},
+ {{0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413}}},
+{{{0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84}},
+ {{0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56}},
+ {{0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7}}},
+{{{0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495}},
+ {{0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5}},
+ {{0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41}}},
+{{{0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76}},
+ {{0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286}},
+ {{0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489}}},
+{{{0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008}},
+ {{0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16}},
+ {{0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76}}},
+{{{0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309}},
+ {{0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700}},
+ {{0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb}}},
+{{{0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a}},
+ {{0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd}},
+ {{0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760}}},
+{{{0xcaf55ec27c59b23f, 0x99aeed3e154d04f2, 0x68441d72e14141f4, 0x140345133932a0a2}},
+ {{0xd91430e0dc028c3c, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c}},
+ {{0x7bfec69aab5cad3d, 0xc23e8cd34cb2cfad, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18}}},
+{{{0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233}},
+ {{0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592}},
+ {{0x405fdd309afcb346, 0xd9723d4428e63f54, 0x94c01df05f65aaae, 0x43e4dc3ae14c0809}}},
+{{{0xbc12c7f1a938a517, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f}},
+ {{0xea6f7ac3adc2c6a3, 0xd0e928f6e9717c94, 0xe2d379ead645eaf5, 0x46dd8785c51ffbbe}},
+ {{0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42}}},
+{{{0x97c749eeb701cb96, 0x83f438d4b6a369c3, 0x62962b8b9a402cd9, 0x6976c7509888df7b}},
+ {{0x5b97946582ffa02a, 0xda096a51fea8f549, 0xa06351375f77af9b, 0x1bcfde61201d1e76}},
+ {{0x4a4a5490246a59a2, 0xd63ebddee87fdd90, 0xd9437c670d2371fa, 0x69e87308d30f8ed6}}},
+{{{0x435a8bb15656beb0, 0xf8fac9ba4f4d5bca, 0xb9b278c41548c075, 0x3eb0ef76e892b622}},
+ {{0x0f80bf028bc80303, 0x6aae16b37a18cefb, 0xdd47ea47d72cd6a3, 0x61943588f4ed39aa}},
+ {{0xd26e5c3e91039f85, 0xc0e9e77df6f33aa9, 0xe8968c5570066a93, 0x3c34d1881faaaddd}}},
+{{{0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, 0xa09ba3ea72d926c4, 0x374193513fd8b36d}},
+ {{0xbd5b0b8f2fffe0d9, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a}},
+ {{0xb4e856e45a9d1ed2, 0xefe848766c97a9a2, 0xb104cf641e5eee7d, 0x2f50b81c88a71c8f}}},
+{{{0x31723c61fc6811bb, 0x9cb450486211800f, 0x768933d347995753, 0x3491a53502752fcd}},
+ {{0x2b552ca0a7da522a, 0x3230b336449b0250, 0xf2c4c5bca4b99fb9, 0x7b2c674958074a22}},
+ {{0xd55165883ed28cdf, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74}}},
+{{{0x3d420811d06d4a67, 0xbefc048590e0ffe3, 0xf870c6b7bd487bde, 0x6e2a7316319afa28}},
+ {{0x9624778c3e94a8ab, 0x0ad6f3cee9a78bec, 0x948ac7810d743c4f, 0x76627935aaecfccc}},
+ {{0x56a8ac24d6d59a9f, 0xc8db753e3096f006, 0x477f41e68f4c5299, 0x588d851cf6c86114}}},
+{{{0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650}},
+ {{0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb}},
+ {{0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba}}},
+{{{0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650}},
+ {{0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9}},
+ {{0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561}}},
+{{{0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e}},
+ {{0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2}},
+ {{0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701}}},
+{{{0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322}},
+ {{0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e}},
+ {{0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0}}},
+{{{0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0}},
+ {{0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839}},
+ {{0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7}}},
+{{{0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9}},
+ {{0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8}},
+ {{0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54}}},
+{{{0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185}},
+ {{0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde}},
+ {{0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f}}},
+{{{0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6}},
+ {{0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253}},
+ {{0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d}}},
+{{{0x47b837f753242cec, 0x256dc48cc04212f2, 0xe222fbfbe1d928c5, 0x48ea295bad8a2c07}},
+ {{0x299b1c3f57c5715e, 0x96cb929e6b686d90, 0x3004806447235ab3, 0x2c435c24a44d9fe1}},
+ {{0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e}}},
+{{{0x8487e3d02bc73659, 0x4baf8445059979df, 0xd17c975adcad6fbf, 0x57369f0bdefc96b6}},
+ {{0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148}},
+ {{0xf1a9990175638698, 0x353dd1beeeaa60d3, 0x849471334c9ba488, 0x63fa6e6843ade311}}},
+{{{0xd15c20536597c168, 0x9f73740098d28789, 0x18aee7f13257ba1f, 0x3418bfda07346f14}},
+ {{0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, 0xdf28074441ca9ede, 0x07073b98f35b7d67}},
+ {{0xd03c676c4ce530d4, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9}}},
+{{{0xe1f6b79ebf8469ad, 0x15801004e2663135, 0x9a498330af74181b, 0x3ba2504f049b673c}},
+ {{0x9a6ce876760321fd, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a}},
+ {{0x0b52b5606dba5ab6, 0xa9134f0fbbb1edab, 0x30a9520d9b04a635, 0x6813b8f37973e5db}}},
+{{{0x9854b054334127c1, 0x105d047882fbff25, 0xdb49f7f944186f4f, 0x1768e838bed0b900}},
+ {{0xf194ca56f3157e29, 0x136d35705ef528a5, 0xdd4cef778b0599bc, 0x7d5472af24f833ed}},
+ {{0xd0ef874daf33da47, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a}}},
+{{{0xf59e6bb319cd63ca, 0x670c159221d06839, 0xb06d565b2150cab6, 0x20fb199d104f12a3}},
+ {{0x12c7bfaeb61ba775, 0xb84e621fe263bffd, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634}},
+ {{0x61943dee6d99c120, 0x86101f2e460b9fe0, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc}}},
+{{{0x791b4cc1756286fa, 0xdbced317d74a157c, 0x7e732421ea72bde6, 0x01fe18491131c8e9}},
+ {{0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f}},
+ {{0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a}}},
+{{{0xdbdae701c5738dd3, 0xf9c6f635b26f1bee, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8}},
+ {{0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, 0xf33ae4f552a2c8b4, 0x59aab07a0d40166a}},
+ {{0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46}}},
+{{{0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7}},
+ {{0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c}},
+ {{0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9}}},
+{{{0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877}},
+ {{0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83}},
+ {{0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3}}},
+{{{0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633}},
+ {{0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98}},
+ {{0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016}}},
+{{{0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1}},
+ {{0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1}},
+ {{0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059}}},
+{{{0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b}},
+ {{0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042}},
+ {{0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a}}},
+{{{0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0}},
+ {{0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217}},
+ {{0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd}}},
+{{{0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff}},
+ {{0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05}},
+ {{0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd}}},
+{{{0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42}},
+ {{0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295}},
+ {{0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd}}},
+{{{0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, 0xae64b9004fdd3c75, 0x403a395b53909e62}},
+ {{0x86c5fc16861b7e9a, 0xf6a330476a27c451, 0x01667267a1e93597, 0x05ffb9cd6082dfeb}},
+ {{0xa617fa9ff53f6139, 0x60f2b5e513e66cb6, 0xd7a8beefb3448aa4, 0x7a2932856f5ea192}}},
+{{{0x0b39d761b02de888, 0x5f550e7ed2414e1f, 0xa6bfa45822e1a940, 0x050a2f7dfd447b99}},
+ {{0xb89c444879639302, 0x4ae4f19350c67f2c, 0xf0b35da8c81af9c6, 0x39d0003546871017}},
+ {{0x437c3b33a650db77, 0x6bafe81dbac52bb2, 0xfe99402d2db7d318, 0x2b5b7eec372ba6ce}}},
+{{{0xb3bc4bbd83f50eef, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9}},
+ {{0xa694404d613ac8f4, 0x500c3c2bfa97e72c, 0x874104d21fcec210, 0x1b205fb38604a8ee}},
+ {{0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae}}},
+{{{0xf2a7af510354c13d, 0xd7a0b145aa372b60, 0x2869b96a05a3d470, 0x6528e42d82460173}},
+ {{0x95265514d71eb524, 0xe603d8815df14593, 0x147cdf410d4de6b7, 0x5293b1730437c850}},
+ {{0x23d0e0814bccf226, 0x92c745cd8196fb93, 0x8b61796c59541e5b, 0x40a44df0c021f978}}},
+{{{0xdaa869894f20ea6a, 0xea14a3d14c620618, 0x6001fccb090bf8be, 0x35f4e822947e9cf0}},
+ {{0x86c96e514bc5d095, 0xf20d4098fca6804a, 0x27363d89c826ea5d, 0x39ca36565719cacf}},
+ {{0x97506f2f6f87b75c, 0xc624aea0034ae070, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f}}},
+{{{0x6469a17d89735d12, 0xdb6f27d5e662b9f1, 0x9fcba3286a395681, 0x363b8004d269af25}},
+ {{0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, 0x90ec9675ee44d967, 0x64ca348d2a985aac}},
+ {{0x99588e19e4c4912d, 0xefcc3b4e1ca5ce6b, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819}}},
+{{{0xb919e1515a770641, 0xa9a2e2c74e7f8039, 0x7527250b3df23109, 0x756a7330ac27b78b}},
+ {{0xa290c06142542129, 0xf2e2c2aebe8d5b90, 0xcf2458db76abfe1b, 0x02157ade83d626bf}},
+ {{0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, 0x81a248776edbb4ca, 0x1a944ee88ecd0563}}},
+{{{0xd5a91d1151039372, 0x2ed377b799ca26de, 0xa17202acfd366b6b, 0x0730291bd6901995}},
+ {{0xbb40a859182362d6, 0xb99f55778a4d1abb, 0x8d18b427758559f6, 0x26c20fe74d26235a}},
+ {{0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49}}},
+{{{0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6}},
+ {{0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e}},
+ {{0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc}}},
+{{{0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402}},
+ {{0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081}},
+ {{0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006}}},
+{{{0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0}},
+ {{0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5}},
+ {{0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64}}},
+{{{0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c}},
+ {{0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90}},
+ {{0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18}}},
+{{{0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b}},
+ {{0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355}},
+ {{0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413}}},
+{{{0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194}},
+ {{0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b}},
+ {{0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56}}},
+{{{0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00}},
+ {{0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b}},
+ {{0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38}}},
+{{{0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6}},
+ {{0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57}},
+ {{0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b}}},
+{{{0xb496123a6b6c6609, 0xa750fe8580ab5938, 0xf471bf39b7c27a5f, 0x507903ce77ac193c}},
+ {{0xff91a66a90166220, 0xf22552ae5bf1e009, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9}},
+ {{0x62f90d65dfde3e34, 0xcf28c592b9fa5fad, 0x99c86ef9c6164510, 0x25d448044a256c84}}},
+{{{0xbd68230ec7e9b16f, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e}},
+ {{0x2c7c4415c9022b55, 0x56a0d241812eb1fe, 0xf02ea1c9d7b65e0d, 0x4180512fd5323b26}},
+ {{0xa4ff3e698a48a5db, 0xba6a3806bd95403b, 0x9f7ce1af47d5b65d, 0x15e087e55939d2fb}}},
+{{{0x12207543745c1496, 0xdaff3cfdda38610c, 0xe4e797272c71c34f, 0x39c07b1934bdede9}},
+ {{0x8894186efb963f38, 0x48a00e80dc639bd5, 0xa4e8092be96c1c99, 0x5a097d54ca573661}},
+ {{0x2d45892b17c9e755, 0xd033fd7289308df8, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079}}},
+{{{0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, 0x96ef5329c7e899cb, 0x3d4e8dbba668baa6}},
+ {{0xee0f0fddd087a25f, 0x9c7531555c3e34ee, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2}},
+ {{0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d}}},
+{{{0xb1491d0bd6900c54, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df}},
+ {{0x1e09d94057775696, 0xeed1265c3cd951db, 0xfa9dac2b20bce16f, 0x0f7f76e0e8d089f4}},
+ {{0x36d9ebc5d485b00c, 0xa2596492e4adb365, 0xc1659480c2119ccd, 0x45306349186e0d5f}}},
+{{{0x94ddd0c1a6cdff1d, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f}},
+ {{0x96a414ec2b072491, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f}},
+ {{0xecb29fff199801f7, 0x9d361d1fa2a0f72f, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2}}},
+{{{0x4c126cf9d18df255, 0xc1d471e9147a63b6, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2}},
+ {{0x1518e85b31b16489, 0x8faadcb7db710bfb, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1}},
+ {{0xce040e9ec04145bc, 0xc71ff4e208f6834c, 0xbd546e8dab8847a3, 0x64666aa0a4d2aba5}}},
+{{{0x6841435a7c06d912, 0xca123c21bb3f830b, 0xd4b37b27b1cbe278, 0x1d753b84c76f5046}},
+ {{0xb0c53bf73337e94c, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468}},
+ {{0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e}}},
+{{{0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e}},
+ {{0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17}},
+ {{0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa}}},
+{{{0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c}},
+ {{0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438}},
+ {{0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543}}},
+{{{0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d}},
+ {{0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452}},
+ {{0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6}}},
+{{{0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f}},
+ {{0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55}},
+ {{0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c}}},
+{{{0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc}},
+ {{0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d}},
+ {{0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86}}},
+{{{0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70}},
+ {{0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a}},
+ {{0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388}}},
+{{{0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00}},
+ {{0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc}},
+ {{0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4}}},
+{{{0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8}},
+ {{0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d}},
+ {{0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af}}},
+{{{0xfd0d75879cf12657, 0xe82fef94e53a0e29, 0xcc34a7f05bbb4be7, 0x0b251172a50c38a2}},
+ {{0x9532f48fcc5cd29b, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2}},
+ {{0x1d5ad94890bb02c0, 0x50e208b10ec25115, 0xa26a22894ef21702, 0x4dc923343b524805}}},
+{{{0xe3828c400f8086b6, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784}},
+ {{0x3ad3e3ebf36c4975, 0xd75d25a537862125, 0xe873943da025a516, 0x6bbc7cb4c411c847}},
+ {{0x3c6f9cd1d4a50d56, 0xb6244077c6feab7e, 0x6ff9bf483580972e, 0x00375883b332acfb}}},
+{{{0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, 0xb5ad8691dcd5ca31, 0x67238dbd8c450660}},
+ {{0xc98bec856c75c99c, 0xe44184c000e33cf4, 0x0a676b9bba907634, 0x669e2cb571f379d7}},
+ {{0xcb116b73a49bd308, 0x025aad6b2392729e, 0xb4793efa3f55d9b1, 0x72a1056140678bb9}}},
+{{{0xa2b6812b1cc9249d, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00}},
+ {{0x0d8d2909e2e505b6, 0x98ca78abc0291230, 0x77ef5569a9b12327, 0x7c77897b81439b47}},
+ {{0xf1c1b5e2de331cb5, 0x5a9f5d8e15fca420, 0x9fa438f17bd932b1, 0x2a381bf01c6146e7}}},
+{{{0xac9b9879cfc811c1, 0x8b7d29813756e567, 0x50da4e607c70edfc, 0x5dbca62f884400b6}},
+ {{0xf7c0be32b534166f, 0x27e6ca6419cf70d4, 0x934df7d7a957a759, 0x5701461dabdec2aa}},
+ {{0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242}}},
+{{{0x6fc09f5266ddd216, 0xdce560a7c8e37048, 0xec65939da2df62fd, 0x7a869ae7e52ed192}},
+ {{0x78409b1d87e463d4, 0xad4da95acdfb639d, 0xec28773755259b9c, 0x69c806e9c31230ab}},
+ {{0x7b48f57414bb3f22, 0x68c7cee4aedccc88, 0xed2f936179ed80be, 0x25d70b885f77bc4b}}},
+{{{0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24}},
+ {{0x98459d29bb1ae4d4, 0x56b9c4c739f954ec, 0x832743f6c29b4b3e, 0x21ea8e2798b6878a}},
+ {{0x87bef4b46a5a7b9c, 0xd2299d1b5fc1d062, 0x82409818dd321648, 0x5c5abeb1e5a2e03d}}},
+{{{0x14722af4b73c2ddb, 0xbc470c5f5a05060d, 0x00943eac2581b02e, 0x0e434b3b1f499c8f}},
+ {{0x02cde6de1306a233, 0x7b5a52a2116f8ec7, 0xe1c681f4c1163b5b, 0x241d350660d32643}},
+ {{0x6be4404d0ebc52c7, 0xae46233bb1a791f5, 0x2aec170ed25db42b, 0x1d8dfd966645d694}}},
+{{{0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d}},
+ {{0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a}},
+ {{0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137}}},
+{{{0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007}},
+ {{0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86}},
+ {{0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e}}},
+{{{0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07}},
+ {{0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c}},
+ {{0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac}}},
+{{{0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318}},
+ {{0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754}},
+ {{0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859}}},
+{{{0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2}},
+ {{0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964}},
+ {{0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410}}},
+{{{0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e}},
+ {{0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599}},
+ {{0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436}}},
+{{{0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992}},
+ {{0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d}},
+ {{0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf}}},
+{{{0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40}},
+ {{0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb}},
+ {{0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716}}},
+{{{0x7afcd613efa9d697, 0x0cc45aa41c067959, 0xa56fe104c1fada96, 0x3a73b70472e40365}},
+ {{0x7b26e56b9e2d4734, 0xc4c7132b81c61675, 0xef5c9525ec9cde7f, 0x39c80b16e71743ad}},
+ {{0x0f196e0d1b826c68, 0xf71ff0e24960e3db, 0x6113167023b7436c, 0x0cf0ea5877da7282}}},
+{{{0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, 0xc75e33c740d6c71b, 0x7bb51279cb3c042f}},
+ {{0xe332ced43ba6945a, 0xde0b1361e881c05d, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d}},
+ {{0xc4b6664a3a70159f, 0x76194f0f0a904e14, 0xa5614c39a4096c13, 0x6cd0ff50979feced}}},
+{{{0xc0e067e78f4428ac, 0x14835ab0a61135e3, 0xf21d14f338062935, 0x6390a4c8df04849c}},
+ {{0x7fecfabdb04ba18e, 0xd0fc7bfc3bddbcf7, 0xa41d486e057a131c, 0x641a4391f2223a61}},
+ {{0xc5c6b95aa606a8db, 0x914b7f9eb06825f1, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc}}},
+{{{0x4e3dcbdad1bff7f9, 0xc9118e8220645717, 0xbacccebc0f189d56, 0x1b4822e9d4467668}},
+ {{0x33bef2bd68bcd52c, 0xc649dbb069482ef2, 0xb5b6ee0c41cb1aee, 0x5c294d270212a7e5}},
+ {{0xab360a7f25563781, 0x2512228a480f7958, 0xc75d05276114b4e3, 0x222d9625d976fe2a}}},
+{{{0x1c717f85b372ace1, 0x81930e694638bf18, 0x239cad056bc08b58, 0x0b34271c87f8fff4}},
+ {{0x0f94be7e0a344f85, 0xeb2faa8c87f22c38, 0x9ce1e75e4ee16f0f, 0x43e64e5418a08dea}},
+ {{0x8155e2521a35ce63, 0xbe100d4df912028e, 0xbff80bf8a57ddcec, 0x57342dc96d6bc6e4}}},
+{{{0xefeef065c8ce5998, 0xbf029510b5cbeaa2, 0x8c64a10620b7c458, 0x35134fb231c24855}},
+ {{0xf3c3bcb71e707bf6, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f}},
+ {{0x272c1f46f9a3902b, 0xc91ba3b799657bcc, 0xae614b304f8a1c0e, 0x7afcaad70b99017b}}},
+{{{0xc25ded54a4b8be41, 0x902d13e11bb0e2dd, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb}},
+ {{0xa88141ecef842b6b, 0x55e7b14797abe6c5, 0x8c748f9703784ffe, 0x5b50a1f7afcd00b7}},
+ {{0x9b840f66f1361315, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320}}},
+{{{0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7}},
+ {{0x960e737b6ecb9d17, 0xfaf24948d67ceae1, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb}},
+ {{0x4a89e68b82b7abf0, 0xf41cd9279ba6b7b9, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6}}},
+{{{0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf}},
+ {{0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4}},
+ {{0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2}}},
+{{{0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d}},
+ {{0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1}},
+ {{0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317}}},
+{{{0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4}},
+ {{0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133}},
+ {{0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c}}},
+{{{0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607}},
+ {{0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827}},
+ {{0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae}}},
+{{{0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e}},
+ {{0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd}},
+ {{0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b}}},
+{{{0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314}},
+ {{0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6}},
+ {{0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389}}},
+{{{0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7}},
+ {{0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea}},
+ {{0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1}}},
+{{{0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be}},
+ {{0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69}},
+ {{0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa}}},
+{{{0xdfdacbee4324c0e9, 0x054442883f955bb7, 0xdef7aaa8ea31609f, 0x68aee70642287cff}},
+ {{0xf68fe2e8809de054, 0xe3bc096a9c82bad1, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e}},
+ {{0xf01cc8f17471cc0c, 0x95242e37579082bb, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb}}},
+{{{0xfac5d2065b35b8da, 0xa8da8a9a85624bb7, 0xccd2ca913d21cd0f, 0x6b8341ee8bf90d58}},
+ {{0xbf019cce7aee7a52, 0xa8ded2b6e454ead3, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8}},
+ {{0x3579f26b0282c4b2, 0x64d592f24fafefae, 0xb7cded7b28c8c7c0, 0x6a927b6b7173a8d7}}},
+{{{0x1f6db24f986e4656, 0x1021c02ed1e9105b, 0xf8ff3fff2cc0a375, 0x1d2a6bf8c6c82592}},
+ {{0x8d7040863ece88eb, 0xf0e307a980eec08c, 0xac2250610d788fda, 0x056d92a43a0d478d}},
+ {{0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7}}},
+{{{0x751a50b9d85c0fb8, 0xd1afdc258bcf097b, 0x2f16a6a38309a969, 0x14ddff9ee5b00659}},
+ {{0xd6d70996f12309d6, 0xdbfb2385e9c3d539, 0x46d602b0f7552411, 0x270a0b0557843e0c}},
+ {{0x61ff0640a7862bcc, 0x81cac09a5f11abfe, 0x9047830455d12abb, 0x19a4bde1945ae873}}},
+{{{0x9b9f26f520a6200a, 0x64804443cf13eaf8, 0x8a63673f8631edd3, 0x72bbbce11ed39dc1}},
+ {{0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04}},
+ {{0xae853c94ab66dc47, 0xeb62343edf762d6e, 0xf08e0e186fb2f7d1, 0x4f0b1c02700ab37a}}},
+{{{0xe1706787d81951fa, 0xa10a2c8eb290c77b, 0xe7382fa03ed66773, 0x0a4d84710bcc4b54}},
+ {{0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, 0xc8172ec9d151486b, 0x68abe9443e0a7534}},
+ {{0xda12c6c407831dcb, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef}}},
+{{{0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, 0x954e6727b1244480, 0x7f792f9d2699f331}},
+ {{0xa485ccd539e4ecf2, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f}},
+ {{0x0b886b925fd4d924, 0x60906f7a3626a80d, 0xecd367b4b98abd12, 0x2876beb1def344cf}}},
+{{{0xdc84e93563144691, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3}},
+ {{0xd594b3333a8a85f8, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4}},
+ {{0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, 0x91bfa43411cce67b, 0x5784481964a831e7}}},
+{{{0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690}},
+ {{0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b}},
+ {{0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b}}},
+{{{0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149}},
+ {{0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5}},
+ {{0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f}}},
+{{{0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd}},
+ {{0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668}},
+ {{0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5}}},
+{{{0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd}},
+ {{0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c}},
+ {{0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7}}},
+{{{0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848}},
+ {{0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33}},
+ {{0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51}}},
+{{{0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6}},
+ {{0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37}},
+ {{0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6}}},
+{{{0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788}},
+ {{0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690}},
+ {{0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759}}},
+{{{0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c}},
+ {{0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90}},
+ {{0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a}}},
+{{{0x16faa8fb532f7428, 0xdbd42ea046a4e272, 0x5337653b8b9ea480, 0x4065947223973f03}},
+ {{0xf7c0a19c1a54a044, 0x4a1c5e2477bd9fbb, 0xa6e3ca115af22972, 0x1819bb953f2e9e0d}},
+ {{0x498fbb795e042e84, 0x7d0dd89a7698b714, 0x8bfb0ba427fe6295, 0x36ba82e721200524}}},
+{{{0xd60ecbb74245ec41, 0xfd9be89e34348716, 0xc9240afee42284de, 0x4472f648d0531db4}},
+ {{0xc8d69d0a57274ed5, 0x45ba803260804b17, 0xdf3cda102255dfac, 0x77d221232709b339}},
+ {{0x498a6d7064ad94d8, 0xa5b5c8fd9af62263, 0x8ca8ed0545c141f4, 0x2c63bec3662d358c}}},
+{{{0x7fe60d8bea787955, 0xb9dc117eb5f401b7, 0x91c7c09a19355cce, 0x22692ef59442bedf}},
+ {{0x9a518b3a8586f8bf, 0x9ee71af6cbb196f0, 0xaa0625e6a2385cf2, 0x1deb2176ddd7c8d1}},
+ {{0x8563d19a2066cf6c, 0x401bfd8c4dcc7cd7, 0xd976a6becd0d8f62, 0x67cfd773a278b05e}}},
+{{{0x8dec31faef3ee475, 0x99dbff8a9e22fd92, 0x512d11594e26cab1, 0x0cde561eec4310b9}},
+ {{0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, 0xaa074dddf21d33d3, 0x185cba721bcb9dee}},
+ {{0x93869da3f4e3cb41, 0xbf0392f540f7977e, 0x026204fcd0463b83, 0x3ec91a769eec6eed}}},
+{{{0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, 0xba002ed8c1eaf988, 0x13fedb3e11f33cfc}},
+ {{0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, 0xf745bcc8c5f8eaa6, 0x7a5fa8794a94e896}},
+ {{0x52958faa13cd67a1, 0x965ee0818bdbb517, 0x16e58daa2e8845b3, 0x357d397d5499da8f}}},
+{{{0x1ebfa05fb0bace6c, 0xc934620c1caf9a1e, 0xcc771cc41d82b61a, 0x2d94a16aa5f74fec}},
+ {{0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1}},
+ {{0x6f58cd5d55aff958, 0xba3eaa5c75567721, 0x75c123999165227d, 0x69be1343c2f2b35e}}},
+{{{0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696}},
+ {{0x82bbbdac684b8de3, 0xa2f4c7d03fca0718, 0x337f92fbe096aaa8, 0x200d4d8c63587376}},
+ {{0x208aed4b4893b32b, 0x3efbf23ebe59b964, 0xd762deb0dba5e507, 0x69607bd681bd9d94}}},
+{{{0xf6be021068de1ce1, 0xe8d518e70edcbc1f, 0xe3effdd01b5505a5, 0x35f63353d3ec3fd0}},
+ {{0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, 0xe5ba8ff53a7852a7, 0x28bc77a5838ece00}},
+ {{0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524}}},
+{{{0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582}},
+ {{0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021}},
+ {{0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6}}},
+{{{0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4}},
+ {{0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369}},
+ {{0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4}}},
+{{{0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312}},
+ {{0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e}},
+ {{0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4}}},
+{{{0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc}},
+ {{0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f}},
+ {{0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537}}},
+{{{0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4}},
+ {{0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390}},
+ {{0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f}}},
+{{{0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff}},
+ {{0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f}},
+ {{0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460}}},
+{{{0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74}},
+ {{0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720}},
+ {{0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7}}},
+{{{0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730}},
+ {{0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d}},
+ {{0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5}}},
+{{{0x591e4a5610628564, 0x2a4bb87ca8b4df34, 0xde2a2572e7a38e43, 0x3cbdabd9fee5046e}},
+ {{0x81aebbdd2cd13070, 0x962e4325f85a0e9e, 0xde9391aacadffecb, 0x53177fda52c230e6}},
+ {{0xa7bc970650b9de79, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc}}},
+{{{0xd9354df64131c1bd, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282}},
+ {{0x21c9d9920d591737, 0x9bea41d2e9b46cd6, 0xe20e84200d89bfca, 0x79d99f946eae5ff8}},
+ {{0xf17b483568673205, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599}}},
+{{{0xe8d10190b77a360b, 0x99b983209995e702, 0xbd4fdff8fa0247aa, 0x2772e344e0d36a87}},
+ {{0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b}},
+ {{0xd6863eba37b9e39f, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4}}},
+{{{0x535fd60613037524, 0xe210adf6b0fbc26a, 0xac8d0a9b23e990ae, 0x47204d08d72fdbf9}},
+ {{0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04}},
+ {{0x00f565a9f93267de, 0xcecfd78dc0d58e8a, 0xa215e2dcf318e28e, 0x4599ee919b633352}}},
+{{{0xd3c220ca70e0e76b, 0xb12bea58ea9f3094, 0x294ddec8c3271282, 0x0c3539e1a1d1d028}},
+ {{0xac746d6b861ae579, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de}},
+ {{0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc}}},
+{{{0x9c102fb732a61161, 0xe48e10dd34d520a8, 0x365c63546f9a9176, 0x32f6fe4c046f6006}},
+ {{0x81c29f1bd708ee3f, 0xddcb5a05ae6407d0, 0x97aec1d7d2a3eba7, 0x1590521a91d50831}},
+ {{0x40a3a11ec7910acc, 0x9013dff8f16d27ae, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463}}},
+{{{0xe9d1d950b3d54f9e, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9}},
+ {{0xcf5e6c95cc36747c, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9}},
+ {{0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698}}},
+{{{0xa2b072e95c8c2ace, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3}},
+ {{0xb4f23c425ef83207, 0xabf894d3c9a934b5, 0xd0708c1339fd87f7, 0x1876789117166130}},
+ {{0x925b5ef0670c507c, 0x819bc842b93c33bf, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74}}},
+{{{0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551}},
+ {{0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa}},
+ {{0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693}}},
+{{{0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63}},
+ {{0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352}},
+ {{0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8}}},
+{{{0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36}},
+ {{0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870}},
+ {{0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f}}},
+{{{0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9}},
+ {{0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51}},
+ {{0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec}}},
+{{{0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8}},
+ {{0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde}},
+ {{0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244}}},
+{{{0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a}},
+ {{0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6}},
+ {{0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4}}},
+{{{0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34}},
+ {{0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6}},
+ {{0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1}}},
+{{{0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab}},
+ {{0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81}},
+ {{0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7}}},
+{{{0x9b2a426e3b646025, 0x32127190385ce4cf, 0xa25cffc2dd6dea45, 0x06409010bea8de75}},
+ {{0xd67cded679d34aa0, 0xcc0b9ec0cc4db39f, 0xa535a456e35d190f, 0x2e05d9eaf61f6fef}},
+ {{0xc447901ad61beb59, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26}}},
+{{{0x86809e7007069096, 0xaad75b15e4e50189, 0x07f35715a21a0147, 0x0487f3f112815d5e}},
+ {{0x16c795d6a11ff200, 0xcb70d0e2b15815c9, 0x89f293209b5395b5, 0x50b8c2d031e47b4f}},
+ {{0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b}}},
+{{{0x9c65fcbe1b32ff79, 0xeb75ea9f03b50f9b, 0xfced2a6c6c07e606, 0x35106cd551717908}},
+ {{0xbf05211b27c152d4, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840}},
+ {{0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, 0xfed5ac25d3404f9a, 0x72e82d5e5505c229}}},
+{{{0x6b0b697ff0d844c8, 0xbb12f85cd979cb49, 0xd2a541c6c1da0f1f, 0x7b7c242958ce7211}},
+ {{0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861}},
+ {{0x9f21903f0101689e, 0xd779dfd3bf861005, 0xa122ee5f3deb0f1b, 0x510df84b485a00d4}}},
+{{{0xa54133bb9277a1fa, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a}},
+ {{0x24b3c887c70ac15e, 0xb0f3a557fb81b732, 0x9b2cde2fe578cc1b, 0x4cf7ed0703b54f8e}},
+ {{0x6bd47c6598fbee0f, 0x9e4733e2ab55be2d, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4}}},
+{{{0xda9b6b624b531f20, 0x429a760e77509abb, 0xdbe9f522e823cb80, 0x618f1856880c8f82}},
+ {{0x1833c773e18fe6c0, 0xe3c4711ad3c87265, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8}},
+ {{0x6da6de8f0e399799, 0x7ad61aa440fda178, 0xb32cd8105e3563dd, 0x15f6beae2ae340ae}}},
+{{{0x862bcb0c31ec3a62, 0x810e2b451138f3c2, 0x788ec4b839dac2a4, 0x28f76867ae2a9281}},
+ {{0xba9a0f7b9245e215, 0xf368612dd98c0dbb, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda}},
+ {{0x3e4df9655884e2aa, 0xbd62fbdbdbd465a5, 0xd7596caa0de9e524, 0x6e8042ccb2b1b3d7}}},
+{{{0xf10d3c29ce28ca6e, 0xbad34540fcb6093d, 0xe7426ed7a2ea2d3f, 0x08af9d4e4ff298b9}},
+ {{0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0}},
+ {{0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7}}},
+{{{0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e}},
+ {{0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9}},
+ {{0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7}}},
+{{{0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9}},
+ {{0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0}},
+ {{0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6}}},
+{{{0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3}},
+ {{0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226}},
+ {{0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945}}},
+{{{0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b}},
+ {{0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c}},
+ {{0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832}}},
+{{{0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122}},
+ {{0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce}},
+ {{0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed}}},
+{{{0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a}},
+ {{0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109}},
+ {{0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790}}},
+{{{0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99}},
+ {{0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1}},
+ {{0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb}}},
+{{{0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92}},
+ {{0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08}},
+ {{0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d}}},
+{{{0x0c9c5303f7957be4, 0xa3c31a20e085c145, 0xb0721d71d0850050, 0x0aba390eab0bf2da}},
+ {{0x529fdffe638c7bf3, 0xdf2b9e60388b4995, 0xe027b34f1bad0249, 0x7bc92fc9b9fa74ed}},
+ {{0x9f97ef2e801ad9f9, 0x83697d5479afda3a, 0xe906b3ffbd596b50, 0x02672b37dd3fb8e0}}},
+{{{0x48b2ca8b260885e4, 0xa4286bec82b34c1c, 0x937e1a2617f58f74, 0x741d1fcbab2ca2a5}},
+ {{0xee9ba729398ca7f5, 0xeb9ca6257a4849db, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8}},
+ {{0xbf61423d253fcb17, 0x08803ceafa39eb14, 0xf18602df9851c7af, 0x0400f3a049e3414b}}},
+{{{0xabce0476ba61c55b, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb}},
+ {{0x2efba412a06e7b06, 0x146785452c8d2560, 0xdf9713ebd67a91c7, 0x32830ac7157eadf3}},
+ {{0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820}}},
+{{{0xff35f5cb9e1516f4, 0xee805bcf648aae45, 0xf0d73c2bb93a9ef3, 0x097b0bf22092a6c2}},
+ {{0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16}},
+ {{0xc48bab1521a9d733, 0xa6c2eaead61abb25, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67}}},
+{{{0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e}},
+ {{0xc527deb59c7cb23d, 0x955391695328404e, 0xd64392817ccf2c7a, 0x6ce97dabf7d8fa11}},
+ {{0x25b5a8e50ef7c48f, 0xeb6034116f2ce532, 0xc5e75173e53de537, 0x73119fa08c12bb03}}},
+{{{0xed30129453f1a4cb, 0xbce621c9c8f53787, 0xfacb2b1338bee7b9, 0x3025798a9ea8428c}},
+ {{0x7845b94d21f4774d, 0xbf62f16c7897b727, 0x671857c03c56522b, 0x3cd6a85295621212}},
+ {{0x3fecde923aeca999, 0xbdaa5b0062e8c12f, 0x67b99dfc96988ade, 0x3f52c02852661036}}},
+{{{0xffeaa48e2a1351c6, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59}},
+ {{0x9258bf99eec416c6, 0xac8a5017a9d2f671, 0x629549ab16dea4ab, 0x05d0e85c99091569}},
+ {{0x051de020de9cbe97, 0xfa07fc56b50bcf74, 0x378cec9f0f11df65, 0x36853c69ab96de4d}}},
+{{{0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b}},
+ {{0x4433c0b0fac5e7be, 0x724bae854c08dcbe, 0xf1f24cc446978f9b, 0x4a0aff6d62825fc8}},
+ {{0xe917fb9e61095301, 0xc102df9402a092f8, 0xbf09e2f5fa66190b, 0x681109bee0dcfe37}}},
+{{{0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d}},
+ {{0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4}},
+ {{0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069}}},
+{{{0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f}},
+ {{0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019}},
+ {{0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012}}},
+{{{0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae}},
+ {{0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6}},
+ {{0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb}}},
+{{{0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877}},
+ {{0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c}},
+ {{0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b}}},
+{{{0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364}},
+ {{0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5}},
+ {{0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1}}},
+{{{0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9}},
+ {{0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554}},
+ {{0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3}}},
+{{{0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485}},
+ {{0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc}},
+ {{0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a}}},
+{{{0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4}},
+ {{0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d}},
+ {{0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c}}},
+{{{0x53175a7205d21a77, 0xb0c04422d3b934d4, 0xadd9f24bdd5deadc, 0x074f46e69f10ff8c}},
+ {{0x0de9b204a059a445, 0xe15cb4aa4b17ad0f, 0xe1bbec521f79c557, 0x2633f1b9d071081b}},
+ {{0xc1fb4177018b9910, 0xa6ea20dc6c0fe140, 0xd661f3e74354c6ff, 0x5ecb72e6f1a3407a}}},
+{{{0xa515a31b2259fb4e, 0x0960f3972bcac52f, 0xedb52fec8d3454cb, 0x382e2720c476c019}},
+ {{0xfeeae106e8e86997, 0x9863337f98d09383, 0x9470480eaa06ebef, 0x038b6898d4c5c2d0}},
+ {{0xf391c51d8ace50a6, 0x3142d0b9ae2d2948, 0xdb4d5a1a7f24ca80, 0x21aeba8b59250ea8}}},
+{{{0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d}},
+ {{0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed}},
+ {{0x17e49c17cc947f3d, 0xccc6eda6aac1d27b, 0xdf6092ceb0f08e56, 0x4909b3e22c67c36b}}},
+{{{0x9c9c85ea63fe2e89, 0xbe1baf910e9412ec, 0x8f7baa8a86fbfe7b, 0x0fb17f9fef968b6c}},
+ {{0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68}},
+ {{0x79d5c62eafc3902b, 0x773a215289e80728, 0xc38ae640e10120b9, 0x09ae23717b2b1a6d}}},
+{{{0xbb6a192a4e4d083c, 0x34ace0630029e192, 0x98245a59aafabaeb, 0x6d9c8a9ada97faac}},
+ {{0x10ab8fa1ad32b1d0, 0xe9aced1be2778b24, 0xa8856bc0373de90f, 0x66f35ddddda53996}},
+ {{0xd27d9afb24997323, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8}}},
+{{{0x04a186b5565345cd, 0xeee76610bcc4116a, 0x689c73b478fb2a45, 0x387dcbff65697512}},
+ {{0xaf09b214e6b3dc6b, 0x3f7573b5ad7d2f65, 0xd019d988100a23b0, 0x392b63a58b5c35f7}},
+ {{0x4093addc9c07c205, 0xc565be15f532c37e, 0x63dbecfd1583402a, 0x61722b4aef2e032e}}},
+{{{0x0012aafeecbd47af, 0x55a266fb1cd46309, 0xf203eb680967c72c, 0x39633944ca3c1429}},
+ {{0xd6b07a5581cb0e3c, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59}},
+ {{0x8d0cb88c1b37cfe1, 0x05b6a5a3053818f3, 0xf2e9bc04b787d959, 0x6beba1249add7f64}}},
+{{{0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5}},
+ {{0x5c3cecb943f5a53b, 0x9cc9a61d06c08df2, 0xcfba639a85895447, 0x5a845ae80df09fd5}},
+ {{0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, 0xc43eced4a169d097, 0x0a1249fff7e587c3}}},
+{{{0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792}},
+ {{0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c}},
+ {{0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319}}},
+{{{0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266}},
+ {{0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13}},
+ {{0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e}}},
+{{{0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868}},
+ {{0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9}},
+ {{0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe}}},
+{{{0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd}},
+ {{0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241}},
+ {{0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463}}},
+{{{0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b}},
+ {{0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280}},
+ {{0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a}}},
+{{{0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac}},
+ {{0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67}},
+ {{0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99}}},
+{{{0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9}},
+ {{0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b}},
+ {{0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db}}},
+{{{0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf}},
+ {{0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf}},
+ {{0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859}}},
+{{{0x88bd438cd11e0d4a, 0x30cb610d43ccf308, 0xe09a0e3791937bcc, 0x4559135b25b1720c}},
+ {{0x1ea436837c6da1e9, 0xf9c189af1fb9bdbe, 0x303001fcce5dd155, 0x28a7c99ebc57be52}},
+ {{0xb8fd9399e8d19e9d, 0x908191cb962423ff, 0xb2b948d747c742a3, 0x37f33226d7fb44c4}}},
+{{{0x0dae8767b55f6e08, 0x4a43b3b35b203a02, 0xe3725a6e80af8c79, 0x0f7a7fd1705fa7a3}},
+ {{0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f}},
+ {{0x8eeb5d076eb55ce0, 0x2fc536bfaa0d925a, 0xbe81830fdcb6c6e8, 0x556c7045827baf52}}},
+{{{0x8e2b517302e9d8b7, 0xe3e52269248714e8, 0xbd4fbd774ca960b5, 0x6f4b4199c5ecada9}},
+ {{0xb94b90022bf44406, 0xabd4237eff90b534, 0x7600a960faf86d3a, 0x2f45abdac2322ee3}},
+ {{0x61af4912c8ef8a6a, 0xe58fa4fe43fb6e5e, 0xb5afcc5d6fd427cf, 0x6a5393281e1e11eb}}},
+{{{0xf3da5139a5d1ee89, 0x8145457cff936988, 0x3f622fed00e188c4, 0x0f513815db8b5a3d}},
+ {{0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d}},
+ {{0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2}}},
+{{{0xcfb68265fd0e75f6, 0xe45b3e28bb90e707, 0x7242a8de9ff92c7a, 0x685b3201933202dd}},
+ {{0x81886a92294ac9e8, 0x23162b45d55547be, 0x94cfbc4403715983, 0x50eb8fdb134bc401}},
+ {{0xc0b73ec6d6b330cd, 0x84e44807132faff1, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2}}},
+{{{0xaf3b46bf7a4aafa2, 0xb78705ec4d40d411, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d}},
+ {{0x33d1013e9b73a562, 0x925cef5748ec26e1, 0xa7fce614dd468058, 0x78b0fad41e9aa438}},
+ {{0xbf56a431ed05b488, 0xa533e66c9c495c7e, 0xe8652baf87f3651a, 0x0241800059d66c33}}},
+{{{0xceb077fea37a5be4, 0xdb642f02e5a5eeb7, 0xc2e6d0c5471270b8, 0x4771b65538e4529c}},
+ {{0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, 0xace7cfbe857082f7, 0x4d2845aba2d9a1e0}},
+ {{0xbb537fe0447070de, 0xcba744436dd557df, 0xd3b5a3473600dbcb, 0x4aeabbe6f9ffd7f8}}},
+{{{0x4630119e40d8f78c, 0xa01a9bc53c710e11, 0x486d2b258910dd79, 0x1e6c47b3db0324e5}},
+ {{0x6a2134bcc4a9c8f2, 0xfbf8fd1c8ace2e37, 0x000ae3049911a0ba, 0x046e3a616bc89b9e}},
+ {{0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c}}},
+{{{0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6}},
+ {{0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095}},
+ {{0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1}}},
+{{{0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f}},
+ {{0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99}},
+ {{0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e}}},
+{{{0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4}},
+ {{0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0}},
+ {{0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c}}},
+{{{0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c}},
+ {{0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3}},
+ {{0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d}}},
+{{{0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca}},
+ {{0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24}},
+ {{0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34}}},
+{{{0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354}},
+ {{0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e}},
+ {{0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075}}},
+{{{0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993}},
+ {{0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d}},
+ {{0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe}}},
+{{{0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68}},
+ {{0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95}},
+ {{0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d}}},
+{{{0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, 0xba4190e2c3c7e084, 0x0e545daea51874d9}},
+ {{0x957b8b8b0df53c30, 0x2a1c770a8e60f098, 0xbbc7a670345796de, 0x22a48f9a90c99bc9}},
+ {{0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136}}},
+{{{0x20ad660839e31e32, 0xf81e1bd58405be50, 0xf8064056f4dabc69, 0x14d23dd4ce71b975}},
+ {{0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1}},
+ {{0xf2398e098aa27f82, 0x6d7982bb89a1b024, 0xfa694084214dd24c, 0x71ab966fa32301c3}}},
+{{{0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, 0xbca255434e0328da, 0x35768fbe92411b22}},
+ {{0xb1088a0702809955, 0x43b273ea0b43c391, 0xca9b67aefe0686ed, 0x605eecbf8335f4ed}},
+ {{0x83200a656c340431, 0x9fcd71678ee59c2f, 0x75d4613f71300f8a, 0x7a912faf60f542f9}}},
+{{{0xb204585e5edc1a43, 0x9f0e16ee5897c73c, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be}},
+ {{0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a}},
+ {{0x597028047f116909, 0x828ac41c1e564467, 0x70417dbde6217387, 0x721627aefbac4384}}},
+{{{0x97d03bc38736add5, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7}},
+ {{0xfd3097bc410b2f22, 0xf1a05da7b5cfa844, 0x61289a1def57ca74, 0x245ea199bb821902}},
+ {{0xaedca66978d477f8, 0x1898ba3c29117fe1, 0xcf73f983720cbd58, 0x67da12e6b8b56351}}},
+{{{0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, 0x93c6aa2f38c85a30, 0x76297d1f3d75a78a}},
+ {{0x2b7ef3d38ec8308c, 0x828fd7ec71eb94ab, 0x807c3b36c5062abd, 0x0cb64cb831a94141}},
+ {{0x3030fc33534c6378, 0xb9635c5ce541e861, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb}}},
+{{{0x629398fa8dbffc3a, 0xe12fe52dd54db455, 0xf3be11dfdaf25295, 0x628b140dce5e7b51}},
+ {{0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, 0xceb345941adf4d62, 0x6987ff6f542de50c}},
+ {{0x47e241428f83753c, 0x6317bebc866af997, 0xdabb5b433d1a9829, 0x074d8d245287fb2d}}},
+{{{0x8337d9cd440bfc31, 0x729d2ca1af318fd7, 0xa040a4a4772c2070, 0x46002ef03a7349be}},
+ {{0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9}},
+ {{0xfaa23adeaffe65f7, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395}}},
+{{{0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c}},
+ {{0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060}},
+ {{0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72}}},
+{{{0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b}},
+ {{0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df}},
+ {{0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb}}},
+{{{0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03}},
+ {{0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64}},
+ {{0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa}}},
+{{{0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01}},
+ {{0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613}},
+ {{0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb}}},
+{{{0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c}},
+ {{0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8}},
+ {{0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75}}},
+{{{0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded}},
+ {{0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13}},
+ {{0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6}}},
+{{{0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d}},
+ {{0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b}},
+ {{0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7}}},
+{{{0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73}},
+ {{0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf}},
+ {{0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a}}},
+{{{0xb5a2d50c7ec20d3e, 0xc64bdd6ea0c97263, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba}},
+ {{0x358ecba293a36247, 0xaf8f9862b268fd65, 0x412f7e9968a01c89, 0x5786f312cd754524}},
+ {{0x337788ffca14032c, 0xf3921028447f1ee3, 0x8b14071f231bccad, 0x4c817b4bf2344783}}},
+{{{0x0ff853852871b96e, 0xe13e9fab60c3f1bb, 0xeefd595325344402, 0x0a37c37075b7744b}},
+ {{0x413ba057a40b4484, 0xba4c2e1a4f5f6a43, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53}},
+ {{0x6cbdf1703ad0562b, 0x8ecf4830c92521a3, 0xdaebd303fd8424e7, 0x72ad82a42e5ec56f}}},
+{{{0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d}},
+ {{0xc368939167024bc3, 0x8e69d16d49502fda, 0xfcf2ec3ce45f4b29, 0x065f669ea3b4cbc4}},
+ {{0x8a00aec75532db4d, 0xb869a4e443e31bb1, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08}}},
+{{{0xc720cb6153ead9a3, 0x55b2c97f512b636e, 0xb1e35b5fd40290b1, 0x2fd9ccf13b530ee2}},
+ {{0x9d05ba7d43c31794, 0x2470c8ff93322526, 0x8323dec816197438, 0x2852709881569b53}},
+ {{0x07bd475b47f796b8, 0xd2c7b013542c8f54, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6}}},
+{{{0x4546baaf54aac27f, 0xf6f66fecb2a45a28, 0x582d1b5b562bcfe8, 0x44b123f3920f785f}},
+ {{0x68a24ce3a1d5c9ac, 0xbb77a33d10ff6461, 0x0f86ce4425d3166e, 0x56507c0950b9623b}},
+ {{0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3}}},
+{{{0xc6b5967b5598a074, 0x5efe91ce8e493e25, 0xd4b72c4549280888, 0x20ef1149a26740c2}},
+ {{0x3cd7bc61e7ce4594, 0xcd6b35a9b7dd267e, 0xa080abc84366ef27, 0x6ec7c46f59c79711}},
+ {{0x2f07ad636f09a8a2, 0x8697e6ce24205e7d, 0xc0aefc05ee35a139, 0x15e80958b5f9d897}}},
+{{{0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, 0xc774e1342dc5c327, 0x021354b892021f39}},
+ {{0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443}},
+ {{0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, 0xb323d9f2cda390a7, 0x7be0847b8774d363}}},
+{{{0x8c99cc5a8b3f55c3, 0x0611d7253fded2a0, 0xed2995ff36b70a36, 0x1f699a54d78a2619}},
+ {{0x1466f5af5307fa11, 0x817fcc7ded6c0af2, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b}},
+ {{0xe77292f373e7ea8a, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966}}},
+{{{0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d}},
+ {{0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d}},
+ {{0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0}}},
+{{{0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956}},
+ {{0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba}},
+ {{0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1}}},
+{{{0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a}},
+ {{0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5}},
+ {{0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4}}},
+{{{0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5}},
+ {{0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75}},
+ {{0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3}}},
+{{{0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1}},
+ {{0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026}},
+ {{0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066}}},
+{{{0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7}},
+ {{0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2}},
+ {{0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568}}},
+{{{0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5}},
+ {{0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5}},
+ {{0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26}}},
+{{{0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f}},
+ {{0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223}},
+ {{0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb}}},
+{{{0xf19aeac733a63aef, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5}},
+ {{0x852dd1fd3d578bbe, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40}},
+ {{0xa7ab69798d496476, 0x8121aadefcb5abc8, 0xa5dc12ef7b539472, 0x07fd47065e45351a}}},
+{{{0xc8583c3d258d2bcd, 0x17029a4daf60b73f, 0xfa0fc9d6416a3781, 0x1c1e5fba38b3fb23}},
+ {{0x304211559ae8e7c3, 0xf281b229944882a5, 0x8a13ac2e378250e4, 0x014afa0954ba48f4}},
+ {{0xcb3197001bb3666c, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364}}},
+{{{0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5}},
+ {{0xfb9d37c3bc1ab6eb, 0x02be14534d57a240, 0xf4d73415f8a5e1f6, 0x5964f4300ccc8188}},
+ {{0xe44a23152d096800, 0x5c08c55970866996, 0xdf2db60a46affb6e, 0x579155c1f856fd89}}},
+{{{0x96324edd12e0c9ef, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a}},
+ {{0xb5f16b630817e7a6, 0x808c69233c351026, 0x324a983b54cef201, 0x53c092084a485345}},
+ {{0xd2d41481f1cbafbf, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6}}},
+{{{0xe48f535e3ed15433, 0xd075692a0d7270a3, 0x40fbd21daade6387, 0x14264887cf4495f5}},
+ {{0xab39f3ef61bb3a3f, 0x8eb400652eb9193e, 0xb5de6ecc38c11f74, 0x654d7e9626f3c49f}},
+ {{0xe564cfdd5c7d2ceb, 0x82eeafded737ccb9, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb}}},
+{{{0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501}},
+ {{0x204abad63700a93b, 0xbe0023d3da779373, 0xd85f0346633ab709, 0x00496dc490820412}},
+ {{0x1c74b88dc27e6360, 0x074854268d14850c, 0xa145fb7b3e0dcb30, 0x10843f1b43803b23}}},
+{{{0xc5f90455376276dd, 0xce59158dd7645cd9, 0x92f65d511d366b39, 0x11574b6e526996c4}},
+ {{0xd56f672de324689b, 0xd1da8aedb394a981, 0xdd7b58fe9168cfed, 0x7ce246cd4d56c1e8}},
+ {{0xb8f4308e7f80be53, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671}}},
+{{{0x73f93d36101b95eb, 0xfaef33794f6f4486, 0x5651735f8f15e562, 0x7fa3f19058b40da1}},
+ {{0xa03fc862059d699e, 0x2370cfa19a619e69, 0xc4fe3b122f823deb, 0x1d1b056fa7f0844e}},
+ {{0x1bc64631e56bf61f, 0xd379ab106e5382a3, 0x4d58c57e0540168d, 0x566256628442d8e4}}},
+{{{0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006}},
+ {{0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231}},
+ {{0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc}}},
+{{{0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da}},
+ {{0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd}},
+ {{0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2}}},
+{{{0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace}},
+ {{0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e}},
+ {{0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f}}},
+{{{0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca}},
+ {{0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd}},
+ {{0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f}}},
+{{{0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6}},
+ {{0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616}},
+ {{0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d}}},
+{{{0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831}},
+ {{0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4}},
+ {{0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214}}},
+{{{0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6}},
+ {{0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde}},
+ {{0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e}}},
+{{{0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd}},
+ {{0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074}},
+ {{0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b}}},
+{{{0x9f65c5ea200814cf, 0x840536e169a31740, 0x8b0ed13925c8b4ad, 0x0080dbafe936361d}},
+ {{0x8ce5aad0c9cb971f, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa}},
+ {{0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71}}},
+{{{0x899dea51abf3ff5f, 0x9b93a8672fc2d8ba, 0x2c38cb97be6ebd5c, 0x114d578497263b5d}},
+ {{0x58e84c6f20816247, 0x8db2b2b6e36fd793, 0x977182561d484d85, 0x0822024f8632abd7}},
+ {{0xb301bb7c6b1beca3, 0x55393f6dc6eb1375, 0x910d281097b6e4eb, 0x1ad4548d9d479ea3}}},
+{{{0xcd5a7da0389a48fd, 0xb38fa4aa9a78371e, 0xc6d9761b2cdb8e6c, 0x35cf51dbc97e1443}},
+ {{0xa06fe66d0fe9fed3, 0xa8733a401c587909, 0x30d14d800df98953, 0x41ce5876c7b30258}},
+ {{0x59ac3bc5d670c022, 0xeae67c109b119406, 0x9798bdf0b3782fda, 0x651e3201fd074092}}},
+{{{0xd63d8483ef30c5cf, 0x4cd4b4962361cc0c, 0xee90e500a48426ac, 0x0af51d7d18c14eeb}},
+ {{0xa57ba4a01efcae9e, 0x769f4beedc308a94, 0xd1f10eeb3603cb2e, 0x4099ce5e7e441278}},
+ {{0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, 0x8320aa0dd6430df9, 0x667282652c4a2fb5}}},
+{{{0x874621f4d86bc9ab, 0xb54c7bbe56fe6fea, 0x077a24257fadc22c, 0x1ab53be419b90d39}},
+ {{0xada8b6e02946db23, 0x1c0ce51a7b253ab7, 0x8448c85a66dd485b, 0x7f1fc025d0675adf}},
+ {{0xd8ee1b18319ea6aa, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14}}},
+{{{0x8ce7b23bb99c0755, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1}},
+ {{0xd95b00bbcbb77c68, 0xddbc846a91f17849, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e}},
+ {{0x31b6972d98b0bde8, 0x7d920706aca6de5b, 0xe67310f8908a659f, 0x50fac2a6efdf0235}}},
+{{{0xf3d3a9f35b880f5a, 0xedec050cdb03e7c2, 0xa896981ff9f0b1a2, 0x49a4ae2bac5e34a4}},
+ {{0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, 0xc001cb30aa8e551d, 0x6a28d35944f43662}},
+ {{0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b}}},
+{{{0xa311ddc26b89792d, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408}},
+ {{0x8e793a7acc36e6e0, 0xf9fab7a37d586eed, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e}},
+ {{0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493}}},
+{{{0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3}},
+ {{0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab}},
+ {{0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b}}},
+{{{0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434}},
+ {{0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c}},
+ {{0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be}}},
+{{{0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57}},
+ {{0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36}},
+ {{0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179}}},
+{{{0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661}},
+ {{0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3}},
+ {{0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f}}},
+{{{0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562}},
+ {{0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037}},
+ {{0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e}}},
+{{{0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc}},
+ {{0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7}},
+ {{0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a}}},
+{{{0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372}},
+ {{0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e}},
+ {{0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97}}},
+{{{0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4}},
+ {{0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6}},
+ {{0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867}}},
+{{{0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, 0x8d5cfe45b941a8a4, 0x44c218671c974287}},
+ {{0x745f9d56296bc318, 0x993580d4d8152e65, 0xb0e5b13f5839e9ce, 0x51fc2b28d43921c0}},
+ {{0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6}}},
+{{{0xdff25fce4b1de151, 0xd841c0c7e11c4025, 0x2554b3c854749c87, 0x2d292459908e0df9}},
+ {{0x6b7c5f10f80cb088, 0x736b54dc56e42151, 0xc2b620a5c6ef99c4, 0x5f4c802cc3a06f42}},
+ {{0x9b65c8f17d0752da, 0x881ce338c77ee800, 0xc3b514f05b62f9e3, 0x66ed5dd5bec10d48}}},
+{{{0x7d38a1c20bb2089d, 0x808334e196ccd412, 0xc4a70b8c6c97d313, 0x2eacf8bc03007f20}},
+ {{0xf0adf3c9cbca047d, 0x81c3b2cbf4552f6b, 0xcfda112d44735f93, 0x1f23a0c77e20048c}},
+ {{0xf235467be5bc1570, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50}}},
+{{{0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276}},
+ {{0xcd54e06b7f37e4eb, 0x8cc15f87f5e96cca, 0xb8248bb0d3597dce, 0x246affa06074400c}},
+ {{0x37d88e68fbe45321, 0x86097548c0d75032, 0x4e9b13ef894a0d35, 0x25a83cac5753d325}}},
+{{{0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630}},
+ {{0x9f0f66293952b6e2, 0x33db5e0e0934267b, 0xff45252bd609fedc, 0x06be10f5c506e0c9}},
+ {{0x1a9615a9b62a345f, 0x22050c564a52fecc, 0xa7a2788528bc0dfe, 0x5e82770a1a1ee71d}}},
+{{{0x35425183ad896a5c, 0xe8673afbe78d52f6, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102}},
+ {{0xe802e80a42339c74, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee}},
+ {{0xfd2d5d35197dbe6e, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e}}},
+{{{0xd036b9bbd16dfde2, 0xa2055757c497a829, 0x8e6cc966a7f12667, 0x4d3b1a791239c180}},
+ {{0xecd27d017e2a076a, 0xd788689f1636495e, 0x52a61af0919233e5, 0x2a479df17bb1ae64}},
+ {{0x9e5eee8e33db2710, 0x189854ded6c43ca5, 0xa41c22c592718138, 0x27ad5538a43a5e9b}}},
+{{{0x2746dd4b15350d61, 0xd03fcbc8ee9521b7, 0xe86e365a138672ca, 0x510e987f7e7d89e2}},
+ {{0xcb5a7d638e47077c, 0x8db7536120a1c059, 0x549e1e4d8bedfdcc, 0x080153b7503b179d}},
+ {{0xdda69d930a3ed3e3, 0x3d386ef1cd60a722, 0xc817ad58bdaa4ee6, 0x23be8d554fe7372a}}},
+{{{0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797}},
+ {{0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001}},
+ {{0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293}}},
+{{{0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec}},
+ {{0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f}},
+ {{0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c}}},
+{{{0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07}},
+ {{0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332}},
+ {{0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217}}},
+{{{0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714}},
+ {{0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0}},
+ {{0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e}}},
+{{{0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13}},
+ {{0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e}},
+ {{0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0}}},
+{{{0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade}},
+ {{0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940}},
+ {{0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db}}},
+{{{0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57}},
+ {{0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8}},
+ {{0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408}}},
+{{{0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be}},
+ {{0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98}},
+ {{0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c}}},
+{{{0x3f50a50a4ffb81ef, 0xb1e035093bf420bf, 0x9baa8e1cc6aa2cd0, 0x32239861fa237a40}},
+ {{0xfb735ac2004a35d1, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c}},
+ {{0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd}}},
+{{{0x8451f9e05e4e89dd, 0xc06302ffbc793937, 0x5d22749556a6495c, 0x09a6755ca05603fb}},
+ {{0xf1d3b681a05071b9, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e}},
+ {{0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0}}},
+{{{0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6}},
+ {{0x69ee9e7f9b02805c, 0xcbff828a547d1640, 0x3d93a869b2430968, 0x46b7b8cd3fe26972}},
+ {{0xe9812086fe7eebe0, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9}}},
+{{{0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b}},
+ {{0x6f2b3be4d5d3b002, 0xafec33d96a09c880, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b}},
+ {{0xcb58c8fe433d8939, 0x89a0cb2e6a8d7e50, 0x79ca955309fbbe5a, 0x0c626616cd7fc106}}},
+{{{0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788}},
+ {{0x8fdfc379fbf454b1, 0x45a5a970f1a4b771, 0xac921ef7bad35915, 0x42d088dca81c2192}},
+ {{0x8fda0f37a0165199, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7}}},
+{{{0xc2ddf1deb36202ac, 0x92a5fe09d2e27aa5, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959}},
+ {{0x982d6e1a02c0412f, 0x90fa4c83db58e8fe, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66}},
+ {{0x1fadbadba54395a7, 0xb41a02a0ae0da66a, 0xbf19f598bba37c07, 0x6a12b8acde48430d}}},
+{{{0xf8daea1f39d495d9, 0x592c190e525f1dfc, 0xdb8cbd04c9991d1b, 0x11f7fda3d88f0cb7}},
+ {{0x793bdd801aaeeb5f, 0x00a2a0aac1518871, 0xe8a373a31f2136b4, 0x48aab888fc91ef19}},
+ {{0x041f7e925830f40e, 0x002d6ca979661c06, 0x86dc9ff92b046a2e, 0x760360928b0493d1}}},
+{{{0x21bb41c6120cf9c6, 0xeab2aa12decda59b, 0xc1a72d020aa48b34, 0x215d4d27e87d3b68}},
+ {{0xb43108e5695a0b05, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224}},
+ {{0xc8b247b65bcaf19c, 0x49779dc3b1b2c652, 0x89a180bbd5ece2e2, 0x13f098a3cec8e039}}},
+{{{0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b}},
+ {{0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9}},
+ {{0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09}}},
+{{{0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5}},
+ {{0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc}},
+ {{0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc}}},
+{{{0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147}},
+ {{0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834}},
+ {{0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2}}},
+{{{0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd}},
+ {{0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65}},
+ {{0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469}}},
+{{{0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57}},
+ {{0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2}},
+ {{0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63}}},
+{{{0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7}},
+ {{0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0}},
+ {{0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73}}},
+{{{0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87}},
+ {{0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f}},
+ {{0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65}}},
+{{{0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8}},
+ {{0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620}},
+ {{0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99}}},
+{{{0x738b38d787ce8f89, 0xb62658e24179a88d, 0x30738c9cf151316d, 0x49128c7f727275c9}},
+ {{0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, 0xc6409d99f53eabc6, 0x606175f6332e25d2}},
+ {{0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235}}},
+{{{0x96cd5640df90f3e7, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58}},
+ {{0x1da1965774049e9d, 0xfbcd6ea198fe352b, 0xb1cbcd50cc5236a6, 0x1f5ec83d3f9846e2}},
+ {{0x8efb23c3328ccb75, 0xaf42a207dd876ee9, 0x20fbdadc5dfae796, 0x241e246b06bf9f51}}},
+{{{0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097}},
+ {{0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee}},
+ {{0xe8d5dc9fa96bad93, 0xe58fb17dde1947dc, 0x681532ea65185fa3, 0x1fdd6c3b034a7830}}},
+{{{0x0a64e28c55dc18fe, 0xe3df9e993399ebdd, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e}},
+ {{0x9c13a6a52dd8f7a9, 0x2dbb1f8c3efdcabf, 0x961e32405e08f7b5, 0x48c8a121bbe6c9e5}},
+ {{0xfc415a7c59646445, 0xd224b2d7c128b615, 0x6035c9c905fbb912, 0x42d7a91274429fab}}},
+{{{0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, 0xff547cde6eb508cb, 0x6fed19dd10fcb532}},
+ {{0xa9a48947933da5bc, 0x4a58920ec2e979ec, 0x96d8800013e5ac4c, 0x453692d74b48b147}},
+ {{0xdd775d99a8559c6f, 0xf42a2140df003e24, 0x5223e229da928a66, 0x063f46ba6d38f22c}}},
+{{{0xd2d242895f536694, 0xca33a2c542939b2c, 0x986fada6c7ddb95c, 0x5a152c042f712d5d}},
+ {{0x39843cb737346921, 0xa747fb0738c89447, 0xcb8d8031a245307e, 0x67810f8e6d82f068}},
+ {{0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403}}},
+{{{0x857942f46c3cbe8e, 0xa1d364b14730c046, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2}},
+ {{0xad23f6dae82354cb, 0x6962502ab6571a6d, 0x9b651636e38e37d1, 0x5cac5005d1a3312f}},
+ {{0x8cc154cce9e39904, 0x5b3a040b84de6846, 0xc4d8a61cb1be5d6e, 0x40fb897bd8861f02}}},
+{{{0x84c5aa9062de37a1, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da}},
+ {{0xe57ed8475ab10761, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b}},
+ {{0xd1c101d50b813381, 0xdee60f1176ee6828, 0x0cb68893383f6409, 0x6183c565f6ff484a}}},
+{{{0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff}},
+ {{0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85}},
+ {{0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15}}},
+{{{0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33}},
+ {{0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5}},
+ {{0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44}}},
+{{{0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090}},
+ {{0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438}},
+ {{0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955}}},
+{{{0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f}},
+ {{0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe}},
+ {{0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50}}},
+{{{0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13}},
+ {{0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577}},
+ {{0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907}}},
+{{{0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa}},
+ {{0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a}},
+ {{0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea}}},
+{{{0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1}},
+ {{0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128}},
+ {{0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4}}},
+{{{0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a}},
+ {{0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1}},
+ {{0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664}}},
+{{{0xcbb5b5556c032bff, 0xdf7191b729297a3a, 0xc1ff7326aded81bb, 0x71ade8bb68be03f5}},
+ {{0x1e6284c5806b467c, 0xc5f6997be75d607b, 0x8b67d958b378d262, 0x3d88d66a81cd8b70}},
+ {{0x8b767a93204ed789, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3}}},
+{{{0xe05da1a7e1f5bf49, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd}},
+ {{0xfce219072a7b31b4, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb}},
+ {{0x22b1a58ae9b08183, 0xfd95d071c15c388b, 0xa9812376850a0517, 0x33384cbabb7f335e}}},
+{{{0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, 0xeb53349c5431d6de, 0x5278b38f6b879c89}},
+ {{0x33bc627a26218b8d, 0xea80b21fc7a80c61, 0x9458b12b173e9ee6, 0x076247be0e2f3059}},
+ {{0x52e105f61416375a, 0xec97af3685abeba4, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01}}},
+{{{0xf6c968731ae8cab4, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7}},
+ {{0xbeaece313db342a8, 0xcba3635b842db7ee, 0xe88c6620817f13ef, 0x1b9438aa4e76d5c6}},
+ {{0x8a50777e166f031a, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905}}},
+{{{0x42c1192927f6bdcf, 0x8f91917a403d61ca, 0xdc1c5a668b9e1f61, 0x1596047804ec0f8d}},
+ {{0xecdfc35b48cade41, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29}},
+ {{0xda96bbb3aced37ac, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f}}},
+{{{0x09dcbf4341c30318, 0xeeba061183181dce, 0xc179c0cedc1e29a1, 0x1dbf7b89073f35b0}},
+ {{0xcfed9cdf1b31b964, 0xf486a9858ca51af3, 0x14897265ea8c1f84, 0x784a53dd932acc00}},
+ {{0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, 0xa4132cbbe5cf0003, 0x3f93d82354f000ea}}},
+{{{0x8183e7689e04ce85, 0x678fb71e04465341, 0xad92058f6688edac, 0x5da350d3532b099a}},
+ {{0xeaac12d179e14978, 0xff923ff3bbebff5e, 0x4af663e40663ce27, 0x0fd381a811a5f5ff}},
+ {{0xf256aceca436df54, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50}}},
+{{{0xaea8b07fa902030f, 0xf88c766af463d143, 0x15b083663c787a60, 0x08eab1148267a4a8}},
+ {{0xbdc1409bd002d0ac, 0x66660245b5ccd9a6, 0x82317dc4fade85ec, 0x02fe934b6ad7df0d}},
+ {{0xef5cf100cfb7ea74, 0x22897633a1cb42ac, 0xd4ce0c54cef285e2, 0x30408c048a146a55}}},
+{{{0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e}},
+ {{0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a}},
+ {{0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835}}},
+{{{0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09}},
+ {{0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6}},
+ {{0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d}}},
+{{{0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0}},
+ {{0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e}},
+ {{0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1}}},
+{{{0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda}},
+ {{0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138}},
+ {{0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c}}},
+{{{0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c}},
+ {{0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9}},
+ {{0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293}}},
+{{{0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b}},
+ {{0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d}},
+ {{0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c}}},
+{{{0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0}},
+ {{0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03}},
+ {{0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae}}},
+{{{0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a}},
+ {{0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838}},
+ {{0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0}}},
+{{{0xe9dcd756b637ff2d, 0xec4c348fc987f0c4, 0xced59285f3fbc7b7, 0x3305354793e1ea87}},
+ {{0x01c18980c5fe9f94, 0xcd656769716fd5c8, 0x816045c3d195a086, 0x6e2b7f3266cc7982}},
+ {{0xcc802468f7c3568f, 0x9de9ba8219974cb3, 0xabb7229cb5b81360, 0x44e2017a6fbeba62}}},
+{{{0xc4c2a74354dab774, 0x8e5d4c3c4eaf031a, 0xb76c23d242838f17, 0x749a098f68dce4ea}},
+ {{0x87f82cf3b6ca6ecd, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d}},
+ {{0xdcdfe0a02cc1de60, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606}}},
+{{{0xa52a92fea4747fb5, 0xdc12a4491fa5ab89, 0xd82da94bb847a4ce, 0x4d77edce9512cc4e}},
+ {{0xd111d17caf4feb6e, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75}},
+ {{0x77c8e14577e2189c, 0xa3e46f6aff99c445, 0x3144dfc86d335343, 0x3a96559e7c4216a9}}},
+{{{0x12550d37f42ad2ee, 0x8b78e00498a1fbf5, 0x5d53078233894cb2, 0x02c84e4e3e498d0c}},
+ {{0x4493896880baaa52, 0x4c98afc4f285940e, 0xef4aa79ba45448b6, 0x5278c510a57aae7f}},
+ {{0xa54dd074294c0b94, 0xf55d46b8df18ffb6, 0xf06fecc58dae8366, 0x588657668190d165}}},
+{{{0xd47712311aef7117, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9}},
+ {{0xbf5834f03de25cc3, 0xb887c8aed6815496, 0x5105221a9481e892, 0x6760ed19f7723f93}},
+ {{0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7}}},
+{{{0x3318be7775c52d82, 0x4cb764b554d0aab9, 0xabcf3d27cc773d91, 0x3bf4d1848123288a}},
+ {{0xb1d534b0cc7505e1, 0x32cd003416c35288, 0xcb36a5800762c29d, 0x5bfe69b9237a0bf8}},
+ {{0x183eab7e78a151ab, 0xbbe990c999093763, 0xff717d6e4ac7e335, 0x4c5cddb325f39f88}}},
+{{{0xc0f6b74d6190a6eb, 0x20ea81a42db8f4e4, 0xa8bd6f7d97315760, 0x33b1d60262ac7c21}},
+ {{0x57750967e7a9f902, 0x2c37fdfc4f5b467e, 0xb261663a3177ba46, 0x3a375e78dc2d532b}},
+ {{0x8141e72f2d4dddea, 0xe6eafe9862c607c8, 0x23c28458573cafd0, 0x46b9476f4ff97346}}},
+{{{0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, 0xe587ff910114db88, 0x37130f364785a142}},
+ {{0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f}},
+ {{0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7}}},
+{{{0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62}},
+ {{0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17}},
+ {{0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d}}},
+{{{0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520}},
+ {{0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43}},
+ {{0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80}}},
+{{{0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d}},
+ {{0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d}},
+ {{0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe}}},
+{{{0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc}},
+ {{0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686}},
+ {{0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4}}},
+{{{0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51}},
+ {{0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a}},
+ {{0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd}}},
+{{{0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9}},
+ {{0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472}},
+ {{0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11}}},
+{{{0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2}},
+ {{0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac}},
+ {{0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5}}},
+{{{0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb}},
+ {{0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb}},
+ {{0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d}}},
+{{{0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad}},
+ {{0xaf44842db0285f37, 0x8753189047efc8df, 0x9574e091f820979a, 0x0e378d6069615579}},
+ {{0xd9fa917183075a55, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877}}},
+{{{0x87dfbd1428878f2d, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8}},
+ {{0xe2004b5bb833a98a, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9}},
+ {{0xf3678fd0ecc90b54, 0xf001459b12043599, 0x26725fbc3758b89b, 0x4325e4aa73a719ae}}},
+{{{0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947}},
+ {{0xed24629acf69f59d, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d}},
+ {{0xee332d4de3b42b0a, 0xd84e5a2b16a4601c, 0x78243877078ba3e4, 0x77ed1eb4184ee437}}},
+{{{0xbfd4e13f201839a0, 0xaeefffe23e3df161, 0xb65b04f06b5d1fe3, 0x52e085fb2b62fbc0}},
+ {{0x185d43f89e92ed1a, 0xb04a1eeafe4719c6, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd}},
+ {{0x124079eaa54cf2ba, 0xd72465eb001b26e7, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02}}},
+{{{0xfd0d5dbee45447b0, 0x6cec351a092005ee, 0x99a47844567579cb, 0x59d242a216e7fa45}},
+ {{0xbc18dcad9b829eac, 0x23ae7d28b5f579d0, 0xc346122a69384233, 0x1a6110b2e7d4ac89}},
+ {{0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546}}},
+{{{0xcb8bb346d75353db, 0xfcfcb24bae511e22, 0xcba48d40d50ae6ef, 0x26e3bae5f4f7cb5d}},
+ {{0x84da3cde8d45fe12, 0xbd42c218e444e2d2, 0xa85196781f7e3598, 0x7642c93f5616e2b2}},
+ {{0x2323daa74595f8e4, 0xde688c8b857abeb4, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba}}},
+{{{0xd6bb4428c17f5026, 0x9eb27223fb5a9ca7, 0xe37ba5031919c644, 0x21ce380db59a6602}},
+ {{0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, 0xd5c55245db3de39f, 0x015e68c1476a4af7}},
+ {{0xc1d5285220066a38, 0x95603e523570aef3, 0x832659a7226b8a4d, 0x5dd689091f8eedc9}}},
+{{{0xcbac84debfd3c856, 0x1624c348b35ff244, 0xb7f88dca5d9cad07, 0x3b0e574da2c2ebe8}},
+ {{0x1d022591a5313084, 0xca2d4aaed6270872, 0x86a12b852f0bfd20, 0x56e6c439ad7da748}},
+ {{0xc704ff4942bdbae6, 0x5e21ade2b2de1f79, 0xe95db3f35652fad8, 0x0822b5378f08ebc1}}},
+{{{0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6}},
+ {{0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f}},
+ {{0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea}}},
+{{{0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09}},
+ {{0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5}},
+ {{0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8}}},
+{{{0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486}},
+ {{0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34}},
+ {{0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c}}},
+{{{0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34}},
+ {{0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80}},
+ {{0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2}}},
+{{{0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d}},
+ {{0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b}},
+ {{0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8}}},
+{{{0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d}},
+ {{0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e}},
+ {{0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc}}},
+{{{0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31}},
+ {{0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06}},
+ {{0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094}}},
+{{{0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454}},
+ {{0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071}},
+ {{0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436}}},
+{{{0xe7547449bc7cd692, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183}},
+ {{0xc11ee5e854c53fae, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef}},
+ {{0x32750763b028f48c, 0x06020740556a065f, 0xd53bd812c3495b58, 0x08706c9b865f508d}}},
+{{{0xf37ca2ab3d343dff, 0x1a8c6a2d80abc617, 0x8e49e035d4ccffca, 0x48b46beebaa1d1b9}},
+ {{0xcc991b4138b41246, 0x243b9c526f9ac26b, 0xb9ef494db7cbabbd, 0x5fba433dd082ed00}},
+ {{0x9c49e355c9941ad0, 0xb9734ade74498f84, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3}}},
+{{{0x76430f9f9cd470d9, 0xb62acc9ba42f6008, 0x1898297c59adad5e, 0x7789dd2db78c5080}},
+ {{0x744f7463e9403762, 0xf79a8dee8dfcc9c9, 0x163a649655e4cde3, 0x3b61788db284f435}},
+ {{0xb22228190d6ef6b2, 0xa94a66b246ce4bfa, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf}}},
+{{{0x8497404d0d55e274, 0x6c6663d9c4ad2b53, 0xec2fb0d9ada95734, 0x2617e120cdb8f73c}},
+ {{0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1}},
+ {{0x6f203dd5405b4b42, 0x327ec60410b24509, 0x9c347230ac2a8846, 0x77de29fc11ffeb6a}}},
+{{{0xb0ac57c983b778a8, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac}},
+ {{0x835e138fecced2ca, 0x8c9eaf13ea963b9a, 0xc95fbfc0b2160ea6, 0x575e66f3ad877892}},
+ {{0x99803a27c88fcb3a, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2}}},
+{{{0x085ae2c759ff1be4, 0x149145c93b0e40b7, 0xc467e7fa7ff27379, 0x4eeecf0ad5c73a95}},
+ {{0x6d822986698a19e0, 0xdc9821e174d78a71, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51}},
+ {{0x48329952213fc985, 0x1087cf0d368a1746, 0x8e5261b166c15aa5, 0x2d5b2d842ed24c21}}},
+{{{0x02cfebd9ebd3ded1, 0xd45b217739021974, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2}},
+ {{0x5eb7d13d196ac533, 0x377234ecdb80be2b, 0xe144cffc7cf5ae24, 0x5226bcf9c441acec}},
+ {{0x79ee6c7223e5b547, 0x6f5f50768330d679, 0xed73e1e96d8adce9, 0x27c3da1e1d8ccc03}}},
+{{{0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9}},
+ {{0x28302e71630ef9f6, 0xc2d4a2032b64cee0, 0x090820304b6292be, 0x5fca747aa82adf18}},
+ {{0x232a03c35c258ea5, 0x86f23a2c6bcb0cf1, 0x3dad8d0d2e442166, 0x04a8933cab76862b}}},
+{{{0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf}},
+ {{0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140}},
+ {{0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42}}},
+{{{0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42}},
+ {{0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5}},
+ {{0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b}}},
+{{{0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351}},
+ {{0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b}},
+ {{0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4}}},
+{{{0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217}},
+ {{0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e}},
+ {{0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154}}},
+{{{0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763}},
+ {{0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f}},
+ {{0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597}}},
+{{{0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9}},
+ {{0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b}},
+ {{0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f}}},
+{{{0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858}},
+ {{0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1}},
+ {{0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4}}},
+{{{0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543}},
+ {{0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6}},
+ {{0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f}}},
+{{{0xb1507ca1ab1c6eb9, 0xbd448f3e16b687b3, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1}},
+ {{0x6ab5dcb85b1c16b7, 0x94c0fce83c7b27a5, 0xa4b11c1a735517be, 0x499238d0ba0eafaa}},
+ {{0xecf46e527aba8b57, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5}}},
+{{{0xdf02f95f1015e7a1, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9}},
+ {{0x93d3cbe9bdd8f0a4, 0xdb152c1bfd177302, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe}},
+ {{0xc83ca3e390babd62, 0x80ede3670291c833, 0xc88038ccd37900c4, 0x2c5fc0231ec31fa1}}},
+{{{0xfeba911717038b4f, 0xe5123721c9deef81, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6}},
+ {{0xc422e4d102456e65, 0x87414ac1cad47b91, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f}},
+ {{0x5bd9b4763626e81c, 0x89966936bca02edd, 0x0a41193d61f077b3, 0x3097a24200ce5471}}},
+{{{0x57427734c7f8b84c, 0xf141a13e01b270e9, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48}},
+ {{0xa162e7246695c486, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363}},
+ {{0xaf6c4aa752f912b9, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e}}},
+{{{0xc4007f77d0c1cec3, 0x8d1020b6bac492f8, 0x32ec29d57e69daaf, 0x599408759d95fce0}},
+ {{0x33810a23bf00086e, 0xafce925ee736ff7c, 0x3d60e670e24922d4, 0x11ce9e714f96061b}},
+ {{0x219ef713d815bac1, 0xf141465d485be25c, 0x6d5447cc4e513c51, 0x174926be5ef44393}}},
+{{{0xb5deb2f9fc5bd5bb, 0x92daa72ae1d810e1, 0xafc4cfdcb72a1c59, 0x497d78813fc22a24}},
+ {{0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, 0x8fd24ecf07382c8c, 0x6fa42ead06d8e1ad}},
+ {{0xe276824a1f73371f, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96}}},
+{{{0x825fbdfd63014d2b, 0xc852369c6ca7578b, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f}},
+ {{0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b}},
+ {{0xbd4ea9e10f53c4b6, 0x1673dc5f8ac91a14, 0xa8f81a4e2acc1aba, 0x33a92a7924332a25}}},
+{{{0x9dd1f49927996c02, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1}},
+ {{0x7ba95ba0218f2ada, 0xcff42287330fb9ca, 0xdada496d56c6d907, 0x5380c296f4beee54}},
+ {{0x9d4f270466898d0a, 0x3d0987990aff3f7a, 0xd09ef36267daba45, 0x7761455e7b1c669c}}} \ No newline at end of file
diff --git a/ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data b/ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data
new file mode 100644
index 00000000..a31f6f2f
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_base_niels_smalltables.data
@@ -0,0 +1,768 @@
+{{{0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267}},
+ {{0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65}},
+ {{0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca}}},
+{{{0x8a99a56042b4d5a8, 0x8f2b810c4e60acf6, 0xe09e236bb16e37aa, 0x6bb595a669c92555}},
+ {{0x9224e7fc933c71d7, 0x9f469d967a0ff5b5, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e}},
+ {{0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8}}},
+{{{0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62}},
+ {{0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4}},
+ {{0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21}}},
+{{{0x95fe050a056818bf, 0x327e89715660faa9, 0xc3e8e3cd06a05073, 0x27933f4c7445a49a}},
+ {{0x287351b98efc099f, 0x6765c6f47dfd2538, 0xca348d3dfb0a9265, 0x680e910321e58727}},
+ {{0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18}}},
+{{{0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3}},
+ {{0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb}},
+ {{0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98}}},
+{{{0x499806b67b7d8ca4, 0x575be28427d22739, 0xbb085ce7204553b9, 0x38b64c41ae417884}},
+ {{0x3a0ceeeb77157131, 0x9b27158900c8af88, 0x8065b668da59a736, 0x51e57bb6a2cc38bd}},
+ {{0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f}}},
+{{{0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0}},
+ {{0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e}},
+ {{0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37}}},
+{{{0xe2a75dedf39234d9, 0x963d7680e1b558f9, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3}},
+ {{0x59b7596604dd3e8f, 0x6cb30377e288702c, 0xb1339c665ed9c323, 0x0915e76061bce52f}},
+ {{0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2}}},
+{{{0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9}},
+ {{0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39}},
+ {{0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0}}},
+{{{0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09}},
+ {{0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef}},
+ {{0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c}}},
+{{{0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9}},
+ {{0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a}},
+ {{0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c}}},
+{{{0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173}},
+ {{0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e}},
+ {{0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04}}},
+{{{0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999}},
+ {{0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c}},
+ {{0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56}}},
+{{{0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced}},
+ {{0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4}},
+ {{0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6}}},
+{{{0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f}},
+ {{0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8}},
+ {{0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151}}},
+{{{0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3}},
+ {{0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a}},
+ {{0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213}}},
+{{{0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7}},
+ {{0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d}},
+ {{0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464}}},
+{{{0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2}},
+ {{0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030}},
+ {{0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80}}},
+{{{0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4}},
+ {{0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9}},
+ {{0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b}}},
+{{{0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5}},
+ {{0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481}},
+ {{0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8}}},
+{{{0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb}},
+ {{0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b}},
+ {{0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf}}},
+{{{0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74}},
+ {{0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b}},
+ {{0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6}}},
+{{{0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29}},
+ {{0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3}},
+ {{0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc}}},
+{{{0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83}},
+ {{0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c}},
+ {{0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2}}},
+{{{0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d}},
+ {{0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9}},
+ {{0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf}}},
+{{{0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785}},
+ {{0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a}},
+ {{0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823}}},
+{{{0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee}},
+ {{0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5}},
+ {{0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790}}},
+{{{0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7}},
+ {{0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068}},
+ {{0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375}}},
+{{{0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a}},
+ {{0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252}},
+ {{0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76}}},
+{{{0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21}},
+ {{0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b}},
+ {{0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111}}},
+{{{0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40}},
+ {{0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445}},
+ {{0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c}}},
+{{{0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4}},
+ {{0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245}},
+ {{0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6}}},
+{{{0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0}},
+ {{0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c}},
+ {{0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366}}},
+{{{0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943}},
+ {{0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff}},
+ {{0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812}}},
+{{{0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab}},
+ {{0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b}},
+ {{0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd}}},
+{{{0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1}},
+ {{0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9}},
+ {{0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e}}},
+{{{0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840}},
+ {{0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e}},
+ {{0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272}}},
+{{{0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5}},
+ {{0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4}},
+ {{0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab}}},
+{{{0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b}},
+ {{0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447}},
+ {{0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494}}},
+{{{0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3}},
+ {{0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8}},
+ {{0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03}}},
+{{{0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1}},
+ {{0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108}},
+ {{0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233}}},
+{{{0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d}},
+ {{0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7}},
+ {{0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307}}},
+{{{0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53}},
+ {{0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44}},
+ {{0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6}}},
+{{{0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355}},
+ {{0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd}},
+ {{0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80}}},
+{{{0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304}},
+ {{0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7}},
+ {{0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da}}},
+{{{0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2}},
+ {{0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784}},
+ {{0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c}}},
+{{{0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7}},
+ {{0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472}},
+ {{0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17}}},
+{{{0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4}},
+ {{0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5}},
+ {{0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2}}},
+{{{0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908}},
+ {{0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93}},
+ {{0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3}}},
+{{{0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e}},
+ {{0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c}},
+ {{0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808}}},
+{{{0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22}},
+ {{0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8}},
+ {{0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969}}},
+{{{0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea}},
+ {{0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10}},
+ {{0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba}}},
+{{{0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03}},
+ {{0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c}},
+ {{0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92}}},
+{{{0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a}},
+ {{0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9}},
+ {{0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa}}},
+{{{0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7}},
+ {{0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9}},
+ {{0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a}}},
+{{{0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42}},
+ {{0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c}},
+ {{0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3}}},
+{{{0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232}},
+ {{0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35}},
+ {{0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4}}},
+{{{0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab}},
+ {{0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d}},
+ {{0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413}}},
+{{{0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84}},
+ {{0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56}},
+ {{0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7}}},
+{{{0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495}},
+ {{0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5}},
+ {{0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41}}},
+{{{0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76}},
+ {{0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286}},
+ {{0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489}}},
+{{{0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008}},
+ {{0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16}},
+ {{0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76}}},
+{{{0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309}},
+ {{0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700}},
+ {{0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb}}},
+{{{0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a}},
+ {{0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd}},
+ {{0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760}}},
+{{{0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650}},
+ {{0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb}},
+ {{0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba}}},
+{{{0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650}},
+ {{0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9}},
+ {{0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561}}},
+{{{0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e}},
+ {{0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2}},
+ {{0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701}}},
+{{{0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322}},
+ {{0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e}},
+ {{0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0}}},
+{{{0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0}},
+ {{0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839}},
+ {{0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7}}},
+{{{0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9}},
+ {{0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8}},
+ {{0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54}}},
+{{{0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185}},
+ {{0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde}},
+ {{0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f}}},
+{{{0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6}},
+ {{0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253}},
+ {{0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d}}},
+{{{0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7}},
+ {{0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c}},
+ {{0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9}}},
+{{{0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877}},
+ {{0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83}},
+ {{0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3}}},
+{{{0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633}},
+ {{0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98}},
+ {{0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016}}},
+{{{0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1}},
+ {{0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1}},
+ {{0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059}}},
+{{{0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b}},
+ {{0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042}},
+ {{0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a}}},
+{{{0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0}},
+ {{0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217}},
+ {{0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd}}},
+{{{0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff}},
+ {{0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05}},
+ {{0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd}}},
+{{{0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42}},
+ {{0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295}},
+ {{0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd}}},
+{{{0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6}},
+ {{0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e}},
+ {{0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc}}},
+{{{0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402}},
+ {{0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081}},
+ {{0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006}}},
+{{{0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0}},
+ {{0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5}},
+ {{0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64}}},
+{{{0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c}},
+ {{0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90}},
+ {{0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18}}},
+{{{0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b}},
+ {{0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355}},
+ {{0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413}}},
+{{{0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194}},
+ {{0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b}},
+ {{0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56}}},
+{{{0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00}},
+ {{0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b}},
+ {{0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38}}},
+{{{0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6}},
+ {{0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57}},
+ {{0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b}}},
+{{{0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e}},
+ {{0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17}},
+ {{0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa}}},
+{{{0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c}},
+ {{0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438}},
+ {{0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543}}},
+{{{0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d}},
+ {{0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452}},
+ {{0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6}}},
+{{{0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f}},
+ {{0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55}},
+ {{0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c}}},
+{{{0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc}},
+ {{0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d}},
+ {{0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86}}},
+{{{0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70}},
+ {{0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a}},
+ {{0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388}}},
+{{{0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00}},
+ {{0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc}},
+ {{0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4}}},
+{{{0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8}},
+ {{0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d}},
+ {{0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af}}},
+{{{0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d}},
+ {{0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a}},
+ {{0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137}}},
+{{{0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007}},
+ {{0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86}},
+ {{0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e}}},
+{{{0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07}},
+ {{0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c}},
+ {{0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac}}},
+{{{0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318}},
+ {{0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754}},
+ {{0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859}}},
+{{{0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2}},
+ {{0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964}},
+ {{0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410}}},
+{{{0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e}},
+ {{0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599}},
+ {{0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436}}},
+{{{0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992}},
+ {{0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d}},
+ {{0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf}}},
+{{{0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40}},
+ {{0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb}},
+ {{0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716}}},
+{{{0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf}},
+ {{0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4}},
+ {{0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2}}},
+{{{0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d}},
+ {{0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1}},
+ {{0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317}}},
+{{{0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4}},
+ {{0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133}},
+ {{0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c}}},
+{{{0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607}},
+ {{0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827}},
+ {{0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae}}},
+{{{0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e}},
+ {{0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd}},
+ {{0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b}}},
+{{{0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314}},
+ {{0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6}},
+ {{0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389}}},
+{{{0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7}},
+ {{0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea}},
+ {{0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1}}},
+{{{0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be}},
+ {{0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69}},
+ {{0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa}}},
+{{{0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690}},
+ {{0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b}},
+ {{0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b}}},
+{{{0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149}},
+ {{0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5}},
+ {{0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f}}},
+{{{0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd}},
+ {{0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668}},
+ {{0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5}}},
+{{{0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd}},
+ {{0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c}},
+ {{0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7}}},
+{{{0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848}},
+ {{0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33}},
+ {{0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51}}},
+{{{0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6}},
+ {{0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37}},
+ {{0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6}}},
+{{{0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788}},
+ {{0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690}},
+ {{0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759}}},
+{{{0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c}},
+ {{0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90}},
+ {{0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a}}},
+{{{0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582}},
+ {{0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021}},
+ {{0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6}}},
+{{{0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4}},
+ {{0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369}},
+ {{0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4}}},
+{{{0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312}},
+ {{0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e}},
+ {{0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4}}},
+{{{0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc}},
+ {{0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f}},
+ {{0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537}}},
+{{{0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4}},
+ {{0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390}},
+ {{0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f}}},
+{{{0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff}},
+ {{0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f}},
+ {{0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460}}},
+{{{0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74}},
+ {{0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720}},
+ {{0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7}}},
+{{{0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730}},
+ {{0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d}},
+ {{0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5}}},
+{{{0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551}},
+ {{0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa}},
+ {{0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693}}},
+{{{0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63}},
+ {{0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352}},
+ {{0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8}}},
+{{{0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36}},
+ {{0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870}},
+ {{0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f}}},
+{{{0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9}},
+ {{0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51}},
+ {{0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec}}},
+{{{0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8}},
+ {{0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde}},
+ {{0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244}}},
+{{{0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a}},
+ {{0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6}},
+ {{0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4}}},
+{{{0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34}},
+ {{0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6}},
+ {{0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1}}},
+{{{0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab}},
+ {{0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81}},
+ {{0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7}}},
+{{{0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e}},
+ {{0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9}},
+ {{0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7}}},
+{{{0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9}},
+ {{0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0}},
+ {{0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6}}},
+{{{0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3}},
+ {{0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226}},
+ {{0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945}}},
+{{{0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b}},
+ {{0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c}},
+ {{0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832}}},
+{{{0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122}},
+ {{0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce}},
+ {{0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed}}},
+{{{0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a}},
+ {{0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109}},
+ {{0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790}}},
+{{{0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99}},
+ {{0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1}},
+ {{0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb}}},
+{{{0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92}},
+ {{0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08}},
+ {{0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d}}},
+{{{0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d}},
+ {{0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4}},
+ {{0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069}}},
+{{{0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f}},
+ {{0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019}},
+ {{0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012}}},
+{{{0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae}},
+ {{0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6}},
+ {{0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb}}},
+{{{0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877}},
+ {{0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c}},
+ {{0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b}}},
+{{{0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364}},
+ {{0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5}},
+ {{0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1}}},
+{{{0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9}},
+ {{0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554}},
+ {{0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3}}},
+{{{0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485}},
+ {{0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc}},
+ {{0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a}}},
+{{{0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4}},
+ {{0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d}},
+ {{0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c}}},
+{{{0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792}},
+ {{0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c}},
+ {{0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319}}},
+{{{0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266}},
+ {{0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13}},
+ {{0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e}}},
+{{{0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868}},
+ {{0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9}},
+ {{0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe}}},
+{{{0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd}},
+ {{0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241}},
+ {{0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463}}},
+{{{0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b}},
+ {{0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280}},
+ {{0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a}}},
+{{{0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac}},
+ {{0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67}},
+ {{0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99}}},
+{{{0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9}},
+ {{0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b}},
+ {{0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db}}},
+{{{0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf}},
+ {{0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf}},
+ {{0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859}}},
+{{{0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6}},
+ {{0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095}},
+ {{0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1}}},
+{{{0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f}},
+ {{0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99}},
+ {{0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e}}},
+{{{0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4}},
+ {{0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0}},
+ {{0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c}}},
+{{{0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c}},
+ {{0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3}},
+ {{0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d}}},
+{{{0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca}},
+ {{0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24}},
+ {{0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34}}},
+{{{0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354}},
+ {{0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e}},
+ {{0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075}}},
+{{{0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993}},
+ {{0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d}},
+ {{0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe}}},
+{{{0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68}},
+ {{0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95}},
+ {{0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d}}},
+{{{0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c}},
+ {{0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060}},
+ {{0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72}}},
+{{{0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b}},
+ {{0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df}},
+ {{0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb}}},
+{{{0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03}},
+ {{0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64}},
+ {{0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa}}},
+{{{0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01}},
+ {{0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613}},
+ {{0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb}}},
+{{{0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c}},
+ {{0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8}},
+ {{0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75}}},
+{{{0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded}},
+ {{0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13}},
+ {{0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6}}},
+{{{0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d}},
+ {{0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b}},
+ {{0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7}}},
+{{{0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73}},
+ {{0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf}},
+ {{0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a}}},
+{{{0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d}},
+ {{0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d}},
+ {{0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0}}},
+{{{0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956}},
+ {{0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba}},
+ {{0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1}}},
+{{{0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a}},
+ {{0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5}},
+ {{0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4}}},
+{{{0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5}},
+ {{0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75}},
+ {{0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3}}},
+{{{0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1}},
+ {{0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026}},
+ {{0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066}}},
+{{{0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7}},
+ {{0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2}},
+ {{0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568}}},
+{{{0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5}},
+ {{0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5}},
+ {{0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26}}},
+{{{0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f}},
+ {{0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223}},
+ {{0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb}}},
+{{{0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006}},
+ {{0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231}},
+ {{0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc}}},
+{{{0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da}},
+ {{0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd}},
+ {{0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2}}},
+{{{0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace}},
+ {{0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e}},
+ {{0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f}}},
+{{{0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca}},
+ {{0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd}},
+ {{0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f}}},
+{{{0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6}},
+ {{0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616}},
+ {{0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d}}},
+{{{0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831}},
+ {{0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4}},
+ {{0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214}}},
+{{{0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6}},
+ {{0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde}},
+ {{0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e}}},
+{{{0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd}},
+ {{0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074}},
+ {{0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b}}},
+{{{0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3}},
+ {{0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab}},
+ {{0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b}}},
+{{{0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434}},
+ {{0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c}},
+ {{0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be}}},
+{{{0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57}},
+ {{0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36}},
+ {{0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179}}},
+{{{0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661}},
+ {{0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3}},
+ {{0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f}}},
+{{{0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562}},
+ {{0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037}},
+ {{0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e}}},
+{{{0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc}},
+ {{0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7}},
+ {{0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a}}},
+{{{0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372}},
+ {{0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e}},
+ {{0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97}}},
+{{{0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4}},
+ {{0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6}},
+ {{0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867}}},
+{{{0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797}},
+ {{0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001}},
+ {{0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293}}},
+{{{0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec}},
+ {{0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f}},
+ {{0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c}}},
+{{{0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07}},
+ {{0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332}},
+ {{0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217}}},
+{{{0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714}},
+ {{0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0}},
+ {{0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e}}},
+{{{0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13}},
+ {{0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e}},
+ {{0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0}}},
+{{{0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade}},
+ {{0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940}},
+ {{0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db}}},
+{{{0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57}},
+ {{0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8}},
+ {{0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408}}},
+{{{0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be}},
+ {{0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98}},
+ {{0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c}}},
+{{{0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b}},
+ {{0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9}},
+ {{0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09}}},
+{{{0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5}},
+ {{0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc}},
+ {{0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc}}},
+{{{0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147}},
+ {{0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834}},
+ {{0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2}}},
+{{{0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd}},
+ {{0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65}},
+ {{0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469}}},
+{{{0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57}},
+ {{0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2}},
+ {{0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63}}},
+{{{0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7}},
+ {{0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0}},
+ {{0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73}}},
+{{{0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87}},
+ {{0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f}},
+ {{0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65}}},
+{{{0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8}},
+ {{0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620}},
+ {{0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99}}},
+{{{0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff}},
+ {{0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85}},
+ {{0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15}}},
+{{{0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33}},
+ {{0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5}},
+ {{0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44}}},
+{{{0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090}},
+ {{0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438}},
+ {{0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955}}},
+{{{0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f}},
+ {{0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe}},
+ {{0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50}}},
+{{{0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13}},
+ {{0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577}},
+ {{0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907}}},
+{{{0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa}},
+ {{0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a}},
+ {{0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea}}},
+{{{0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1}},
+ {{0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128}},
+ {{0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4}}},
+{{{0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a}},
+ {{0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1}},
+ {{0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664}}},
+{{{0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e}},
+ {{0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a}},
+ {{0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835}}},
+{{{0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09}},
+ {{0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6}},
+ {{0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d}}},
+{{{0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0}},
+ {{0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e}},
+ {{0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1}}},
+{{{0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda}},
+ {{0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138}},
+ {{0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c}}},
+{{{0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c}},
+ {{0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9}},
+ {{0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293}}},
+{{{0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b}},
+ {{0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d}},
+ {{0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c}}},
+{{{0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0}},
+ {{0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03}},
+ {{0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae}}},
+{{{0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a}},
+ {{0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838}},
+ {{0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0}}},
+{{{0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62}},
+ {{0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17}},
+ {{0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d}}},
+{{{0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520}},
+ {{0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43}},
+ {{0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80}}},
+{{{0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d}},
+ {{0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d}},
+ {{0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe}}},
+{{{0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc}},
+ {{0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686}},
+ {{0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4}}},
+{{{0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51}},
+ {{0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a}},
+ {{0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd}}},
+{{{0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9}},
+ {{0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472}},
+ {{0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11}}},
+{{{0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2}},
+ {{0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac}},
+ {{0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5}}},
+{{{0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb}},
+ {{0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb}},
+ {{0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d}}},
+{{{0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6}},
+ {{0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f}},
+ {{0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea}}},
+{{{0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09}},
+ {{0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5}},
+ {{0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8}}},
+{{{0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486}},
+ {{0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34}},
+ {{0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c}}},
+{{{0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34}},
+ {{0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80}},
+ {{0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2}}},
+{{{0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d}},
+ {{0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b}},
+ {{0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8}}},
+{{{0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d}},
+ {{0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e}},
+ {{0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc}}},
+{{{0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31}},
+ {{0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06}},
+ {{0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094}}},
+{{{0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454}},
+ {{0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071}},
+ {{0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436}}},
+{{{0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf}},
+ {{0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140}},
+ {{0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42}}},
+{{{0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42}},
+ {{0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5}},
+ {{0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b}}},
+{{{0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351}},
+ {{0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b}},
+ {{0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4}}},
+{{{0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217}},
+ {{0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e}},
+ {{0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154}}},
+{{{0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763}},
+ {{0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f}},
+ {{0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597}}},
+{{{0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9}},
+ {{0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b}},
+ {{0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f}}},
+{{{0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858}},
+ {{0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1}},
+ {{0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4}}},
+{{{0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543}},
+ {{0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6}},
+ {{0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f}}} \ No newline at end of file
diff --git a/ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data b/ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data
new file mode 100644
index 00000000..32a5d474
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_base_slide_multiples.data
@@ -0,0 +1,96 @@
+{{{0x9d103905d740913e, 0xfd399f05d140beb3, 0xa5c18434688f8a09, 0x44fd2f9298f81267}},
+ {{0x2fbc93c6f58c3b85, 0xcf932dc6fb8c0e19, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65}},
+ {{0xabc91205877aaa68, 0x26d9e823ccaac49e, 0x5a1b7dcbdd43598c, 0x6f117b689f0c65a8}}},
+{{{0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, 0x8131f31a214bd6bd, 0x2ab91587555bda62}},
+ {{0xaf25b0a84cee9730, 0x025a8430e8864b8a, 0xc11b50029f016732, 0x7a164e1b9a80f8f4}},
+ {{0x14ae933f0dd0d889, 0x589423221c35da62, 0xd170e5458cf2db4c, 0x5a2826af12b9b4c6}}},
+{{{0x7f9182c3a447d6ba, 0xd50014d14b2729b7, 0xe33cf11cb864a087, 0x154a7e73eb1b55f3}},
+ {{0xa212bc4408a5bb33, 0x8d5048c3c75eed02, 0xdd1beb0c5abfec44, 0x2945ccf146e206eb}},
+ {{0xbcbbdbf1812a8285, 0x270e0807d0bdd1fc, 0xb41b670b1bbda72d, 0x43aabe696b3bb69a}}},
+{{{0xba6f2c9aaa3221b1, 0x6ca021533bba23a7, 0x9dea764f92192c3a, 0x1d6edd5d2e5317e0}},
+ {{0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e}},
+ {{0xf1836dc801b8b3a2, 0xb3035f47053ea49a, 0x529c41ba5877adf3, 0x7a9fbb1c6a0f90a7}}},
+{{{0xf36e217e039d8064, 0x98a081b6f520419b, 0x96cbc608e75eb044, 0x49c05a51fadc9c8f}},
+ {{0x9b2e678aa6a8632f, 0xa6509e6f51bc46c5, 0xceb233c9c686f5b5, 0x34b9ed338add7f59}},
+ {{0x06b4e8bf9045af1b, 0xe2ff83e8a719d22f, 0xaaf6fc2993d4cf16, 0x73c172021b008b06}}},
+{{{0x315f5b0249864348, 0x3ed6b36977088381, 0xa3a075556a8deb95, 0x18ab598029d5c77f}},
+ {{0x2fbf00848a802ade, 0xe5d9fecf02302e27, 0x113e847117703406, 0x4275aae2546d8faf}},
+ {{0xd82b2cc5fd6089e9, 0x031eb4a13282e4a4, 0x44311199b51a8622, 0x3dc65522b53df948}}},
+{{{0x506f013b327fbf93, 0xaefcebc99b776f6b, 0x9d12b232aaad5968, 0x0267882d176024a7}},
+ {{0xbf70c222a2007f6d, 0xbf84b39ab5bcdedb, 0x537a0e12fb07ba07, 0x234fd7eec346f241}},
+ {{0x5360a119732ea378, 0x2437e6b1df8dd471, 0xa2ef37f891a7e533, 0x497ba6fdaa097863}}},
+{{{0x040bcd86468ccf0b, 0xd3829ba42a9910d6, 0x7508300807b25192, 0x43b5cd4218d05ebf}},
+ {{0x24cecc0313cfeaa0, 0x8648c28d189c246d, 0x2dbdbdfac1f2d4d0, 0x61e22917f12de72b}},
+ {{0x5d9a762f9bd0b516, 0xeb38af4e373fdeee, 0x032e5a7d93d64270, 0x511d61210ae4d842}}},
+{{{0x081386484420de87, 0x8a1cf016b592edb4, 0x39fa4e2729942d25, 0x71a7fe6fe2482810}},
+ {{0x92c676ef950e9d81, 0xa54620cdc0d7044f, 0xaa9b36646f8f1248, 0x6d325924ddb855e3}},
+ {{0x6c7182b8a5c8c854, 0x33fd1479fe5f2a03, 0x72cf591883778d0c, 0x4746c4b6559eeaa9}}},
+{{{0x348546c864741147, 0x7d35aedd0efcc849, 0xff939a760672a332, 0x219663497db5e6d6}},
+ {{0xd3777b3c6dc69a2b, 0xdefab2276f89f617, 0x45651cf7b53a16b5, 0x5c9a51de34fe9fb7}},
+ {{0xf510f1cf79f10e67, 0xffdddaa1e658515b, 0x09c3a71710142277, 0x4804503c608223bb}}},
+{{{0x3b6821d23a36d175, 0xbbb40aa7e99b9e32, 0x5d9e5ce420838a47, 0x771e098858de4c5e}},
+ {{0xc4249ed02ca37fc7, 0xa059a0e3a615acab, 0x88a96ed7c96e0e23, 0x553398a51650696d}},
+ {{0x9a12f5d278451edf, 0x3ada5d7985899ccb, 0x477f4a2d9fa59508, 0x5a5ed1d68ff5a611}}},
+{{{0xbae5e0c558527359, 0x392e5c19cadb9d7e, 0x28653c1eda1cabe9, 0x019b60135fefdc44}},
+ {{0x1195122afe150e83, 0xcf209a257e4b35d8, 0x7387f8291e711e20, 0x44acb897d8bf92f0}},
+ {{0x1e6068145e134b83, 0xc4f5e64f24304c16, 0x506e88a8fc1a3ed7, 0x150c49fde6ad2f92}}},
+{{{0xb849863c9cdca868, 0xc83f44dbb8714ad0, 0xfe3ee3560c36168d, 0x78a6d7791e05fbc1}},
+ {{0x8e7bf29509471138, 0x5d6fef394f75a651, 0x10af79c425a708ad, 0x6b2b5a075bb99922}},
+ {{0x58bf704b47a0b976, 0xa601b355741748d5, 0xaa2b1fb1d542f590, 0x725c7ffc4ad55d00}}},
+{{{0x91802bf71cd098c0, 0xfe416ca4ed5e6366, 0xdf585d714902994c, 0x4cd54625f855fae7}},
+ {{0xe4426715d1cf99b2, 0x7352d51102a20d34, 0x23d1157b8b12109f, 0x794cc9277cb1f3a3}},
+ {{0x4af6c426c2ac5053, 0xbc9aedad32f67258, 0x2ad032f10a311021, 0x7008357b6fcc8e85}}},
+{{{0xd01b9fbb82584a34, 0x47ab6463d2b4792b, 0xb631639c48536202, 0x13a92a3669d6d428}},
+ {{0x0b88672738773f01, 0xb8ccc8fa95fbccfb, 0x8d2dd5a3b9ad29b6, 0x06ef7e9851ad0f6a}},
+ {{0xca93771cc0577de5, 0x7540e41e5035dc5c, 0x24680f01d802e071, 0x3c296ddf8a2af86a}}},
+{{{0xfceb4d2ebb1f2541, 0xb89510c740adb91f, 0xfc71a37dd0a1ad05, 0x0a892c700747717b}},
+ {{0xaead15f9d914a713, 0xa92f7bf98c8ff912, 0xaff823179f53d730, 0x7a99d393490c77ba}},
+ {{0x8f52ed2436bda3e8, 0x77a8c84157e80794, 0xa5a96563262f9ce0, 0x286762d28302f7d2}}},
+{{{0x7c558e2bce2ef5bd, 0xe4986cb46747bc63, 0x154a179f3bbb89b8, 0x7686f2a3d6f1767a}},
+ {{0x4e7836093ce35b25, 0x82e1181db26baa97, 0x0cc192d3cbc7b83f, 0x32f1da046a9d9d3a}},
+ {{0xaa8d12a66d597c6a, 0x8f11930304d3852b, 0x3f91dc73c209b022, 0x561305f8a9ad28a6}}},
+{{{0x6722cc28e7b0c0d5, 0x709de9bbdb075c53, 0xcaf68da7d7010a61, 0x030a1aef2c57cc6c}},
+ {{0x100c978dec92aed1, 0xca43d5434d6d73e5, 0x83131b22d847ba48, 0x00aaec53e35d4d2c}},
+ {{0x7bb1f773003ad2aa, 0x0b3f29802b216608, 0x7821dc86520ed23e, 0x20be9c1c24065480}}},
+{{{0x20e0e44ae2025e60, 0xb03b3b2fcbdcb938, 0x105d639cf95a0d1c, 0x69764c545067e311}},
+ {{0xe15387d8249673a6, 0x5943bc2df546e493, 0x1c7f9a81c36f63b5, 0x750ab3361f0ac1de}},
+ {{0x1e8a3283a2f81037, 0x6f2eda23bd7fcbf1, 0xb72fd15bac2e2563, 0x54f96b3fb7075040}}},
+{{{0x177dafc616b11ecd, 0x89764b9cfa576479, 0xb7a8a110e6ece785, 0x78e6839fbe85dbf0}},
+ {{0x0fadf20429669279, 0x3adda2047d7d724a, 0x6f3d94828c5760f1, 0x3d7fe9c52bb7539e}},
+ {{0x70332df737b8856b, 0x75d05d43041a178a, 0x320ff74aa0e59e22, 0x70f268f350088242}}},
+{{{0x2324112070dcf355, 0x380cc97ee7fce117, 0xb31ddeed3552b698, 0x404e56c039b8c4b9}},
+ {{0x66864583b1805f47, 0xf535c5d160dd7c19, 0xe9874eb71e4cb006, 0x7c0d345cfad889d9}},
+ {{0x591f1f4b8c78338a, 0xa0366ab167e0b5e1, 0x5cbc4152b45f3d44, 0x20d754762aaec777}}},
+{{{0x9d74feb135b9f543, 0x84b37df1de8c956c, 0xe9322b0757138ba9, 0x38b8ada8790b4ce1}},
+ {{0x5e8fc36fc73bb758, 0xace543a5363cbb9a, 0xa9934a7d903bc922, 0x2b8f1e46f3ceec62}},
+ {{0xb5c04a9cdf51f95d, 0x2b3952aecb1fdeac, 0x1d106d8b328b66da, 0x049aeb32ceba1953}}},
+{{{0xd7767d3c63dcfe7e, 0x209c594897856e40, 0xb6676861e14f7c13, 0x51c665e0c8d625fc}},
+ {{0xaa507d0b75fc7931, 0x0fef924b7a6725d3, 0x1d82542b396b3930, 0x795ee17530f674fc}},
+ {{0x254a5b0a52ecbd81, 0x5d411f6ee034afe7, 0xe6a24d0dcaee4a31, 0x6cd19bf49dc54477}}},
+{{{0x7e87619052179ca3, 0x571d0a060b2c9f85, 0x80a2baa88499711e, 0x7520f3db40b2e638}},
+ {{0x1ffe612165afc386, 0x082a2a88b8d51b10, 0x76f6627e20990baa, 0x5e01b3a7429e43e7}},
+ {{0x3db50be3d39357a1, 0x967b6cdd599e94a5, 0x1a309a64df311e6e, 0x71092c9ccef3c986}}},
+{{{0x53d8523f0364918c, 0xa2b404f43fab6b1c, 0x080b4a9e6681e5a4, 0x0ea15b03d0257ba7}},
+ {{0x856bd8ac74051dcf, 0x03f6a40855b7aa1e, 0x3a4ae7cbc9743ceb, 0x4173a5bb7137abde}},
+ {{0x17c56e31f0f9218a, 0x5a696e2b1afc4708, 0xf7931668f4b2f176, 0x5fc565614a4e3a67}}},
+{{{0x136e570dc46d7ae5, 0x0fd0aacc54f8dc8f, 0x59549f03310dad86, 0x62711c414c454aa1}},
+ {{0x4892e1e67790988e, 0x01d5950f1c5cd722, 0xe3b0819ae5923eed, 0x3214c7409d46651b}},
+ {{0x1329827406651770, 0x3ba4a0668a279436, 0xd9b6b8ec185d223c, 0x5bea94073ecb833c}}},
+{{{0x641dbf0912c89be4, 0xacf38b317d6e579c, 0xabfe9e02f697b065, 0x3aacd5c148f61eec}},
+ {{0xb470ce63f343d2f8, 0x0067ba8f0543e8f1, 0x35da51a1a2117b6f, 0x4ad0785944f1bd2f}},
+ {{0x858e3b34c3318301, 0xdc99c04707316826, 0x34085b2ed39da88c, 0x3aff0cb1d902853d}}},
+{{{0x87c5c7eb3a20405e, 0x8ee311efedad56c9, 0x29252e48ad29d5f9, 0x110e7e86f4cd251d}},
+ {{0x9226430bf4c53505, 0x68e49c13261f2283, 0x09ef33788fd327c6, 0x2ccf9f732bd99e7f}},
+ {{0x57c0d89ed603f5e4, 0x12888628f0b0200c, 0x53172709a02e3bb7, 0x05c557e0b9693a37}}},
+{{{0xd8f9ce311fc97e6f, 0x7a3f263011f9fdae, 0xe15b7ea08bed25dd, 0x6e154c178fe9875a}},
+ {{0xf776bbb089c20eb0, 0x61f85bf6fa0fd85c, 0xb6b93f4e634421fb, 0x289fef0841861205}},
+ {{0xcf616336fed69abf, 0x9b16e4e78335c94f, 0x13789765753a7fe7, 0x6afbf642a95ca319}}},
+{{{0x7da8de0c62f5d2c1, 0x98fc3da4b00e7b9a, 0x7deb6ada0dad70e0, 0x0db4b851b95038c4}},
+ {{0x5de55070f913a8cc, 0x7d1d167b2b0cf561, 0xda2956b690ead489, 0x12c093cedb801ed9}},
+ {{0xfc147f9308b8190f, 0x06969da0a11ae310, 0xcee75572dac7d7fd, 0x33aa8799c6635ce6}}},
+{{{0xaf0ff51ebd085cf2, 0x78f51a8967d33f1f, 0x6ec2bfe15060033c, 0x233c6f29e8e21a86}},
+ {{0x8348f588fc156cb1, 0x6da2ba9b1a0a6d27, 0xe2262d5c87ca5ab6, 0x212cd0c1c8d589a6}},
+ {{0xd2f4d5107f18c781, 0x122ecdf2527e9d28, 0xa70a862a3d3d3341, 0x1db7778911914ce3}}},
+{{{0xddf352397c6bc26f, 0x7a97e2cc53d50113, 0x7c74f43abf79a330, 0x31ad97ad26e2adfc}},
+ {{0xb3394769dd701ab6, 0xe2b8ded419cf8da5, 0x15df4161fd2ac852, 0x7ae2ca8a017d24be}},
+ {{0xb7e817ed0920b962, 0x1e8518cc3f19da9d, 0xe491c14f25560a64, 0x1ed1fc53a6622c83}}} \ No newline at end of file
diff --git a/ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s b/ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s
new file mode 100644
index 00000000..265daf09
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_dbl_p1p1.s
@@ -0,0 +1,2975 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 pp
+
+# qhasm: input rp
+
+# qhasm: input pp
+
+# qhasm: int64 a0
+
+# qhasm: int64 a1
+
+# qhasm: int64 a2
+
+# qhasm: int64 a3
+
+# qhasm: stack64 a0_stack
+
+# qhasm: stack64 a1_stack
+
+# qhasm: stack64 a2_stack
+
+# qhasm: stack64 a3_stack
+
+# qhasm: int64 b0
+
+# qhasm: int64 b1
+
+# qhasm: int64 b2
+
+# qhasm: int64 b3
+
+# qhasm: stack64 b0_stack
+
+# qhasm: stack64 b1_stack
+
+# qhasm: stack64 b2_stack
+
+# qhasm: stack64 b3_stack
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: stack64 c0_stack
+
+# qhasm: stack64 c1_stack
+
+# qhasm: stack64 c2_stack
+
+# qhasm: stack64 c3_stack
+
+# qhasm: int64 d0
+
+# qhasm: int64 d1
+
+# qhasm: int64 d2
+
+# qhasm: int64 d3
+
+# qhasm: stack64 d0_stack
+
+# qhasm: stack64 d1_stack
+
+# qhasm: stack64 d2_stack
+
+# qhasm: stack64 d3_stack
+
+# qhasm: int64 e0
+
+# qhasm: int64 e1
+
+# qhasm: int64 e2
+
+# qhasm: int64 e3
+
+# qhasm: stack64 e0_stack
+
+# qhasm: stack64 e1_stack
+
+# qhasm: stack64 e2_stack
+
+# qhasm: stack64 e3_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: stack64 rx0_stack
+
+# qhasm: stack64 rx1_stack
+
+# qhasm: stack64 rx2_stack
+
+# qhasm: stack64 rx3_stack
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 ry4
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 rt0
+
+# qhasm: int64 rt1
+
+# qhasm: int64 rt2
+
+# qhasm: int64 rt3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: int64 squarer4
+
+# qhasm: int64 squarer5
+
+# qhasm: int64 squarer6
+
+# qhasm: int64 squarer7
+
+# qhasm: int64 squarer8
+
+# qhasm: int64 squarerax
+
+# qhasm: int64 squarerdx
+
+# qhasm: int64 squaret1
+
+# qhasm: int64 squaret2
+
+# qhasm: int64 squaret3
+
+# qhasm: int64 squarec
+
+# qhasm: int64 squarezero
+
+# qhasm: int64 squarei38
+
+# qhasm: int64 addt0
+
+# qhasm: int64 addt1
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1
+.globl crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1
+_crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1:
+crypto_sign_ed25519_amd64_64_ge25519_dbl_p1p1:
+mov %rsp,%r11
+and $31,%r11
+add $192,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 8)
+# asm 1: movq 8(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 8(<pp=%rsi),>squarerax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0)
+# asm 1: mulq 0(<pp=int64#2)
+# asm 2: mulq 0(<pp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: a1 = squarerax
+# asm 1: mov <squarerax=int64#7,>a1=int64#5
+# asm 2: mov <squarerax=%rax,>a1=%r8
+mov %rax,%r8
+
+# qhasm: a2 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>a2=int64#6
+# asm 2: mov <squarerdx=%rdx,>a2=%r9
+mov %rdx,%r9
+
+# qhasm: squarerax = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 16(<pp=%rsi),>squarerax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 8)
+# asm 1: mulq 8(<pp=int64#2)
+# asm 2: mulq 8(<pp=%rsi)
+mulq 8(%rsi)
+
+# qhasm: a3 = squarerax
+# asm 1: mov <squarerax=int64#7,>a3=int64#8
+# asm 2: mov <squarerax=%rax,>a3=%r10
+mov %rax,%r10
+
+# qhasm: squarer4 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer4=int64#9
+# asm 2: mov <squarerdx=%rdx,>squarer4=%r11
+mov %rdx,%r11
+
+# qhasm: squarerax = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<pp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 16)
+# asm 1: mulq 16(<pp=int64#2)
+# asm 2: mulq 16(<pp=%rsi)
+mulq 16(%rsi)
+
+# qhasm: squarer5 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer5=int64#10
+# asm 2: mov <squarerax=%rax,>squarer5=%r12
+mov %rax,%r12
+
+# qhasm: squarer6 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer6=int64#11
+# asm 2: mov <squarerdx=%rdx,>squarer6=%r13
+mov %rdx,%r13
+
+# qhasm: squarerax = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 16(<pp=%rsi),>squarerax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0)
+# asm 1: mulq 0(<pp=int64#2)
+# asm 2: mulq 0(<pp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: carry? a2 += squarerax
+# asm 1: add <squarerax=int64#7,<a2=int64#6
+# asm 2: add <squarerax=%rax,<a2=%r9
+add %rax,%r9
+
+# qhasm: carry? a3 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<a3=int64#8
+# asm 2: adc <squarerdx=%rdx,<a3=%r10
+adc %rdx,%r10
+
+# qhasm: squarer4 += 0 + carry
+# asm 1: adc $0,<squarer4=int64#9
+# asm 2: adc $0,<squarer4=%r11
+adc $0,%r11
+
+# qhasm: squarerax = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<pp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 8)
+# asm 1: mulq 8(<pp=int64#2)
+# asm 2: mulq 8(<pp=%rsi)
+mulq 8(%rsi)
+
+# qhasm: carry? squarer4 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer4=int64#9
+# asm 2: add <squarerax=%rax,<squarer4=%r11
+add %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarerax = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<pp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0)
+# asm 1: mulq 0(<pp=int64#2)
+# asm 2: mulq 0(<pp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: carry? a3 += squarerax
+# asm 1: add <squarerax=int64#7,<a3=int64#8
+# asm 2: add <squarerax=%rax,<a3=%r10
+add %rax,%r10
+
+# qhasm: carry? squarer4 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer4=int64#9
+# asm 2: adc <squarerdx=%rdx,<squarer4=%r11
+adc %rdx,%r11
+
+# qhasm: carry? squarer5 += 0 + carry
+# asm 1: adc $0,<squarer5=int64#10
+# asm 2: adc $0,<squarer5=%r12
+adc $0,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: carry? a1 += a1
+# asm 1: add <a1=int64#5,<a1=int64#5
+# asm 2: add <a1=%r8,<a1=%r8
+add %r8,%r8
+
+# qhasm: carry? a2 += a2 + carry
+# asm 1: adc <a2=int64#6,<a2=int64#6
+# asm 2: adc <a2=%r9,<a2=%r9
+adc %r9,%r9
+
+# qhasm: carry? a3 += a3 + carry
+# asm 1: adc <a3=int64#8,<a3=int64#8
+# asm 2: adc <a3=%r10,<a3=%r10
+adc %r10,%r10
+
+# qhasm: carry? squarer4 += squarer4 + carry
+# asm 1: adc <squarer4=int64#9,<squarer4=int64#9
+# asm 2: adc <squarer4=%r11,<squarer4=%r11
+adc %r11,%r11
+
+# qhasm: carry? squarer5 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<squarer5=int64#10
+# asm 2: adc <squarer5=%r12,<squarer5=%r12
+adc %r12,%r12
+
+# qhasm: carry? squarer6 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<squarer6=int64#11
+# asm 2: adc <squarer6=%r13,<squarer6=%r13
+adc %r13,%r13
+
+# qhasm: squarer7 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<squarer7=int64#4
+# asm 2: adc <squarer7=%rcx,<squarer7=%rcx
+adc %rcx,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 0)
+# asm 1: movq 0(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 0(<pp=%rsi),>squarerax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 0)
+# asm 1: mulq 0(<pp=int64#2)
+# asm 2: mulq 0(<pp=%rsi)
+mulq 0(%rsi)
+
+# qhasm: a0 = squarerax
+# asm 1: mov <squarerax=int64#7,>a0=int64#12
+# asm 2: mov <squarerax=%rax,>a0=%r14
+mov %rax,%r14
+
+# qhasm: squaret1 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret1=int64#13
+# asm 2: mov <squarerdx=%rdx,>squaret1=%r15
+mov %rdx,%r15
+
+# qhasm: squarerax = *(uint64 *)(pp + 8)
+# asm 1: movq 8(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 8(<pp=%rsi),>squarerax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 8)
+# asm 1: mulq 8(<pp=int64#2)
+# asm 2: mulq 8(<pp=%rsi)
+mulq 8(%rsi)
+
+# qhasm: squaret2 = squarerax
+# asm 1: mov <squarerax=int64#7,>squaret2=int64#14
+# asm 2: mov <squarerax=%rax,>squaret2=%rbx
+mov %rax,%rbx
+
+# qhasm: squaret3 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret3=int64#15
+# asm 2: mov <squarerdx=%rdx,>squaret3=%rbp
+mov %rdx,%rbp
+
+# qhasm: squarerax = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 16(<pp=%rsi),>squarerax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 16)
+# asm 1: mulq 16(<pp=int64#2)
+# asm 2: mulq 16(<pp=%rsi)
+mulq 16(%rsi)
+
+# qhasm: carry? a1 += squaret1
+# asm 1: add <squaret1=int64#13,<a1=int64#5
+# asm 2: add <squaret1=%r15,<a1=%r8
+add %r15,%r8
+
+# qhasm: carry? a2 += squaret2 + carry
+# asm 1: adc <squaret2=int64#14,<a2=int64#6
+# asm 2: adc <squaret2=%rbx,<a2=%r9
+adc %rbx,%r9
+
+# qhasm: carry? a3 += squaret3 + carry
+# asm 1: adc <squaret3=int64#15,<a3=int64#8
+# asm 2: adc <squaret3=%rbp,<a3=%r10
+adc %rbp,%r10
+
+# qhasm: carry? squarer4 += squarerax + carry
+# asm 1: adc <squarerax=int64#7,<squarer4=int64#9
+# asm 2: adc <squarerax=%rax,<squarer4=%r11
+adc %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 24(<pp=%rsi),>squarerax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 24)
+# asm 1: mulq 24(<pp=int64#2)
+# asm 2: mulq 24(<pp=%rsi)
+mulq 24(%rsi)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: squarerax = squarer4
+# asm 1: mov <squarer4=int64#9,>squarerax=int64#7
+# asm 2: mov <squarer4=%r11,>squarerax=%rax
+mov %r11,%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: squarer4 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer4=int64#9
+# asm 2: mov <squarerax=%rax,>squarer4=%r11
+mov %rax,%r11
+
+# qhasm: squarerax = squarer5
+# asm 1: mov <squarer5=int64#10,>squarerax=int64#7
+# asm 2: mov <squarer5=%r12,>squarerax=%rax
+mov %r12,%rax
+
+# qhasm: squarer5 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer5=int64#10
+# asm 2: mov <squarerdx=%rdx,>squarer5=%r12
+mov %rdx,%r12
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer5 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer5=int64#10
+# asm 2: add <squarerax=%rax,<squarer5=%r12
+add %rax,%r12
+
+# qhasm: squarerax = squarer6
+# asm 1: mov <squarer6=int64#11,>squarerax=int64#7
+# asm 2: mov <squarer6=%r13,>squarerax=%rax
+mov %r13,%rax
+
+# qhasm: squarer6 = 0
+# asm 1: mov $0,>squarer6=int64#11
+# asm 2: mov $0,>squarer6=%r13
+mov $0,%r13
+
+# qhasm: squarer6 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer6=int64#11
+# asm 2: adc <squarerdx=%rdx,<squarer6=%r13
+adc %rdx,%r13
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarerax = squarer7
+# asm 1: mov <squarer7=int64#4,>squarerax=int64#7
+# asm 2: mov <squarer7=%rcx,>squarerax=%rax
+mov %rcx,%rax
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer7 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer7=int64#4
+# asm 2: add <squarerax=%rax,<squarer7=%rcx
+add %rax,%rcx
+
+# qhasm: squarer8 = 0
+# asm 1: mov $0,>squarer8=int64#7
+# asm 2: mov $0,>squarer8=%rax
+mov $0,%rax
+
+# qhasm: squarer8 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer8=int64#7
+# asm 2: adc <squarerdx=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? a0 += squarer4
+# asm 1: add <squarer4=int64#9,<a0=int64#12
+# asm 2: add <squarer4=%r11,<a0=%r14
+add %r11,%r14
+
+# qhasm: carry? a1 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<a1=int64#5
+# asm 2: adc <squarer5=%r12,<a1=%r8
+adc %r12,%r8
+
+# qhasm: carry? a2 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<a2=int64#6
+# asm 2: adc <squarer6=%r13,<a2=%r9
+adc %r13,%r9
+
+# qhasm: carry? a3 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<a3=int64#8
+# asm 2: adc <squarer7=%rcx,<a3=%r10
+adc %rcx,%r10
+
+# qhasm: squarezero = 0
+# asm 1: mov $0,>squarezero=int64#3
+# asm 2: mov $0,>squarezero=%rdx
+mov $0,%rdx
+
+# qhasm: squarer8 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<squarer8=int64#7
+# asm 2: adc <squarezero=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: squarer8 *= 38
+# asm 1: imulq $38,<squarer8=int64#7,>squarer8=int64#4
+# asm 2: imulq $38,<squarer8=%rax,>squarer8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? a0 += squarer8
+# asm 1: add <squarer8=int64#4,<a0=int64#12
+# asm 2: add <squarer8=%rcx,<a0=%r14
+add %rcx,%r14
+
+# qhasm: carry? a1 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<a1=int64#5
+# asm 2: adc <squarezero=%rdx,<a1=%r8
+adc %rdx,%r8
+
+# qhasm: carry? a2 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<a2=int64#6
+# asm 2: adc <squarezero=%rdx,<a2=%r9
+adc %rdx,%r9
+
+# qhasm: carry? a3 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<a3=int64#8
+# asm 2: adc <squarezero=%rdx,<a3=%r10
+adc %rdx,%r10
+
+# qhasm: squarezero += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<squarezero=int64#3
+# asm 2: adc <squarezero=%rdx,<squarezero=%rdx
+adc %rdx,%rdx
+
+# qhasm: squarezero *= 38
+# asm 1: imulq $38,<squarezero=int64#3,>squarezero=int64#3
+# asm 2: imulq $38,<squarezero=%rdx,>squarezero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: a0 += squarezero
+# asm 1: add <squarezero=int64#3,<a0=int64#12
+# asm 2: add <squarezero=%rdx,<a0=%r14
+add %rdx,%r14
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#12,>a0_stack=stack64#8
+# asm 2: movq <a0=%r14,>a0_stack=56(%rsp)
+movq %r14,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#5,>a1_stack=stack64#9
+# asm 2: movq <a1=%r8,>a1_stack=64(%rsp)
+movq %r8,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#6,>a2_stack=stack64#10
+# asm 2: movq <a2=%r9,>a2_stack=72(%rsp)
+movq %r9,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#8,>a3_stack=stack64#11
+# asm 2: movq <a3=%r10,>a3_stack=80(%rsp)
+movq %r10,80(%rsp)
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 40(<pp=%rsi),>squarerax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32)
+# asm 1: mulq 32(<pp=int64#2)
+# asm 2: mulq 32(<pp=%rsi)
+mulq 32(%rsi)
+
+# qhasm: b1 = squarerax
+# asm 1: mov <squarerax=int64#7,>b1=int64#5
+# asm 2: mov <squarerax=%rax,>b1=%r8
+mov %rax,%r8
+
+# qhasm: b2 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>b2=int64#6
+# asm 2: mov <squarerdx=%rdx,>b2=%r9
+mov %rdx,%r9
+
+# qhasm: squarerax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 48(<pp=%rsi),>squarerax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 40)
+# asm 1: mulq 40(<pp=int64#2)
+# asm 2: mulq 40(<pp=%rsi)
+mulq 40(%rsi)
+
+# qhasm: b3 = squarerax
+# asm 1: mov <squarerax=int64#7,>b3=int64#8
+# asm 2: mov <squarerax=%rax,>b3=%r10
+mov %rax,%r10
+
+# qhasm: squarer4 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer4=int64#9
+# asm 2: mov <squarerdx=%rdx,>squarer4=%r11
+mov %rdx,%r11
+
+# qhasm: squarerax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 56(<pp=%rsi),>squarerax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 48)
+# asm 1: mulq 48(<pp=int64#2)
+# asm 2: mulq 48(<pp=%rsi)
+mulq 48(%rsi)
+
+# qhasm: squarer5 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer5=int64#10
+# asm 2: mov <squarerax=%rax,>squarer5=%r12
+mov %rax,%r12
+
+# qhasm: squarer6 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer6=int64#11
+# asm 2: mov <squarerdx=%rdx,>squarer6=%r13
+mov %rdx,%r13
+
+# qhasm: squarerax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 48(<pp=%rsi),>squarerax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32)
+# asm 1: mulq 32(<pp=int64#2)
+# asm 2: mulq 32(<pp=%rsi)
+mulq 32(%rsi)
+
+# qhasm: carry? b2 += squarerax
+# asm 1: add <squarerax=int64#7,<b2=int64#6
+# asm 2: add <squarerax=%rax,<b2=%r9
+add %rax,%r9
+
+# qhasm: carry? b3 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<b3=int64#8
+# asm 2: adc <squarerdx=%rdx,<b3=%r10
+adc %rdx,%r10
+
+# qhasm: squarer4 += 0 + carry
+# asm 1: adc $0,<squarer4=int64#9
+# asm 2: adc $0,<squarer4=%r11
+adc $0,%r11
+
+# qhasm: squarerax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 56(<pp=%rsi),>squarerax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 40)
+# asm 1: mulq 40(<pp=int64#2)
+# asm 2: mulq 40(<pp=%rsi)
+mulq 40(%rsi)
+
+# qhasm: carry? squarer4 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer4=int64#9
+# asm 2: add <squarerax=%rax,<squarer4=%r11
+add %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarerax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 56(<pp=%rsi),>squarerax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32)
+# asm 1: mulq 32(<pp=int64#2)
+# asm 2: mulq 32(<pp=%rsi)
+mulq 32(%rsi)
+
+# qhasm: carry? b3 += squarerax
+# asm 1: add <squarerax=int64#7,<b3=int64#8
+# asm 2: add <squarerax=%rax,<b3=%r10
+add %rax,%r10
+
+# qhasm: carry? squarer4 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer4=int64#9
+# asm 2: adc <squarerdx=%rdx,<squarer4=%r11
+adc %rdx,%r11
+
+# qhasm: carry? squarer5 += 0 + carry
+# asm 1: adc $0,<squarer5=int64#10
+# asm 2: adc $0,<squarer5=%r12
+adc $0,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: carry? b1 += b1
+# asm 1: add <b1=int64#5,<b1=int64#5
+# asm 2: add <b1=%r8,<b1=%r8
+add %r8,%r8
+
+# qhasm: carry? b2 += b2 + carry
+# asm 1: adc <b2=int64#6,<b2=int64#6
+# asm 2: adc <b2=%r9,<b2=%r9
+adc %r9,%r9
+
+# qhasm: carry? b3 += b3 + carry
+# asm 1: adc <b3=int64#8,<b3=int64#8
+# asm 2: adc <b3=%r10,<b3=%r10
+adc %r10,%r10
+
+# qhasm: carry? squarer4 += squarer4 + carry
+# asm 1: adc <squarer4=int64#9,<squarer4=int64#9
+# asm 2: adc <squarer4=%r11,<squarer4=%r11
+adc %r11,%r11
+
+# qhasm: carry? squarer5 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<squarer5=int64#10
+# asm 2: adc <squarer5=%r12,<squarer5=%r12
+adc %r12,%r12
+
+# qhasm: carry? squarer6 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<squarer6=int64#11
+# asm 2: adc <squarer6=%r13,<squarer6=%r13
+adc %r13,%r13
+
+# qhasm: squarer7 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<squarer7=int64#4
+# asm 2: adc <squarer7=%rcx,<squarer7=%rcx
+adc %rcx,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 32(<pp=%rsi),>squarerax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 32)
+# asm 1: mulq 32(<pp=int64#2)
+# asm 2: mulq 32(<pp=%rsi)
+mulq 32(%rsi)
+
+# qhasm: b0 = squarerax
+# asm 1: mov <squarerax=int64#7,>b0=int64#12
+# asm 2: mov <squarerax=%rax,>b0=%r14
+mov %rax,%r14
+
+# qhasm: squaret1 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret1=int64#13
+# asm 2: mov <squarerdx=%rdx,>squaret1=%r15
+mov %rdx,%r15
+
+# qhasm: squarerax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 40(<pp=%rsi),>squarerax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 40)
+# asm 1: mulq 40(<pp=int64#2)
+# asm 2: mulq 40(<pp=%rsi)
+mulq 40(%rsi)
+
+# qhasm: squaret2 = squarerax
+# asm 1: mov <squarerax=int64#7,>squaret2=int64#14
+# asm 2: mov <squarerax=%rax,>squaret2=%rbx
+mov %rax,%rbx
+
+# qhasm: squaret3 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret3=int64#15
+# asm 2: mov <squarerdx=%rdx,>squaret3=%rbp
+mov %rdx,%rbp
+
+# qhasm: squarerax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 48(<pp=%rsi),>squarerax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 48)
+# asm 1: mulq 48(<pp=int64#2)
+# asm 2: mulq 48(<pp=%rsi)
+mulq 48(%rsi)
+
+# qhasm: carry? b1 += squaret1
+# asm 1: add <squaret1=int64#13,<b1=int64#5
+# asm 2: add <squaret1=%r15,<b1=%r8
+add %r15,%r8
+
+# qhasm: carry? b2 += squaret2 + carry
+# asm 1: adc <squaret2=int64#14,<b2=int64#6
+# asm 2: adc <squaret2=%rbx,<b2=%r9
+adc %rbx,%r9
+
+# qhasm: carry? b3 += squaret3 + carry
+# asm 1: adc <squaret3=int64#15,<b3=int64#8
+# asm 2: adc <squaret3=%rbp,<b3=%r10
+adc %rbp,%r10
+
+# qhasm: carry? squarer4 += squarerax + carry
+# asm 1: adc <squarerax=int64#7,<squarer4=int64#9
+# asm 2: adc <squarerax=%rax,<squarer4=%r11
+adc %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 56(<pp=%rsi),>squarerax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 56)
+# asm 1: mulq 56(<pp=int64#2)
+# asm 2: mulq 56(<pp=%rsi)
+mulq 56(%rsi)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: squarerax = squarer4
+# asm 1: mov <squarer4=int64#9,>squarerax=int64#7
+# asm 2: mov <squarer4=%r11,>squarerax=%rax
+mov %r11,%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: squarer4 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer4=int64#9
+# asm 2: mov <squarerax=%rax,>squarer4=%r11
+mov %rax,%r11
+
+# qhasm: squarerax = squarer5
+# asm 1: mov <squarer5=int64#10,>squarerax=int64#7
+# asm 2: mov <squarer5=%r12,>squarerax=%rax
+mov %r12,%rax
+
+# qhasm: squarer5 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer5=int64#10
+# asm 2: mov <squarerdx=%rdx,>squarer5=%r12
+mov %rdx,%r12
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer5 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer5=int64#10
+# asm 2: add <squarerax=%rax,<squarer5=%r12
+add %rax,%r12
+
+# qhasm: squarerax = squarer6
+# asm 1: mov <squarer6=int64#11,>squarerax=int64#7
+# asm 2: mov <squarer6=%r13,>squarerax=%rax
+mov %r13,%rax
+
+# qhasm: squarer6 = 0
+# asm 1: mov $0,>squarer6=int64#11
+# asm 2: mov $0,>squarer6=%r13
+mov $0,%r13
+
+# qhasm: squarer6 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer6=int64#11
+# asm 2: adc <squarerdx=%rdx,<squarer6=%r13
+adc %rdx,%r13
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarerax = squarer7
+# asm 1: mov <squarer7=int64#4,>squarerax=int64#7
+# asm 2: mov <squarer7=%rcx,>squarerax=%rax
+mov %rcx,%rax
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer7 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer7=int64#4
+# asm 2: add <squarerax=%rax,<squarer7=%rcx
+add %rax,%rcx
+
+# qhasm: squarer8 = 0
+# asm 1: mov $0,>squarer8=int64#7
+# asm 2: mov $0,>squarer8=%rax
+mov $0,%rax
+
+# qhasm: squarer8 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer8=int64#7
+# asm 2: adc <squarerdx=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? b0 += squarer4
+# asm 1: add <squarer4=int64#9,<b0=int64#12
+# asm 2: add <squarer4=%r11,<b0=%r14
+add %r11,%r14
+
+# qhasm: carry? b1 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<b1=int64#5
+# asm 2: adc <squarer5=%r12,<b1=%r8
+adc %r12,%r8
+
+# qhasm: carry? b2 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<b2=int64#6
+# asm 2: adc <squarer6=%r13,<b2=%r9
+adc %r13,%r9
+
+# qhasm: carry? b3 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<b3=int64#8
+# asm 2: adc <squarer7=%rcx,<b3=%r10
+adc %rcx,%r10
+
+# qhasm: squarezero = 0
+# asm 1: mov $0,>squarezero=int64#3
+# asm 2: mov $0,>squarezero=%rdx
+mov $0,%rdx
+
+# qhasm: squarer8 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<squarer8=int64#7
+# asm 2: adc <squarezero=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: squarer8 *= 38
+# asm 1: imulq $38,<squarer8=int64#7,>squarer8=int64#4
+# asm 2: imulq $38,<squarer8=%rax,>squarer8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? b0 += squarer8
+# asm 1: add <squarer8=int64#4,<b0=int64#12
+# asm 2: add <squarer8=%rcx,<b0=%r14
+add %rcx,%r14
+
+# qhasm: carry? b1 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<b1=int64#5
+# asm 2: adc <squarezero=%rdx,<b1=%r8
+adc %rdx,%r8
+
+# qhasm: carry? b2 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<b2=int64#6
+# asm 2: adc <squarezero=%rdx,<b2=%r9
+adc %rdx,%r9
+
+# qhasm: carry? b3 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<b3=int64#8
+# asm 2: adc <squarezero=%rdx,<b3=%r10
+adc %rdx,%r10
+
+# qhasm: squarezero += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<squarezero=int64#3
+# asm 2: adc <squarezero=%rdx,<squarezero=%rdx
+adc %rdx,%rdx
+
+# qhasm: squarezero *= 38
+# asm 1: imulq $38,<squarezero=int64#3,>squarezero=int64#3
+# asm 2: imulq $38,<squarezero=%rdx,>squarezero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: b0 += squarezero
+# asm 1: add <squarezero=int64#3,<b0=int64#12
+# asm 2: add <squarezero=%rdx,<b0=%r14
+add %rdx,%r14
+
+# qhasm: b0_stack = b0
+# asm 1: movq <b0=int64#12,>b0_stack=stack64#12
+# asm 2: movq <b0=%r14,>b0_stack=88(%rsp)
+movq %r14,88(%rsp)
+
+# qhasm: b1_stack = b1
+# asm 1: movq <b1=int64#5,>b1_stack=stack64#13
+# asm 2: movq <b1=%r8,>b1_stack=96(%rsp)
+movq %r8,96(%rsp)
+
+# qhasm: b2_stack = b2
+# asm 1: movq <b2=int64#6,>b2_stack=stack64#14
+# asm 2: movq <b2=%r9,>b2_stack=104(%rsp)
+movq %r9,104(%rsp)
+
+# qhasm: b3_stack = b3
+# asm 1: movq <b3=int64#8,>b3_stack=stack64#15
+# asm 2: movq <b3=%r10,>b3_stack=112(%rsp)
+movq %r10,112(%rsp)
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 72(<pp=%rsi),>squarerax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64)
+# asm 1: mulq 64(<pp=int64#2)
+# asm 2: mulq 64(<pp=%rsi)
+mulq 64(%rsi)
+
+# qhasm: c1 = squarerax
+# asm 1: mov <squarerax=int64#7,>c1=int64#5
+# asm 2: mov <squarerax=%rax,>c1=%r8
+mov %rax,%r8
+
+# qhasm: c2 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>c2=int64#6
+# asm 2: mov <squarerdx=%rdx,>c2=%r9
+mov %rdx,%r9
+
+# qhasm: squarerax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 80(<pp=%rsi),>squarerax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 72)
+# asm 1: mulq 72(<pp=int64#2)
+# asm 2: mulq 72(<pp=%rsi)
+mulq 72(%rsi)
+
+# qhasm: c3 = squarerax
+# asm 1: mov <squarerax=int64#7,>c3=int64#8
+# asm 2: mov <squarerax=%rax,>c3=%r10
+mov %rax,%r10
+
+# qhasm: squarer4 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer4=int64#9
+# asm 2: mov <squarerdx=%rdx,>squarer4=%r11
+mov %rdx,%r11
+
+# qhasm: squarerax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 88(<pp=%rsi),>squarerax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 80)
+# asm 1: mulq 80(<pp=int64#2)
+# asm 2: mulq 80(<pp=%rsi)
+mulq 80(%rsi)
+
+# qhasm: squarer5 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer5=int64#10
+# asm 2: mov <squarerax=%rax,>squarer5=%r12
+mov %rax,%r12
+
+# qhasm: squarer6 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer6=int64#11
+# asm 2: mov <squarerdx=%rdx,>squarer6=%r13
+mov %rdx,%r13
+
+# qhasm: squarerax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 80(<pp=%rsi),>squarerax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64)
+# asm 1: mulq 64(<pp=int64#2)
+# asm 2: mulq 64(<pp=%rsi)
+mulq 64(%rsi)
+
+# qhasm: carry? c2 += squarerax
+# asm 1: add <squarerax=int64#7,<c2=int64#6
+# asm 2: add <squarerax=%rax,<c2=%r9
+add %rax,%r9
+
+# qhasm: carry? c3 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<c3=int64#8
+# asm 2: adc <squarerdx=%rdx,<c3=%r10
+adc %rdx,%r10
+
+# qhasm: squarer4 += 0 + carry
+# asm 1: adc $0,<squarer4=int64#9
+# asm 2: adc $0,<squarer4=%r11
+adc $0,%r11
+
+# qhasm: squarerax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 88(<pp=%rsi),>squarerax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 72)
+# asm 1: mulq 72(<pp=int64#2)
+# asm 2: mulq 72(<pp=%rsi)
+mulq 72(%rsi)
+
+# qhasm: carry? squarer4 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer4=int64#9
+# asm 2: add <squarerax=%rax,<squarer4=%r11
+add %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarerax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 88(<pp=%rsi),>squarerax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64)
+# asm 1: mulq 64(<pp=int64#2)
+# asm 2: mulq 64(<pp=%rsi)
+mulq 64(%rsi)
+
+# qhasm: carry? c3 += squarerax
+# asm 1: add <squarerax=int64#7,<c3=int64#8
+# asm 2: add <squarerax=%rax,<c3=%r10
+add %rax,%r10
+
+# qhasm: carry? squarer4 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer4=int64#9
+# asm 2: adc <squarerdx=%rdx,<squarer4=%r11
+adc %rdx,%r11
+
+# qhasm: carry? squarer5 += 0 + carry
+# asm 1: adc $0,<squarer5=int64#10
+# asm 2: adc $0,<squarer5=%r12
+adc $0,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: carry? c1 += c1
+# asm 1: add <c1=int64#5,<c1=int64#5
+# asm 2: add <c1=%r8,<c1=%r8
+add %r8,%r8
+
+# qhasm: carry? c2 += c2 + carry
+# asm 1: adc <c2=int64#6,<c2=int64#6
+# asm 2: adc <c2=%r9,<c2=%r9
+adc %r9,%r9
+
+# qhasm: carry? c3 += c3 + carry
+# asm 1: adc <c3=int64#8,<c3=int64#8
+# asm 2: adc <c3=%r10,<c3=%r10
+adc %r10,%r10
+
+# qhasm: carry? squarer4 += squarer4 + carry
+# asm 1: adc <squarer4=int64#9,<squarer4=int64#9
+# asm 2: adc <squarer4=%r11,<squarer4=%r11
+adc %r11,%r11
+
+# qhasm: carry? squarer5 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<squarer5=int64#10
+# asm 2: adc <squarer5=%r12,<squarer5=%r12
+adc %r12,%r12
+
+# qhasm: carry? squarer6 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<squarer6=int64#11
+# asm 2: adc <squarer6=%r13,<squarer6=%r13
+adc %r13,%r13
+
+# qhasm: squarer7 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<squarer7=int64#4
+# asm 2: adc <squarer7=%rcx,<squarer7=%rcx
+adc %rcx,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 64(<pp=%rsi),>squarerax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 64)
+# asm 1: mulq 64(<pp=int64#2)
+# asm 2: mulq 64(<pp=%rsi)
+mulq 64(%rsi)
+
+# qhasm: c0 = squarerax
+# asm 1: mov <squarerax=int64#7,>c0=int64#12
+# asm 2: mov <squarerax=%rax,>c0=%r14
+mov %rax,%r14
+
+# qhasm: squaret1 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret1=int64#13
+# asm 2: mov <squarerdx=%rdx,>squaret1=%r15
+mov %rdx,%r15
+
+# qhasm: squarerax = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 72(<pp=%rsi),>squarerax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 72)
+# asm 1: mulq 72(<pp=int64#2)
+# asm 2: mulq 72(<pp=%rsi)
+mulq 72(%rsi)
+
+# qhasm: squaret2 = squarerax
+# asm 1: mov <squarerax=int64#7,>squaret2=int64#14
+# asm 2: mov <squarerax=%rax,>squaret2=%rbx
+mov %rax,%rbx
+
+# qhasm: squaret3 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret3=int64#15
+# asm 2: mov <squarerdx=%rdx,>squaret3=%rbp
+mov %rdx,%rbp
+
+# qhasm: squarerax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 80(<pp=%rsi),>squarerax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 80)
+# asm 1: mulq 80(<pp=int64#2)
+# asm 2: mulq 80(<pp=%rsi)
+mulq 80(%rsi)
+
+# qhasm: carry? c1 += squaret1
+# asm 1: add <squaret1=int64#13,<c1=int64#5
+# asm 2: add <squaret1=%r15,<c1=%r8
+add %r15,%r8
+
+# qhasm: carry? c2 += squaret2 + carry
+# asm 1: adc <squaret2=int64#14,<c2=int64#6
+# asm 2: adc <squaret2=%rbx,<c2=%r9
+adc %rbx,%r9
+
+# qhasm: carry? c3 += squaret3 + carry
+# asm 1: adc <squaret3=int64#15,<c3=int64#8
+# asm 2: adc <squaret3=%rbp,<c3=%r10
+adc %rbp,%r10
+
+# qhasm: carry? squarer4 += squarerax + carry
+# asm 1: adc <squarerax=int64#7,<squarer4=int64#9
+# asm 2: adc <squarerax=%rax,<squarer4=%r11
+adc %rax,%r11
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r12
+adc %rdx,%r12
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#11
+# asm 2: adc $0,<squarer6=%r13
+adc $0,%r13
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#4
+# asm 2: adc $0,<squarer7=%rcx
+adc $0,%rcx
+
+# qhasm: squarerax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>squarerax=int64#7
+# asm 2: movq 88(<pp=%rsi),>squarerax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)(pp + 88)
+# asm 1: mulq 88(<pp=int64#2)
+# asm 2: mulq 88(<pp=%rsi)
+mulq 88(%rsi)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: squarerax = squarer4
+# asm 1: mov <squarer4=int64#9,>squarerax=int64#7
+# asm 2: mov <squarer4=%r11,>squarerax=%rax
+mov %r11,%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: squarer4 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer4=int64#9
+# asm 2: mov <squarerax=%rax,>squarer4=%r11
+mov %rax,%r11
+
+# qhasm: squarerax = squarer5
+# asm 1: mov <squarer5=int64#10,>squarerax=int64#7
+# asm 2: mov <squarer5=%r12,>squarerax=%rax
+mov %r12,%rax
+
+# qhasm: squarer5 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer5=int64#10
+# asm 2: mov <squarerdx=%rdx,>squarer5=%r12
+mov %rdx,%r12
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer5 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer5=int64#10
+# asm 2: add <squarerax=%rax,<squarer5=%r12
+add %rax,%r12
+
+# qhasm: squarerax = squarer6
+# asm 1: mov <squarer6=int64#11,>squarerax=int64#7
+# asm 2: mov <squarer6=%r13,>squarerax=%rax
+mov %r13,%rax
+
+# qhasm: squarer6 = 0
+# asm 1: mov $0,>squarer6=int64#11
+# asm 2: mov $0,>squarer6=%r13
+mov $0,%r13
+
+# qhasm: squarer6 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer6=int64#11
+# asm 2: adc <squarerdx=%rdx,<squarer6=%r13
+adc %rdx,%r13
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#11
+# asm 2: add <squarerax=%rax,<squarer6=%r13
+add %rax,%r13
+
+# qhasm: squarerax = squarer7
+# asm 1: mov <squarer7=int64#4,>squarerax=int64#7
+# asm 2: mov <squarer7=%rcx,>squarerax=%rax
+mov %rcx,%rax
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#4
+# asm 2: mov $0,>squarer7=%rcx
+mov $0,%rcx
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#4
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rcx
+adc %rdx,%rcx
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer7 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer7=int64#4
+# asm 2: add <squarerax=%rax,<squarer7=%rcx
+add %rax,%rcx
+
+# qhasm: squarer8 = 0
+# asm 1: mov $0,>squarer8=int64#7
+# asm 2: mov $0,>squarer8=%rax
+mov $0,%rax
+
+# qhasm: squarer8 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer8=int64#7
+# asm 2: adc <squarerdx=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? c0 += squarer4
+# asm 1: add <squarer4=int64#9,<c0=int64#12
+# asm 2: add <squarer4=%r11,<c0=%r14
+add %r11,%r14
+
+# qhasm: carry? c1 += squarer5 + carry
+# asm 1: adc <squarer5=int64#10,<c1=int64#5
+# asm 2: adc <squarer5=%r12,<c1=%r8
+adc %r12,%r8
+
+# qhasm: carry? c2 += squarer6 + carry
+# asm 1: adc <squarer6=int64#11,<c2=int64#6
+# asm 2: adc <squarer6=%r13,<c2=%r9
+adc %r13,%r9
+
+# qhasm: carry? c3 += squarer7 + carry
+# asm 1: adc <squarer7=int64#4,<c3=int64#8
+# asm 2: adc <squarer7=%rcx,<c3=%r10
+adc %rcx,%r10
+
+# qhasm: squarezero = 0
+# asm 1: mov $0,>squarezero=int64#3
+# asm 2: mov $0,>squarezero=%rdx
+mov $0,%rdx
+
+# qhasm: squarer8 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<squarer8=int64#7
+# asm 2: adc <squarezero=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: squarer8 *= 38
+# asm 1: imulq $38,<squarer8=int64#7,>squarer8=int64#4
+# asm 2: imulq $38,<squarer8=%rax,>squarer8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? c0 += squarer8
+# asm 1: add <squarer8=int64#4,<c0=int64#12
+# asm 2: add <squarer8=%rcx,<c0=%r14
+add %rcx,%r14
+
+# qhasm: carry? c1 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<c1=int64#5
+# asm 2: adc <squarezero=%rdx,<c1=%r8
+adc %rdx,%r8
+
+# qhasm: carry? c2 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<c2=int64#6
+# asm 2: adc <squarezero=%rdx,<c2=%r9
+adc %rdx,%r9
+
+# qhasm: carry? c3 += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<c3=int64#8
+# asm 2: adc <squarezero=%rdx,<c3=%r10
+adc %rdx,%r10
+
+# qhasm: squarezero += squarezero + carry
+# asm 1: adc <squarezero=int64#3,<squarezero=int64#3
+# asm 2: adc <squarezero=%rdx,<squarezero=%rdx
+adc %rdx,%rdx
+
+# qhasm: squarezero *= 38
+# asm 1: imulq $38,<squarezero=int64#3,>squarezero=int64#3
+# asm 2: imulq $38,<squarezero=%rdx,>squarezero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: c0 += squarezero
+# asm 1: add <squarezero=int64#3,<c0=int64#12
+# asm 2: add <squarezero=%rdx,<c0=%r14
+add %rdx,%r14
+
+# qhasm: carry? c0 += c0
+# asm 1: add <c0=int64#12,<c0=int64#12
+# asm 2: add <c0=%r14,<c0=%r14
+add %r14,%r14
+
+# qhasm: carry? c1 += c1 + carry
+# asm 1: adc <c1=int64#5,<c1=int64#5
+# asm 2: adc <c1=%r8,<c1=%r8
+adc %r8,%r8
+
+# qhasm: carry? c2 += c2 + carry
+# asm 1: adc <c2=int64#6,<c2=int64#6
+# asm 2: adc <c2=%r9,<c2=%r9
+adc %r9,%r9
+
+# qhasm: carry? c3 += c3 + carry
+# asm 1: adc <c3=int64#8,<c3=int64#8
+# asm 2: adc <c3=%r10,<c3=%r10
+adc %r10,%r10
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#3
+# asm 2: mov $0,>addt0=%rdx
+mov $0,%rdx
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#4
+# asm 2: mov $38,>addt1=%rcx
+mov $38,%rcx
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#3,<addt1=int64#4
+# asm 2: cmovae <addt0=%rdx,<addt1=%rcx
+cmovae %rdx,%rcx
+
+# qhasm: carry? c0 += addt1
+# asm 1: add <addt1=int64#4,<c0=int64#12
+# asm 2: add <addt1=%rcx,<c0=%r14
+add %rcx,%r14
+
+# qhasm: carry? c1 += addt0 + carry
+# asm 1: adc <addt0=int64#3,<c1=int64#5
+# asm 2: adc <addt0=%rdx,<c1=%r8
+adc %rdx,%r8
+
+# qhasm: carry? c2 += addt0 + carry
+# asm 1: adc <addt0=int64#3,<c2=int64#6
+# asm 2: adc <addt0=%rdx,<c2=%r9
+adc %rdx,%r9
+
+# qhasm: carry? c3 += addt0 + carry
+# asm 1: adc <addt0=int64#3,<c3=int64#8
+# asm 2: adc <addt0=%rdx,<c3=%r10
+adc %rdx,%r10
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#4,<addt0=int64#3
+# asm 2: cmovc <addt1=%rcx,<addt0=%rdx
+cmovc %rcx,%rdx
+
+# qhasm: c0 += addt0
+# asm 1: add <addt0=int64#3,<c0=int64#12
+# asm 2: add <addt0=%rdx,<c0=%r14
+add %rdx,%r14
+
+# qhasm: c0_stack = c0
+# asm 1: movq <c0=int64#12,>c0_stack=stack64#16
+# asm 2: movq <c0=%r14,>c0_stack=120(%rsp)
+movq %r14,120(%rsp)
+
+# qhasm: c1_stack = c1
+# asm 1: movq <c1=int64#5,>c1_stack=stack64#17
+# asm 2: movq <c1=%r8,>c1_stack=128(%rsp)
+movq %r8,128(%rsp)
+
+# qhasm: c2_stack = c2
+# asm 1: movq <c2=int64#6,>c2_stack=stack64#18
+# asm 2: movq <c2=%r9,>c2_stack=136(%rsp)
+movq %r9,136(%rsp)
+
+# qhasm: c3_stack = c3
+# asm 1: movq <c3=int64#8,>c3_stack=stack64#19
+# asm 2: movq <c3=%r10,>c3_stack=144(%rsp)
+movq %r10,144(%rsp)
+
+# qhasm: d0 = 0
+# asm 1: mov $0,>d0=int64#3
+# asm 2: mov $0,>d0=%rdx
+mov $0,%rdx
+
+# qhasm: d1 = 0
+# asm 1: mov $0,>d1=int64#4
+# asm 2: mov $0,>d1=%rcx
+mov $0,%rcx
+
+# qhasm: d2 = 0
+# asm 1: mov $0,>d2=int64#5
+# asm 2: mov $0,>d2=%r8
+mov $0,%r8
+
+# qhasm: d3 = 0
+# asm 1: mov $0,>d3=int64#6
+# asm 2: mov $0,>d3=%r9
+mov $0,%r9
+
+# qhasm: carry? d0 -= a0_stack
+# asm 1: subq <a0_stack=stack64#8,<d0=int64#3
+# asm 2: subq <a0_stack=56(%rsp),<d0=%rdx
+subq 56(%rsp),%rdx
+
+# qhasm: carry? d1 -= a1_stack - carry
+# asm 1: sbbq <a1_stack=stack64#9,<d1=int64#4
+# asm 2: sbbq <a1_stack=64(%rsp),<d1=%rcx
+sbbq 64(%rsp),%rcx
+
+# qhasm: carry? d2 -= a2_stack - carry
+# asm 1: sbbq <a2_stack=stack64#10,<d2=int64#5
+# asm 2: sbbq <a2_stack=72(%rsp),<d2=%r8
+sbbq 72(%rsp),%r8
+
+# qhasm: carry? d3 -= a3_stack - carry
+# asm 1: sbbq <a3_stack=stack64#11,<d3=int64#6
+# asm 2: sbbq <a3_stack=80(%rsp),<d3=%r9
+sbbq 80(%rsp),%r9
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#7
+# asm 2: mov $0,>subt0=%rax
+mov $0,%rax
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#8
+# asm 2: mov $38,>subt1=%r10
+mov $38,%r10
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#7,<subt1=int64#8
+# asm 2: cmovae <subt0=%rax,<subt1=%r10
+cmovae %rax,%r10
+
+# qhasm: carry? d0 -= subt1
+# asm 1: sub <subt1=int64#8,<d0=int64#3
+# asm 2: sub <subt1=%r10,<d0=%rdx
+sub %r10,%rdx
+
+# qhasm: carry? d1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#7,<d1=int64#4
+# asm 2: sbb <subt0=%rax,<d1=%rcx
+sbb %rax,%rcx
+
+# qhasm: carry? d2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#7,<d2=int64#5
+# asm 2: sbb <subt0=%rax,<d2=%r8
+sbb %rax,%r8
+
+# qhasm: carry? d3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#7,<d3=int64#6
+# asm 2: sbb <subt0=%rax,<d3=%r9
+sbb %rax,%r9
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#8,<subt0=int64#7
+# asm 2: cmovc <subt1=%r10,<subt0=%rax
+cmovc %r10,%rax
+
+# qhasm: d0 -= subt0
+# asm 1: sub <subt0=int64#7,<d0=int64#3
+# asm 2: sub <subt0=%rax,<d0=%rdx
+sub %rax,%rdx
+
+# qhasm: d0_stack = d0
+# asm 1: movq <d0=int64#3,>d0_stack=stack64#8
+# asm 2: movq <d0=%rdx,>d0_stack=56(%rsp)
+movq %rdx,56(%rsp)
+
+# qhasm: d1_stack = d1
+# asm 1: movq <d1=int64#4,>d1_stack=stack64#9
+# asm 2: movq <d1=%rcx,>d1_stack=64(%rsp)
+movq %rcx,64(%rsp)
+
+# qhasm: d2_stack = d2
+# asm 1: movq <d2=int64#5,>d2_stack=stack64#10
+# asm 2: movq <d2=%r8,>d2_stack=72(%rsp)
+movq %r8,72(%rsp)
+
+# qhasm: d3_stack = d3
+# asm 1: movq <d3=int64#6,>d3_stack=stack64#11
+# asm 2: movq <d3=%r9,>d3_stack=80(%rsp)
+movq %r9,80(%rsp)
+
+# qhasm: e0 = 0
+# asm 1: mov $0,>e0=int64#7
+# asm 2: mov $0,>e0=%rax
+mov $0,%rax
+
+# qhasm: e1 = 0
+# asm 1: mov $0,>e1=int64#8
+# asm 2: mov $0,>e1=%r10
+mov $0,%r10
+
+# qhasm: e2 = 0
+# asm 1: mov $0,>e2=int64#9
+# asm 2: mov $0,>e2=%r11
+mov $0,%r11
+
+# qhasm: e3 = 0
+# asm 1: mov $0,>e3=int64#10
+# asm 2: mov $0,>e3=%r12
+mov $0,%r12
+
+# qhasm: carry? e0 -= b0_stack
+# asm 1: subq <b0_stack=stack64#12,<e0=int64#7
+# asm 2: subq <b0_stack=88(%rsp),<e0=%rax
+subq 88(%rsp),%rax
+
+# qhasm: carry? e1 -= b1_stack - carry
+# asm 1: sbbq <b1_stack=stack64#13,<e1=int64#8
+# asm 2: sbbq <b1_stack=96(%rsp),<e1=%r10
+sbbq 96(%rsp),%r10
+
+# qhasm: carry? e2 -= b2_stack - carry
+# asm 1: sbbq <b2_stack=stack64#14,<e2=int64#9
+# asm 2: sbbq <b2_stack=104(%rsp),<e2=%r11
+sbbq 104(%rsp),%r11
+
+# qhasm: carry? e3 -= b3_stack - carry
+# asm 1: sbbq <b3_stack=stack64#15,<e3=int64#10
+# asm 2: sbbq <b3_stack=112(%rsp),<e3=%r12
+sbbq 112(%rsp),%r12
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#11
+# asm 2: mov $0,>subt0=%r13
+mov $0,%r13
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#12
+# asm 2: mov $38,>subt1=%r14
+mov $38,%r14
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#11,<subt1=int64#12
+# asm 2: cmovae <subt0=%r13,<subt1=%r14
+cmovae %r13,%r14
+
+# qhasm: carry? e0 -= subt1
+# asm 1: sub <subt1=int64#12,<e0=int64#7
+# asm 2: sub <subt1=%r14,<e0=%rax
+sub %r14,%rax
+
+# qhasm: carry? e1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<e1=int64#8
+# asm 2: sbb <subt0=%r13,<e1=%r10
+sbb %r13,%r10
+
+# qhasm: carry? e2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<e2=int64#9
+# asm 2: sbb <subt0=%r13,<e2=%r11
+sbb %r13,%r11
+
+# qhasm: carry? e3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<e3=int64#10
+# asm 2: sbb <subt0=%r13,<e3=%r12
+sbb %r13,%r12
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#12,<subt0=int64#11
+# asm 2: cmovc <subt1=%r14,<subt0=%r13
+cmovc %r14,%r13
+
+# qhasm: e0 -= subt0
+# asm 1: sub <subt0=int64#11,<e0=int64#7
+# asm 2: sub <subt0=%r13,<e0=%rax
+sub %r13,%rax
+
+# qhasm: e0_stack = e0
+# asm 1: movq <e0=int64#7,>e0_stack=stack64#20
+# asm 2: movq <e0=%rax,>e0_stack=152(%rsp)
+movq %rax,152(%rsp)
+
+# qhasm: e1_stack = e1
+# asm 1: movq <e1=int64#8,>e1_stack=stack64#21
+# asm 2: movq <e1=%r10,>e1_stack=160(%rsp)
+movq %r10,160(%rsp)
+
+# qhasm: e2_stack = e2
+# asm 1: movq <e2=int64#9,>e2_stack=stack64#22
+# asm 2: movq <e2=%r11,>e2_stack=168(%rsp)
+movq %r11,168(%rsp)
+
+# qhasm: e3_stack = e3
+# asm 1: movq <e3=int64#10,>e3_stack=stack64#23
+# asm 2: movq <e3=%r12,>e3_stack=176(%rsp)
+movq %r12,176(%rsp)
+
+# qhasm: rz0 = d0
+# asm 1: mov <d0=int64#3,>rz0=int64#7
+# asm 2: mov <d0=%rdx,>rz0=%rax
+mov %rdx,%rax
+
+# qhasm: rz1 = d1
+# asm 1: mov <d1=int64#4,>rz1=int64#8
+# asm 2: mov <d1=%rcx,>rz1=%r10
+mov %rcx,%r10
+
+# qhasm: rz2 = d2
+# asm 1: mov <d2=int64#5,>rz2=int64#9
+# asm 2: mov <d2=%r8,>rz2=%r11
+mov %r8,%r11
+
+# qhasm: rz3 = d3
+# asm 1: mov <d3=int64#6,>rz3=int64#10
+# asm 2: mov <d3=%r9,>rz3=%r12
+mov %r9,%r12
+
+# qhasm: carry? rz0 += b0_stack
+# asm 1: addq <b0_stack=stack64#12,<rz0=int64#7
+# asm 2: addq <b0_stack=88(%rsp),<rz0=%rax
+addq 88(%rsp),%rax
+
+# qhasm: carry? rz1 += b1_stack + carry
+# asm 1: adcq <b1_stack=stack64#13,<rz1=int64#8
+# asm 2: adcq <b1_stack=96(%rsp),<rz1=%r10
+adcq 96(%rsp),%r10
+
+# qhasm: carry? rz2 += b2_stack + carry
+# asm 1: adcq <b2_stack=stack64#14,<rz2=int64#9
+# asm 2: adcq <b2_stack=104(%rsp),<rz2=%r11
+adcq 104(%rsp),%r11
+
+# qhasm: carry? rz3 += b3_stack + carry
+# asm 1: adcq <b3_stack=stack64#15,<rz3=int64#10
+# asm 2: adcq <b3_stack=112(%rsp),<rz3=%r12
+adcq 112(%rsp),%r12
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#11
+# asm 2: mov $0,>addt0=%r13
+mov $0,%r13
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#12
+# asm 2: mov $38,>addt1=%r14
+mov $38,%r14
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#11,<addt1=int64#12
+# asm 2: cmovae <addt0=%r13,<addt1=%r14
+cmovae %r13,%r14
+
+# qhasm: carry? rz0 += addt1
+# asm 1: add <addt1=int64#12,<rz0=int64#7
+# asm 2: add <addt1=%r14,<rz0=%rax
+add %r14,%rax
+
+# qhasm: carry? rz1 += addt0 + carry
+# asm 1: adc <addt0=int64#11,<rz1=int64#8
+# asm 2: adc <addt0=%r13,<rz1=%r10
+adc %r13,%r10
+
+# qhasm: carry? rz2 += addt0 + carry
+# asm 1: adc <addt0=int64#11,<rz2=int64#9
+# asm 2: adc <addt0=%r13,<rz2=%r11
+adc %r13,%r11
+
+# qhasm: carry? rz3 += addt0 + carry
+# asm 1: adc <addt0=int64#11,<rz3=int64#10
+# asm 2: adc <addt0=%r13,<rz3=%r12
+adc %r13,%r12
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#12,<addt0=int64#11
+# asm 2: cmovc <addt1=%r14,<addt0=%r13
+cmovc %r14,%r13
+
+# qhasm: rz0 += addt0
+# asm 1: add <addt0=int64#11,<rz0=int64#7
+# asm 2: add <addt0=%r13,<rz0=%rax
+add %r13,%rax
+
+# qhasm: *(uint64 *) (rp + 32) = rz0
+# asm 1: movq <rz0=int64#7,32(<rp=int64#1)
+# asm 2: movq <rz0=%rax,32(<rp=%rdi)
+movq %rax,32(%rdi)
+
+# qhasm: *(uint64 *) (rp + 40) = rz1
+# asm 1: movq <rz1=int64#8,40(<rp=int64#1)
+# asm 2: movq <rz1=%r10,40(<rp=%rdi)
+movq %r10,40(%rdi)
+
+# qhasm: *(uint64 *) (rp + 48) = rz2
+# asm 1: movq <rz2=int64#9,48(<rp=int64#1)
+# asm 2: movq <rz2=%r11,48(<rp=%rdi)
+movq %r11,48(%rdi)
+
+# qhasm: *(uint64 *) (rp + 56) = rz3
+# asm 1: movq <rz3=int64#10,56(<rp=int64#1)
+# asm 2: movq <rz3=%r12,56(<rp=%rdi)
+movq %r12,56(%rdi)
+
+# qhasm: carry? d0 -= b0_stack
+# asm 1: subq <b0_stack=stack64#12,<d0=int64#3
+# asm 2: subq <b0_stack=88(%rsp),<d0=%rdx
+subq 88(%rsp),%rdx
+
+# qhasm: carry? d1 -= b1_stack - carry
+# asm 1: sbbq <b1_stack=stack64#13,<d1=int64#4
+# asm 2: sbbq <b1_stack=96(%rsp),<d1=%rcx
+sbbq 96(%rsp),%rcx
+
+# qhasm: carry? d2 -= b2_stack - carry
+# asm 1: sbbq <b2_stack=stack64#14,<d2=int64#5
+# asm 2: sbbq <b2_stack=104(%rsp),<d2=%r8
+sbbq 104(%rsp),%r8
+
+# qhasm: carry? d3 -= b3_stack - carry
+# asm 1: sbbq <b3_stack=stack64#15,<d3=int64#6
+# asm 2: sbbq <b3_stack=112(%rsp),<d3=%r9
+sbbq 112(%rsp),%r9
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#11
+# asm 2: mov $0,>subt0=%r13
+mov $0,%r13
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#12
+# asm 2: mov $38,>subt1=%r14
+mov $38,%r14
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#11,<subt1=int64#12
+# asm 2: cmovae <subt0=%r13,<subt1=%r14
+cmovae %r13,%r14
+
+# qhasm: carry? d0 -= subt1
+# asm 1: sub <subt1=int64#12,<d0=int64#3
+# asm 2: sub <subt1=%r14,<d0=%rdx
+sub %r14,%rdx
+
+# qhasm: carry? d1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<d1=int64#4
+# asm 2: sbb <subt0=%r13,<d1=%rcx
+sbb %r13,%rcx
+
+# qhasm: carry? d2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<d2=int64#5
+# asm 2: sbb <subt0=%r13,<d2=%r8
+sbb %r13,%r8
+
+# qhasm: carry? d3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<d3=int64#6
+# asm 2: sbb <subt0=%r13,<d3=%r9
+sbb %r13,%r9
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#12,<subt0=int64#11
+# asm 2: cmovc <subt1=%r14,<subt0=%r13
+cmovc %r14,%r13
+
+# qhasm: d0 -= subt0
+# asm 1: sub <subt0=int64#11,<d0=int64#3
+# asm 2: sub <subt0=%r13,<d0=%rdx
+sub %r13,%rdx
+
+# qhasm: *(uint64 *)(rp + 64) = d0
+# asm 1: movq <d0=int64#3,64(<rp=int64#1)
+# asm 2: movq <d0=%rdx,64(<rp=%rdi)
+movq %rdx,64(%rdi)
+
+# qhasm: *(uint64 *)(rp + 72) = d1
+# asm 1: movq <d1=int64#4,72(<rp=int64#1)
+# asm 2: movq <d1=%rcx,72(<rp=%rdi)
+movq %rcx,72(%rdi)
+
+# qhasm: *(uint64 *)(rp + 80) = d2
+# asm 1: movq <d2=int64#5,80(<rp=int64#1)
+# asm 2: movq <d2=%r8,80(<rp=%rdi)
+movq %r8,80(%rdi)
+
+# qhasm: *(uint64 *)(rp + 88) = d3
+# asm 1: movq <d3=int64#6,88(<rp=int64#1)
+# asm 2: movq <d3=%r9,88(<rp=%rdi)
+movq %r9,88(%rdi)
+
+# qhasm: carry? rz0 -= c0_stack
+# asm 1: subq <c0_stack=stack64#16,<rz0=int64#7
+# asm 2: subq <c0_stack=120(%rsp),<rz0=%rax
+subq 120(%rsp),%rax
+
+# qhasm: carry? rz1 -= c1_stack - carry
+# asm 1: sbbq <c1_stack=stack64#17,<rz1=int64#8
+# asm 2: sbbq <c1_stack=128(%rsp),<rz1=%r10
+sbbq 128(%rsp),%r10
+
+# qhasm: carry? rz2 -= c2_stack - carry
+# asm 1: sbbq <c2_stack=stack64#18,<rz2=int64#9
+# asm 2: sbbq <c2_stack=136(%rsp),<rz2=%r11
+sbbq 136(%rsp),%r11
+
+# qhasm: carry? rz3 -= c3_stack - carry
+# asm 1: sbbq <c3_stack=stack64#19,<rz3=int64#10
+# asm 2: sbbq <c3_stack=144(%rsp),<rz3=%r12
+sbbq 144(%rsp),%r12
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#3
+# asm 2: mov $0,>subt0=%rdx
+mov $0,%rdx
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#4
+# asm 2: mov $38,>subt1=%rcx
+mov $38,%rcx
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#3,<subt1=int64#4
+# asm 2: cmovae <subt0=%rdx,<subt1=%rcx
+cmovae %rdx,%rcx
+
+# qhasm: carry? rz0 -= subt1
+# asm 1: sub <subt1=int64#4,<rz0=int64#7
+# asm 2: sub <subt1=%rcx,<rz0=%rax
+sub %rcx,%rax
+
+# qhasm: carry? rz1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#3,<rz1=int64#8
+# asm 2: sbb <subt0=%rdx,<rz1=%r10
+sbb %rdx,%r10
+
+# qhasm: carry? rz2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#3,<rz2=int64#9
+# asm 2: sbb <subt0=%rdx,<rz2=%r11
+sbb %rdx,%r11
+
+# qhasm: carry? rz3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#3,<rz3=int64#10
+# asm 2: sbb <subt0=%rdx,<rz3=%r12
+sbb %rdx,%r12
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#4,<subt0=int64#3
+# asm 2: cmovc <subt1=%rcx,<subt0=%rdx
+cmovc %rcx,%rdx
+
+# qhasm: rz0 -= subt0
+# asm 1: sub <subt0=int64#3,<rz0=int64#7
+# asm 2: sub <subt0=%rdx,<rz0=%rax
+sub %rdx,%rax
+
+# qhasm: *(uint64 *) (rp + 96) = rz0
+# asm 1: movq <rz0=int64#7,96(<rp=int64#1)
+# asm 2: movq <rz0=%rax,96(<rp=%rdi)
+movq %rax,96(%rdi)
+
+# qhasm: *(uint64 *) (rp + 104) = rz1
+# asm 1: movq <rz1=int64#8,104(<rp=int64#1)
+# asm 2: movq <rz1=%r10,104(<rp=%rdi)
+movq %r10,104(%rdi)
+
+# qhasm: *(uint64 *) (rp + 112) = rz2
+# asm 1: movq <rz2=int64#9,112(<rp=int64#1)
+# asm 2: movq <rz2=%r11,112(<rp=%rdi)
+movq %r11,112(%rdi)
+
+# qhasm: *(uint64 *) (rp + 120) = rz3
+# asm 1: movq <rz3=int64#10,120(<rp=int64#1)
+# asm 2: movq <rz3=%r12,120(<rp=%rdi)
+movq %r12,120(%rdi)
+
+# qhasm: rx0 = *(uint64 *)(pp + 0)
+# asm 1: movq 0(<pp=int64#2),>rx0=int64#3
+# asm 2: movq 0(<pp=%rsi),>rx0=%rdx
+movq 0(%rsi),%rdx
+
+# qhasm: rx1 = *(uint64 *)(pp + 8)
+# asm 1: movq 8(<pp=int64#2),>rx1=int64#4
+# asm 2: movq 8(<pp=%rsi),>rx1=%rcx
+movq 8(%rsi),%rcx
+
+# qhasm: rx2 = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>rx2=int64#5
+# asm 2: movq 16(<pp=%rsi),>rx2=%r8
+movq 16(%rsi),%r8
+
+# qhasm: rx3 = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>rx3=int64#6
+# asm 2: movq 24(<pp=%rsi),>rx3=%r9
+movq 24(%rsi),%r9
+
+# qhasm: carry? rx0 += *(uint64 *)(pp + 32)
+# asm 1: addq 32(<pp=int64#2),<rx0=int64#3
+# asm 2: addq 32(<pp=%rsi),<rx0=%rdx
+addq 32(%rsi),%rdx
+
+# qhasm: carry? rx1 += *(uint64 *)(pp + 40) + carry
+# asm 1: adcq 40(<pp=int64#2),<rx1=int64#4
+# asm 2: adcq 40(<pp=%rsi),<rx1=%rcx
+adcq 40(%rsi),%rcx
+
+# qhasm: carry? rx2 += *(uint64 *)(pp + 48) + carry
+# asm 1: adcq 48(<pp=int64#2),<rx2=int64#5
+# asm 2: adcq 48(<pp=%rsi),<rx2=%r8
+adcq 48(%rsi),%r8
+
+# qhasm: carry? rx3 += *(uint64 *)(pp + 56) + carry
+# asm 1: adcq 56(<pp=int64#2),<rx3=int64#6
+# asm 2: adcq 56(<pp=%rsi),<rx3=%r9
+adcq 56(%rsi),%r9
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#2
+# asm 2: mov $0,>addt0=%rsi
+mov $0,%rsi
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#7
+# asm 2: mov $38,>addt1=%rax
+mov $38,%rax
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#2,<addt1=int64#7
+# asm 2: cmovae <addt0=%rsi,<addt1=%rax
+cmovae %rsi,%rax
+
+# qhasm: carry? rx0 += addt1
+# asm 1: add <addt1=int64#7,<rx0=int64#3
+# asm 2: add <addt1=%rax,<rx0=%rdx
+add %rax,%rdx
+
+# qhasm: carry? rx1 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx1=int64#4
+# asm 2: adc <addt0=%rsi,<rx1=%rcx
+adc %rsi,%rcx
+
+# qhasm: carry? rx2 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx2=int64#5
+# asm 2: adc <addt0=%rsi,<rx2=%r8
+adc %rsi,%r8
+
+# qhasm: carry? rx3 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx3=int64#6
+# asm 2: adc <addt0=%rsi,<rx3=%r9
+adc %rsi,%r9
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#7,<addt0=int64#2
+# asm 2: cmovc <addt1=%rax,<addt0=%rsi
+cmovc %rax,%rsi
+
+# qhasm: rx0 += addt0
+# asm 1: add <addt0=int64#2,<rx0=int64#3
+# asm 2: add <addt0=%rsi,<rx0=%rdx
+add %rsi,%rdx
+
+# qhasm: rx0_stack = rx0
+# asm 1: movq <rx0=int64#3,>rx0_stack=stack64#12
+# asm 2: movq <rx0=%rdx,>rx0_stack=88(%rsp)
+movq %rdx,88(%rsp)
+
+# qhasm: rx1_stack = rx1
+# asm 1: movq <rx1=int64#4,>rx1_stack=stack64#13
+# asm 2: movq <rx1=%rcx,>rx1_stack=96(%rsp)
+movq %rcx,96(%rsp)
+
+# qhasm: rx2_stack = rx2
+# asm 1: movq <rx2=int64#5,>rx2_stack=stack64#14
+# asm 2: movq <rx2=%r8,>rx2_stack=104(%rsp)
+movq %r8,104(%rsp)
+
+# qhasm: rx3_stack = rx3
+# asm 1: movq <rx3=int64#6,>rx3_stack=stack64#15
+# asm 2: movq <rx3=%r9,>rx3_stack=112(%rsp)
+movq %r9,112(%rsp)
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#2
+# asm 2: mov $0,>squarer7=%rsi
+mov $0,%rsi
+
+# qhasm: squarerax = rx1_stack
+# asm 1: movq <rx1_stack=stack64#13,>squarerax=int64#7
+# asm 2: movq <rx1_stack=96(%rsp),>squarerax=%rax
+movq 96(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack
+# asm 1: mulq <rx0_stack=stack64#12
+# asm 2: mulq <rx0_stack=88(%rsp)
+mulq 88(%rsp)
+
+# qhasm: rx1 = squarerax
+# asm 1: mov <squarerax=int64#7,>rx1=int64#4
+# asm 2: mov <squarerax=%rax,>rx1=%rcx
+mov %rax,%rcx
+
+# qhasm: rx2 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>rx2=int64#5
+# asm 2: mov <squarerdx=%rdx,>rx2=%r8
+mov %rdx,%r8
+
+# qhasm: squarerax = rx2_stack
+# asm 1: movq <rx2_stack=stack64#14,>squarerax=int64#7
+# asm 2: movq <rx2_stack=104(%rsp),>squarerax=%rax
+movq 104(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx1_stack
+# asm 1: mulq <rx1_stack=stack64#13
+# asm 2: mulq <rx1_stack=96(%rsp)
+mulq 96(%rsp)
+
+# qhasm: rx3 = squarerax
+# asm 1: mov <squarerax=int64#7,>rx3=int64#6
+# asm 2: mov <squarerax=%rax,>rx3=%r9
+mov %rax,%r9
+
+# qhasm: squarer4 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer4=int64#8
+# asm 2: mov <squarerdx=%rdx,>squarer4=%r10
+mov %rdx,%r10
+
+# qhasm: squarerax = rx3_stack
+# asm 1: movq <rx3_stack=stack64#15,>squarerax=int64#7
+# asm 2: movq <rx3_stack=112(%rsp),>squarerax=%rax
+movq 112(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx2_stack
+# asm 1: mulq <rx2_stack=stack64#14
+# asm 2: mulq <rx2_stack=104(%rsp)
+mulq 104(%rsp)
+
+# qhasm: squarer5 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer5=int64#9
+# asm 2: mov <squarerax=%rax,>squarer5=%r11
+mov %rax,%r11
+
+# qhasm: squarer6 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer6=int64#10
+# asm 2: mov <squarerdx=%rdx,>squarer6=%r12
+mov %rdx,%r12
+
+# qhasm: squarerax = rx2_stack
+# asm 1: movq <rx2_stack=stack64#14,>squarerax=int64#7
+# asm 2: movq <rx2_stack=104(%rsp),>squarerax=%rax
+movq 104(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack
+# asm 1: mulq <rx0_stack=stack64#12
+# asm 2: mulq <rx0_stack=88(%rsp)
+mulq 88(%rsp)
+
+# qhasm: carry? rx2 += squarerax
+# asm 1: add <squarerax=int64#7,<rx2=int64#5
+# asm 2: add <squarerax=%rax,<rx2=%r8
+add %rax,%r8
+
+# qhasm: carry? rx3 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<rx3=int64#6
+# asm 2: adc <squarerdx=%rdx,<rx3=%r9
+adc %rdx,%r9
+
+# qhasm: squarer4 += 0 + carry
+# asm 1: adc $0,<squarer4=int64#8
+# asm 2: adc $0,<squarer4=%r10
+adc $0,%r10
+
+# qhasm: squarerax = rx3_stack
+# asm 1: movq <rx3_stack=stack64#15,>squarerax=int64#7
+# asm 2: movq <rx3_stack=112(%rsp),>squarerax=%rax
+movq 112(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx1_stack
+# asm 1: mulq <rx1_stack=stack64#13
+# asm 2: mulq <rx1_stack=96(%rsp)
+mulq 96(%rsp)
+
+# qhasm: carry? squarer4 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer4=int64#8
+# asm 2: add <squarerax=%rax,<squarer4=%r10
+add %rax,%r10
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#9
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r11
+adc %rdx,%r11
+
+# qhasm: squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#10
+# asm 2: adc $0,<squarer6=%r12
+adc $0,%r12
+
+# qhasm: squarerax = rx3_stack
+# asm 1: movq <rx3_stack=stack64#15,>squarerax=int64#7
+# asm 2: movq <rx3_stack=112(%rsp),>squarerax=%rax
+movq 112(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack
+# asm 1: mulq <rx0_stack=stack64#12
+# asm 2: mulq <rx0_stack=88(%rsp)
+mulq 88(%rsp)
+
+# qhasm: carry? rx3 += squarerax
+# asm 1: add <squarerax=int64#7,<rx3=int64#6
+# asm 2: add <squarerax=%rax,<rx3=%r9
+add %rax,%r9
+
+# qhasm: carry? squarer4 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer4=int64#8
+# asm 2: adc <squarerdx=%rdx,<squarer4=%r10
+adc %rdx,%r10
+
+# qhasm: carry? squarer5 += 0 + carry
+# asm 1: adc $0,<squarer5=int64#9
+# asm 2: adc $0,<squarer5=%r11
+adc $0,%r11
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#10
+# asm 2: adc $0,<squarer6=%r12
+adc $0,%r12
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#2
+# asm 2: adc $0,<squarer7=%rsi
+adc $0,%rsi
+
+# qhasm: carry? rx1 += rx1
+# asm 1: add <rx1=int64#4,<rx1=int64#4
+# asm 2: add <rx1=%rcx,<rx1=%rcx
+add %rcx,%rcx
+
+# qhasm: carry? rx2 += rx2 + carry
+# asm 1: adc <rx2=int64#5,<rx2=int64#5
+# asm 2: adc <rx2=%r8,<rx2=%r8
+adc %r8,%r8
+
+# qhasm: carry? rx3 += rx3 + carry
+# asm 1: adc <rx3=int64#6,<rx3=int64#6
+# asm 2: adc <rx3=%r9,<rx3=%r9
+adc %r9,%r9
+
+# qhasm: carry? squarer4 += squarer4 + carry
+# asm 1: adc <squarer4=int64#8,<squarer4=int64#8
+# asm 2: adc <squarer4=%r10,<squarer4=%r10
+adc %r10,%r10
+
+# qhasm: carry? squarer5 += squarer5 + carry
+# asm 1: adc <squarer5=int64#9,<squarer5=int64#9
+# asm 2: adc <squarer5=%r11,<squarer5=%r11
+adc %r11,%r11
+
+# qhasm: carry? squarer6 += squarer6 + carry
+# asm 1: adc <squarer6=int64#10,<squarer6=int64#10
+# asm 2: adc <squarer6=%r12,<squarer6=%r12
+adc %r12,%r12
+
+# qhasm: squarer7 += squarer7 + carry
+# asm 1: adc <squarer7=int64#2,<squarer7=int64#2
+# asm 2: adc <squarer7=%rsi,<squarer7=%rsi
+adc %rsi,%rsi
+
+# qhasm: squarerax = rx0_stack
+# asm 1: movq <rx0_stack=stack64#12,>squarerax=int64#7
+# asm 2: movq <rx0_stack=88(%rsp),>squarerax=%rax
+movq 88(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx0_stack
+# asm 1: mulq <rx0_stack=stack64#12
+# asm 2: mulq <rx0_stack=88(%rsp)
+mulq 88(%rsp)
+
+# qhasm: rx0 = squarerax
+# asm 1: mov <squarerax=int64#7,>rx0=int64#11
+# asm 2: mov <squarerax=%rax,>rx0=%r13
+mov %rax,%r13
+
+# qhasm: squaret1 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret1=int64#12
+# asm 2: mov <squarerdx=%rdx,>squaret1=%r14
+mov %rdx,%r14
+
+# qhasm: squarerax = rx1_stack
+# asm 1: movq <rx1_stack=stack64#13,>squarerax=int64#7
+# asm 2: movq <rx1_stack=96(%rsp),>squarerax=%rax
+movq 96(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx1_stack
+# asm 1: mulq <rx1_stack=stack64#13
+# asm 2: mulq <rx1_stack=96(%rsp)
+mulq 96(%rsp)
+
+# qhasm: squaret2 = squarerax
+# asm 1: mov <squarerax=int64#7,>squaret2=int64#13
+# asm 2: mov <squarerax=%rax,>squaret2=%r15
+mov %rax,%r15
+
+# qhasm: squaret3 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squaret3=int64#14
+# asm 2: mov <squarerdx=%rdx,>squaret3=%rbx
+mov %rdx,%rbx
+
+# qhasm: squarerax = rx2_stack
+# asm 1: movq <rx2_stack=stack64#14,>squarerax=int64#7
+# asm 2: movq <rx2_stack=104(%rsp),>squarerax=%rax
+movq 104(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx2_stack
+# asm 1: mulq <rx2_stack=stack64#14
+# asm 2: mulq <rx2_stack=104(%rsp)
+mulq 104(%rsp)
+
+# qhasm: carry? rx1 += squaret1
+# asm 1: add <squaret1=int64#12,<rx1=int64#4
+# asm 2: add <squaret1=%r14,<rx1=%rcx
+add %r14,%rcx
+
+# qhasm: carry? rx2 += squaret2 + carry
+# asm 1: adc <squaret2=int64#13,<rx2=int64#5
+# asm 2: adc <squaret2=%r15,<rx2=%r8
+adc %r15,%r8
+
+# qhasm: carry? rx3 += squaret3 + carry
+# asm 1: adc <squaret3=int64#14,<rx3=int64#6
+# asm 2: adc <squaret3=%rbx,<rx3=%r9
+adc %rbx,%r9
+
+# qhasm: carry? squarer4 += squarerax + carry
+# asm 1: adc <squarerax=int64#7,<squarer4=int64#8
+# asm 2: adc <squarerax=%rax,<squarer4=%r10
+adc %rax,%r10
+
+# qhasm: carry? squarer5 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer5=int64#9
+# asm 2: adc <squarerdx=%rdx,<squarer5=%r11
+adc %rdx,%r11
+
+# qhasm: carry? squarer6 += 0 + carry
+# asm 1: adc $0,<squarer6=int64#10
+# asm 2: adc $0,<squarer6=%r12
+adc $0,%r12
+
+# qhasm: squarer7 += 0 + carry
+# asm 1: adc $0,<squarer7=int64#2
+# asm 2: adc $0,<squarer7=%rsi
+adc $0,%rsi
+
+# qhasm: squarerax = rx3_stack
+# asm 1: movq <rx3_stack=stack64#15,>squarerax=int64#7
+# asm 2: movq <rx3_stack=112(%rsp),>squarerax=%rax
+movq 112(%rsp),%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * rx3_stack
+# asm 1: mulq <rx3_stack=stack64#15
+# asm 2: mulq <rx3_stack=112(%rsp)
+mulq 112(%rsp)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#10
+# asm 2: add <squarerax=%rax,<squarer6=%r12
+add %rax,%r12
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#2
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rsi
+adc %rdx,%rsi
+
+# qhasm: squarerax = squarer4
+# asm 1: mov <squarer4=int64#8,>squarerax=int64#7
+# asm 2: mov <squarer4=%r10,>squarerax=%rax
+mov %r10,%rax
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: squarer4 = squarerax
+# asm 1: mov <squarerax=int64#7,>squarer4=int64#8
+# asm 2: mov <squarerax=%rax,>squarer4=%r10
+mov %rax,%r10
+
+# qhasm: squarerax = squarer5
+# asm 1: mov <squarer5=int64#9,>squarerax=int64#7
+# asm 2: mov <squarer5=%r11,>squarerax=%rax
+mov %r11,%rax
+
+# qhasm: squarer5 = squarerdx
+# asm 1: mov <squarerdx=int64#3,>squarer5=int64#9
+# asm 2: mov <squarerdx=%rdx,>squarer5=%r11
+mov %rdx,%r11
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer5 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer5=int64#9
+# asm 2: add <squarerax=%rax,<squarer5=%r11
+add %rax,%r11
+
+# qhasm: squarerax = squarer6
+# asm 1: mov <squarer6=int64#10,>squarerax=int64#7
+# asm 2: mov <squarer6=%r12,>squarerax=%rax
+mov %r12,%rax
+
+# qhasm: squarer6 = 0
+# asm 1: mov $0,>squarer6=int64#10
+# asm 2: mov $0,>squarer6=%r12
+mov $0,%r12
+
+# qhasm: squarer6 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer6=int64#10
+# asm 2: adc <squarerdx=%rdx,<squarer6=%r12
+adc %rdx,%r12
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer6 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer6=int64#10
+# asm 2: add <squarerax=%rax,<squarer6=%r12
+add %rax,%r12
+
+# qhasm: squarerax = squarer7
+# asm 1: mov <squarer7=int64#2,>squarerax=int64#7
+# asm 2: mov <squarer7=%rsi,>squarerax=%rax
+mov %rsi,%rax
+
+# qhasm: squarer7 = 0
+# asm 1: mov $0,>squarer7=int64#2
+# asm 2: mov $0,>squarer7=%rsi
+mov $0,%rsi
+
+# qhasm: squarer7 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer7=int64#2
+# asm 2: adc <squarerdx=%rdx,<squarer7=%rsi
+adc %rdx,%rsi
+
+# qhasm: (uint128) squarerdx squarerax = squarerax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? squarer7 += squarerax
+# asm 1: add <squarerax=int64#7,<squarer7=int64#2
+# asm 2: add <squarerax=%rax,<squarer7=%rsi
+add %rax,%rsi
+
+# qhasm: squarer8 = 0
+# asm 1: mov $0,>squarer8=int64#7
+# asm 2: mov $0,>squarer8=%rax
+mov $0,%rax
+
+# qhasm: squarer8 += squarerdx + carry
+# asm 1: adc <squarerdx=int64#3,<squarer8=int64#7
+# asm 2: adc <squarerdx=%rdx,<squarer8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rx0 += squarer4
+# asm 1: add <squarer4=int64#8,<rx0=int64#11
+# asm 2: add <squarer4=%r10,<rx0=%r13
+add %r10,%r13
+
+# qhasm: carry? rx1 += squarer5 + carry
+# asm 1: adc <squarer5=int64#9,<rx1=int64#4
+# asm 2: adc <squarer5=%r11,<rx1=%rcx
+adc %r11,%rcx
+
+# qhasm: carry? rx2 += squarer6 + carry
+# asm 1: adc <squarer6=int64#10,<rx2=int64#5
+# asm 2: adc <squarer6=%r12,<rx2=%r8
+adc %r12,%r8
+
+# qhasm: carry? rx3 += squarer7 + carry
+# asm 1: adc <squarer7=int64#2,<rx3=int64#6
+# asm 2: adc <squarer7=%rsi,<rx3=%r9
+adc %rsi,%r9
+
+# qhasm: squarezero = 0
+# asm 1: mov $0,>squarezero=int64#2
+# asm 2: mov $0,>squarezero=%rsi
+mov $0,%rsi
+
+# qhasm: squarer8 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<squarer8=int64#7
+# asm 2: adc <squarezero=%rsi,<squarer8=%rax
+adc %rsi,%rax
+
+# qhasm: squarer8 *= 38
+# asm 1: imulq $38,<squarer8=int64#7,>squarer8=int64#3
+# asm 2: imulq $38,<squarer8=%rax,>squarer8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rx0 += squarer8
+# asm 1: add <squarer8=int64#3,<rx0=int64#11
+# asm 2: add <squarer8=%rdx,<rx0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rx1 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<rx1=int64#4
+# asm 2: adc <squarezero=%rsi,<rx1=%rcx
+adc %rsi,%rcx
+
+# qhasm: carry? rx2 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<rx2=int64#5
+# asm 2: adc <squarezero=%rsi,<rx2=%r8
+adc %rsi,%r8
+
+# qhasm: carry? rx3 += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<rx3=int64#6
+# asm 2: adc <squarezero=%rsi,<rx3=%r9
+adc %rsi,%r9
+
+# qhasm: squarezero += squarezero + carry
+# asm 1: adc <squarezero=int64#2,<squarezero=int64#2
+# asm 2: adc <squarezero=%rsi,<squarezero=%rsi
+adc %rsi,%rsi
+
+# qhasm: squarezero *= 38
+# asm 1: imulq $38,<squarezero=int64#2,>squarezero=int64#2
+# asm 2: imulq $38,<squarezero=%rsi,>squarezero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rx0 += squarezero
+# asm 1: add <squarezero=int64#2,<rx0=int64#11
+# asm 2: add <squarezero=%rsi,<rx0=%r13
+add %rsi,%r13
+
+# qhasm: carry? rx0 += d0_stack
+# asm 1: addq <d0_stack=stack64#8,<rx0=int64#11
+# asm 2: addq <d0_stack=56(%rsp),<rx0=%r13
+addq 56(%rsp),%r13
+
+# qhasm: carry? rx1 += d1_stack + carry
+# asm 1: adcq <d1_stack=stack64#9,<rx1=int64#4
+# asm 2: adcq <d1_stack=64(%rsp),<rx1=%rcx
+adcq 64(%rsp),%rcx
+
+# qhasm: carry? rx2 += d2_stack + carry
+# asm 1: adcq <d2_stack=stack64#10,<rx2=int64#5
+# asm 2: adcq <d2_stack=72(%rsp),<rx2=%r8
+adcq 72(%rsp),%r8
+
+# qhasm: carry? rx3 += d3_stack + carry
+# asm 1: adcq <d3_stack=stack64#11,<rx3=int64#6
+# asm 2: adcq <d3_stack=80(%rsp),<rx3=%r9
+adcq 80(%rsp),%r9
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#2
+# asm 2: mov $0,>addt0=%rsi
+mov $0,%rsi
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#3
+# asm 2: mov $38,>addt1=%rdx
+mov $38,%rdx
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#2,<addt1=int64#3
+# asm 2: cmovae <addt0=%rsi,<addt1=%rdx
+cmovae %rsi,%rdx
+
+# qhasm: carry? rx0 += addt1
+# asm 1: add <addt1=int64#3,<rx0=int64#11
+# asm 2: add <addt1=%rdx,<rx0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rx1 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx1=int64#4
+# asm 2: adc <addt0=%rsi,<rx1=%rcx
+adc %rsi,%rcx
+
+# qhasm: carry? rx2 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx2=int64#5
+# asm 2: adc <addt0=%rsi,<rx2=%r8
+adc %rsi,%r8
+
+# qhasm: carry? rx3 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx3=int64#6
+# asm 2: adc <addt0=%rsi,<rx3=%r9
+adc %rsi,%r9
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#3,<addt0=int64#2
+# asm 2: cmovc <addt1=%rdx,<addt0=%rsi
+cmovc %rdx,%rsi
+
+# qhasm: rx0 += addt0
+# asm 1: add <addt0=int64#2,<rx0=int64#11
+# asm 2: add <addt0=%rsi,<rx0=%r13
+add %rsi,%r13
+
+# qhasm: carry? rx0 += e0_stack
+# asm 1: addq <e0_stack=stack64#20,<rx0=int64#11
+# asm 2: addq <e0_stack=152(%rsp),<rx0=%r13
+addq 152(%rsp),%r13
+
+# qhasm: carry? rx1 += e1_stack + carry
+# asm 1: adcq <e1_stack=stack64#21,<rx1=int64#4
+# asm 2: adcq <e1_stack=160(%rsp),<rx1=%rcx
+adcq 160(%rsp),%rcx
+
+# qhasm: carry? rx2 += e2_stack + carry
+# asm 1: adcq <e2_stack=stack64#22,<rx2=int64#5
+# asm 2: adcq <e2_stack=168(%rsp),<rx2=%r8
+adcq 168(%rsp),%r8
+
+# qhasm: carry? rx3 += e3_stack + carry
+# asm 1: adcq <e3_stack=stack64#23,<rx3=int64#6
+# asm 2: adcq <e3_stack=176(%rsp),<rx3=%r9
+adcq 176(%rsp),%r9
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#2
+# asm 2: mov $0,>addt0=%rsi
+mov $0,%rsi
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#3
+# asm 2: mov $38,>addt1=%rdx
+mov $38,%rdx
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#2,<addt1=int64#3
+# asm 2: cmovae <addt0=%rsi,<addt1=%rdx
+cmovae %rsi,%rdx
+
+# qhasm: carry? rx0 += addt1
+# asm 1: add <addt1=int64#3,<rx0=int64#11
+# asm 2: add <addt1=%rdx,<rx0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rx1 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx1=int64#4
+# asm 2: adc <addt0=%rsi,<rx1=%rcx
+adc %rsi,%rcx
+
+# qhasm: carry? rx2 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx2=int64#5
+# asm 2: adc <addt0=%rsi,<rx2=%r8
+adc %rsi,%r8
+
+# qhasm: carry? rx3 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rx3=int64#6
+# asm 2: adc <addt0=%rsi,<rx3=%r9
+adc %rsi,%r9
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#3,<addt0=int64#2
+# asm 2: cmovc <addt1=%rdx,<addt0=%rsi
+cmovc %rdx,%rsi
+
+# qhasm: rx0 += addt0
+# asm 1: add <addt0=int64#2,<rx0=int64#11
+# asm 2: add <addt0=%rsi,<rx0=%r13
+add %rsi,%r13
+
+# qhasm: *(uint64 *)(rp + 0) = rx0
+# asm 1: movq <rx0=int64#11,0(<rp=int64#1)
+# asm 2: movq <rx0=%r13,0(<rp=%rdi)
+movq %r13,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = rx1
+# asm 1: movq <rx1=int64#4,8(<rp=int64#1)
+# asm 2: movq <rx1=%rcx,8(<rp=%rdi)
+movq %rcx,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = rx2
+# asm 1: movq <rx2=int64#5,16(<rp=int64#1)
+# asm 2: movq <rx2=%r8,16(<rp=%rdi)
+movq %r8,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = rx3
+# asm 1: movq <rx3=int64#6,24(<rp=int64#1)
+# asm 2: movq <rx3=%r9,24(<rp=%rdi)
+movq %r9,24(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_double.c b/ext/ed25519-amd64-asm/ge25519_double.c
new file mode 100644
index 00000000..d55e2b4f
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_double.c
@@ -0,0 +1,8 @@
+#include "ge25519.h"
+
+void ge25519_double(ge25519_p3 *r, const ge25519_p3 *p)
+{
+ ge25519_p1p1 grp1p1;
+ ge25519_dbl_p1p1(&grp1p1, (ge25519_p2 *)p);
+ ge25519_p1p1_to_p3(r, &grp1p1);
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_double_scalarmult.c b/ext/ed25519-amd64-asm/ge25519_double_scalarmult.c
new file mode 100644
index 00000000..30c922af
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_double_scalarmult.c
@@ -0,0 +1,102 @@
+#include "fe25519.h"
+#include "sc25519.h"
+#include "ge25519.h"
+
+#define S1_SWINDOWSIZE 5
+#define PRE1_SIZE (1<<(S1_SWINDOWSIZE-2))
+#define S2_SWINDOWSIZE 7
+#define PRE2_SIZE (1<<(S2_SWINDOWSIZE-2))
+
+ge25519_niels pre2[PRE2_SIZE] = {
+#include "ge25519_base_slide_multiples.data"
+};
+
+static const fe25519 ec2d = {{0xEBD69B9426B2F146, 0x00E0149A8283B156, 0x198E80F2EEF3D130, 0xA406D9DC56DFFCE7}};
+
+static void setneutral(ge25519 *r)
+{
+ fe25519_setint(&r->x,0);
+ fe25519_setint(&r->y,1);
+ fe25519_setint(&r->z,1);
+ fe25519_setint(&r->t,0);
+}
+
+/* computes [s1]p1 + [s2]p2 */
+void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const sc25519 *s2)
+{
+ signed char slide1[256], slide2[256];
+ ge25519_pniels pre1[PRE1_SIZE], neg;
+ ge25519_p3 d1;
+ ge25519_p1p1 t;
+ ge25519_niels nneg;
+ fe25519 d;
+ int i;
+
+ sc25519_slide(slide1, s1, S1_SWINDOWSIZE);
+ sc25519_slide(slide2, s2, S2_SWINDOWSIZE);
+
+ /* precomputation */
+ pre1[0] = *(ge25519_pniels *)p1;
+ ge25519_dbl_p1p1(&t,(ge25519_p2 *)pre1); ge25519_p1p1_to_p3(&d1, &t);
+ /* Convert pre[0] to projective Niels representation */
+ d = pre1[0].ysubx;
+ fe25519_sub(&pre1[0].ysubx, &pre1[0].xaddy, &pre1[0].ysubx);
+ fe25519_add(&pre1[0].xaddy, &pre1[0].xaddy, &d);
+ fe25519_mul(&pre1[0].t2d, &pre1[0].t2d, &ec2d);
+
+ for(i=0;i<PRE1_SIZE-1;i++)
+ {
+ ge25519_pnielsadd_p1p1(&t, &d1, &pre1[i]); ge25519_p1p1_to_p3((ge25519_p3 *)&pre1[i+1], &t);
+ /* Convert pre1[i+1] to projective Niels representation */
+ d = pre1[i+1].ysubx;
+ fe25519_sub(&pre1[i+1].ysubx, &pre1[i+1].xaddy, &pre1[i+1].ysubx);
+ fe25519_add(&pre1[i+1].xaddy, &pre1[i+1].xaddy, &d);
+ fe25519_mul(&pre1[i+1].t2d, &pre1[i+1].t2d, &ec2d);
+ }
+
+ setneutral(r);
+ for (i = 255;i >= 0;--i) {
+ if (slide1[i] || slide2[i]) goto firstbit;
+ }
+
+ for(;i>=0;i--)
+ {
+ firstbit:
+
+ ge25519_dbl_p1p1(&t, (ge25519_p2 *)r);
+
+ if(slide1[i]>0)
+ {
+ ge25519_p1p1_to_p3(r, &t);
+ ge25519_pnielsadd_p1p1(&t, r, &pre1[slide1[i]/2]);
+ }
+ else if(slide1[i]<0)
+ {
+ ge25519_p1p1_to_p3(r, &t);
+ neg = pre1[-slide1[i]/2];
+ d = neg.ysubx;
+ neg.ysubx = neg.xaddy;
+ neg.xaddy = d;
+ fe25519_neg(&neg.t2d, &neg.t2d);
+ ge25519_pnielsadd_p1p1(&t, r, &neg);
+ }
+
+ if(slide2[i]>0)
+ {
+ ge25519_p1p1_to_p3(r, &t);
+ ge25519_nielsadd_p1p1(&t, r, &pre2[slide2[i]/2]);
+ }
+ else if(slide2[i]<0)
+ {
+ ge25519_p1p1_to_p3(r, &t);
+ nneg = pre2[-slide2[i]/2];
+ d = nneg.ysubx;
+ nneg.ysubx = nneg.xaddy;
+ nneg.xaddy = d;
+ fe25519_neg(&nneg.t2d, &nneg.t2d);
+ ge25519_nielsadd_p1p1(&t, r, &nneg);
+ }
+
+ ge25519_p1p1_to_p2((ge25519_p2 *)r, &t);
+ }
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_isneutral.c b/ext/ed25519-amd64-asm/ge25519_isneutral.c
new file mode 100644
index 00000000..cf566dba
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_isneutral.c
@@ -0,0 +1,9 @@
+#include "fe25519.h"
+#include "ge25519.h"
+
+int ge25519_isneutral_vartime(const ge25519_p3 *p)
+{
+ if(!fe25519_iszero_vartime(&p->x)) return 0;
+ if(!fe25519_iseq_vartime(&p->y, &p->z)) return 0;
+ return 1;
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c b/ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c
new file mode 100644
index 00000000..afc6aeae
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_multi_scalarmult.c
@@ -0,0 +1,102 @@
+#include "fe25519.h"
+#include "sc25519.h"
+#include "ge25519.h"
+#include "index_heap.h"
+
+static void setneutral(ge25519 *r)
+{
+ fe25519_setint(&r->x,0);
+ fe25519_setint(&r->y,1);
+ fe25519_setint(&r->z,1);
+ fe25519_setint(&r->t,0);
+}
+
+static void ge25519_scalarmult_vartime_2limbs(ge25519 *r, ge25519 *p, sc25519 *s)
+{
+ if (s->v[1] == 0 && s->v[0] == 1) /* This will happen most of the time after Bos-Coster */
+ *r = *p;
+ else if (s->v[1] == 0 && s->v[0] == 0) /* This won't ever happen, except for all scalars == 0 in Bos-Coster */
+ setneutral(r);
+ else
+ {
+ ge25519 d;
+ unsigned long long mask = (1ULL << 63);
+ int i = 1;
+ while(!(mask & s->v[1]) && mask != 0)
+ mask >>= 1;
+ if(mask == 0)
+ {
+ mask = (1ULL << 63);
+ i = 0;
+ while(!(mask & s->v[0]) && mask != 0)
+ mask >>= 1;
+ }
+ d = *p;
+ mask >>= 1;
+ for(;mask != 0;mask >>= 1)
+ {
+ ge25519_double(&d,&d);
+ if(s->v[i] & mask)
+ ge25519_add(&d,&d,p);
+ }
+ if(i==1)
+ {
+ mask = (1ULL << 63);
+ for(;mask != 0;mask >>= 1)
+ {
+ ge25519_double(&d,&d);
+ if(s->v[0] & mask)
+ ge25519_add(&d,&d,p);
+ }
+ }
+ *r = d;
+ }
+}
+
+/* caller's responsibility to ensure npoints >= 5 */
+void ge25519_multi_scalarmult_vartime(ge25519_p3 *r, ge25519_p3 *p, sc25519 *s, const unsigned long long npoints)
+{
+ unsigned long long pos[npoints];
+ unsigned long long hlen=((npoints+1)/2)|1;
+ unsigned long long max1, max2,i;
+
+ heap_init(pos, hlen, s);
+
+ for(i=0;;i++)
+ {
+ heap_get2max(pos, &max1, &max2, s);
+ if((s[max1].v[3] == 0) || (sc25519_iszero_vartime(&s[max2]))) break;
+ sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
+ ge25519_add(&p[max2],&p[max2],&p[max1]);
+ heap_rootreplaced(pos, hlen, s);
+ }
+ for(;;i++)
+ {
+ heap_get2max(pos, &max1, &max2, s);
+ if((s[max1].v[2] == 0) || (sc25519_iszero_vartime(&s[max2]))) break;
+ sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
+ ge25519_add(&p[max2],&p[max2],&p[max1]);
+ heap_rootreplaced_3limbs(pos, hlen, s);
+ }
+ /* We know that (npoints-1)/2 scalars are only 128-bit scalars */
+ heap_extend(pos, hlen, npoints, s);
+ hlen = npoints;
+ for(;;i++)
+ {
+ heap_get2max(pos, &max1, &max2, s);
+ if((s[max1].v[1] == 0) || (sc25519_iszero_vartime(&s[max2]))) break;
+ sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
+ ge25519_add(&p[max2],&p[max2],&p[max1]);
+ heap_rootreplaced_2limbs(pos, hlen, s);
+ }
+ for(;;i++)
+ {
+ heap_get2max(pos, &max1, &max2, s);
+ if(sc25519_iszero_vartime(&s[max2])) break;
+ sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
+ ge25519_add(&p[max2],&p[max2],&p[max1]);
+ heap_rootreplaced_1limb(pos, hlen, s);
+ }
+
+ ge25519_scalarmult_vartime_2limbs(r, &p[max1], &s[max1]);
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_nielsadd2.s b/ext/ed25519-amd64-asm/ge25519_nielsadd2.s
new file mode 100644
index 00000000..19d71f11
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_nielsadd2.s
@@ -0,0 +1,5791 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 qp
+
+# qhasm: input rp
+
+# qhasm: input qp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 a0
+
+# qhasm: int64 a1
+
+# qhasm: int64 a2
+
+# qhasm: int64 a3
+
+# qhasm: stack64 a0_stack
+
+# qhasm: stack64 a1_stack
+
+# qhasm: stack64 a2_stack
+
+# qhasm: stack64 a3_stack
+
+# qhasm: int64 b0
+
+# qhasm: int64 b1
+
+# qhasm: int64 b2
+
+# qhasm: int64 b3
+
+# qhasm: stack64 b0_stack
+
+# qhasm: stack64 b1_stack
+
+# qhasm: stack64 b2_stack
+
+# qhasm: stack64 b3_stack
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: stack64 c0_stack
+
+# qhasm: stack64 c1_stack
+
+# qhasm: stack64 c2_stack
+
+# qhasm: stack64 c3_stack
+
+# qhasm: int64 d0
+
+# qhasm: int64 d1
+
+# qhasm: int64 d2
+
+# qhasm: int64 d3
+
+# qhasm: stack64 d0_stack
+
+# qhasm: stack64 d1_stack
+
+# qhasm: stack64 d2_stack
+
+# qhasm: stack64 d3_stack
+
+# qhasm: int64 e0
+
+# qhasm: int64 e1
+
+# qhasm: int64 e2
+
+# qhasm: int64 e3
+
+# qhasm: stack64 e0_stack
+
+# qhasm: stack64 e1_stack
+
+# qhasm: stack64 e2_stack
+
+# qhasm: stack64 e3_stack
+
+# qhasm: int64 f0
+
+# qhasm: int64 f1
+
+# qhasm: int64 f2
+
+# qhasm: int64 f3
+
+# qhasm: stack64 f0_stack
+
+# qhasm: stack64 f1_stack
+
+# qhasm: stack64 f2_stack
+
+# qhasm: stack64 f3_stack
+
+# qhasm: int64 g0
+
+# qhasm: int64 g1
+
+# qhasm: int64 g2
+
+# qhasm: int64 g3
+
+# qhasm: stack64 g0_stack
+
+# qhasm: stack64 g1_stack
+
+# qhasm: stack64 g2_stack
+
+# qhasm: stack64 g3_stack
+
+# qhasm: int64 h0
+
+# qhasm: int64 h1
+
+# qhasm: int64 h2
+
+# qhasm: int64 h3
+
+# qhasm: stack64 h0_stack
+
+# qhasm: stack64 h1_stack
+
+# qhasm: stack64 h2_stack
+
+# qhasm: stack64 h3_stack
+
+# qhasm: int64 qt0
+
+# qhasm: int64 qt1
+
+# qhasm: int64 qt2
+
+# qhasm: int64 qt3
+
+# qhasm: stack64 qt0_stack
+
+# qhasm: stack64 qt1_stack
+
+# qhasm: stack64 qt2_stack
+
+# qhasm: stack64 qt3_stack
+
+# qhasm: int64 t10
+
+# qhasm: int64 t11
+
+# qhasm: int64 t12
+
+# qhasm: int64 t13
+
+# qhasm: stack64 t10_stack
+
+# qhasm: stack64 t11_stack
+
+# qhasm: stack64 t12_stack
+
+# qhasm: stack64 t13_stack
+
+# qhasm: int64 t20
+
+# qhasm: int64 t21
+
+# qhasm: int64 t22
+
+# qhasm: int64 t23
+
+# qhasm: stack64 t20_stack
+
+# qhasm: stack64 t21_stack
+
+# qhasm: stack64 t22_stack
+
+# qhasm: stack64 t23_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 rt0
+
+# qhasm: int64 rt1
+
+# qhasm: int64 rt2
+
+# qhasm: int64 rt3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: int64 addt0
+
+# qhasm: int64 addt1
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_nielsadd2
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_nielsadd2
+.globl crypto_sign_ed25519_amd64_64_ge25519_nielsadd2
+_crypto_sign_ed25519_amd64_64_ge25519_nielsadd2:
+crypto_sign_ed25519_amd64_64_ge25519_nielsadd2:
+mov %rsp,%r11
+and $31,%r11
+add $192,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: a0 = *(uint64 *)(rp + 32)
+# asm 1: movq 32(<rp=int64#1),>a0=int64#3
+# asm 2: movq 32(<rp=%rdi),>a0=%rdx
+movq 32(%rdi),%rdx
+
+# qhasm: a1 = *(uint64 *)(rp + 40)
+# asm 1: movq 40(<rp=int64#1),>a1=int64#4
+# asm 2: movq 40(<rp=%rdi),>a1=%rcx
+movq 40(%rdi),%rcx
+
+# qhasm: a2 = *(uint64 *)(rp + 48)
+# asm 1: movq 48(<rp=int64#1),>a2=int64#5
+# asm 2: movq 48(<rp=%rdi),>a2=%r8
+movq 48(%rdi),%r8
+
+# qhasm: a3 = *(uint64 *)(rp + 56)
+# asm 1: movq 56(<rp=int64#1),>a3=int64#6
+# asm 2: movq 56(<rp=%rdi),>a3=%r9
+movq 56(%rdi),%r9
+
+# qhasm: b0 = a0
+# asm 1: mov <a0=int64#3,>b0=int64#7
+# asm 2: mov <a0=%rdx,>b0=%rax
+mov %rdx,%rax
+
+# qhasm: b1 = a1
+# asm 1: mov <a1=int64#4,>b1=int64#8
+# asm 2: mov <a1=%rcx,>b1=%r10
+mov %rcx,%r10
+
+# qhasm: b2 = a2
+# asm 1: mov <a2=int64#5,>b2=int64#9
+# asm 2: mov <a2=%r8,>b2=%r11
+mov %r8,%r11
+
+# qhasm: b3 = a3
+# asm 1: mov <a3=int64#6,>b3=int64#10
+# asm 2: mov <a3=%r9,>b3=%r12
+mov %r9,%r12
+
+# qhasm: carry? a0 -= *(uint64 *) (rp + 0)
+# asm 1: subq 0(<rp=int64#1),<a0=int64#3
+# asm 2: subq 0(<rp=%rdi),<a0=%rdx
+subq 0(%rdi),%rdx
+
+# qhasm: carry? a1 -= *(uint64 *) (rp + 8) - carry
+# asm 1: sbbq 8(<rp=int64#1),<a1=int64#4
+# asm 2: sbbq 8(<rp=%rdi),<a1=%rcx
+sbbq 8(%rdi),%rcx
+
+# qhasm: carry? a2 -= *(uint64 *) (rp + 16) - carry
+# asm 1: sbbq 16(<rp=int64#1),<a2=int64#5
+# asm 2: sbbq 16(<rp=%rdi),<a2=%r8
+sbbq 16(%rdi),%r8
+
+# qhasm: carry? a3 -= *(uint64 *) (rp + 24) - carry
+# asm 1: sbbq 24(<rp=int64#1),<a3=int64#6
+# asm 2: sbbq 24(<rp=%rdi),<a3=%r9
+sbbq 24(%rdi),%r9
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#11
+# asm 2: mov $0,>subt0=%r13
+mov $0,%r13
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#12
+# asm 2: mov $38,>subt1=%r14
+mov $38,%r14
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#11,<subt1=int64#12
+# asm 2: cmovae <subt0=%r13,<subt1=%r14
+cmovae %r13,%r14
+
+# qhasm: carry? a0 -= subt1
+# asm 1: sub <subt1=int64#12,<a0=int64#3
+# asm 2: sub <subt1=%r14,<a0=%rdx
+sub %r14,%rdx
+
+# qhasm: carry? a1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<a1=int64#4
+# asm 2: sbb <subt0=%r13,<a1=%rcx
+sbb %r13,%rcx
+
+# qhasm: carry? a2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<a2=int64#5
+# asm 2: sbb <subt0=%r13,<a2=%r8
+sbb %r13,%r8
+
+# qhasm: carry? a3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#11,<a3=int64#6
+# asm 2: sbb <subt0=%r13,<a3=%r9
+sbb %r13,%r9
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#12,<subt0=int64#11
+# asm 2: cmovc <subt1=%r14,<subt0=%r13
+cmovc %r14,%r13
+
+# qhasm: a0 -= subt0
+# asm 1: sub <subt0=int64#11,<a0=int64#3
+# asm 2: sub <subt0=%r13,<a0=%rdx
+sub %r13,%rdx
+
+# qhasm: carry? b0 += *(uint64 *) (rp + 0)
+# asm 1: addq 0(<rp=int64#1),<b0=int64#7
+# asm 2: addq 0(<rp=%rdi),<b0=%rax
+addq 0(%rdi),%rax
+
+# qhasm: carry? b1 += *(uint64 *) (rp + 8) + carry
+# asm 1: adcq 8(<rp=int64#1),<b1=int64#8
+# asm 2: adcq 8(<rp=%rdi),<b1=%r10
+adcq 8(%rdi),%r10
+
+# qhasm: carry? b2 += *(uint64 *) (rp + 16) + carry
+# asm 1: adcq 16(<rp=int64#1),<b2=int64#9
+# asm 2: adcq 16(<rp=%rdi),<b2=%r11
+adcq 16(%rdi),%r11
+
+# qhasm: carry? b3 += *(uint64 *) (rp + 24) + carry
+# asm 1: adcq 24(<rp=int64#1),<b3=int64#10
+# asm 2: adcq 24(<rp=%rdi),<b3=%r12
+adcq 24(%rdi),%r12
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#11
+# asm 2: mov $0,>addt0=%r13
+mov $0,%r13
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#12
+# asm 2: mov $38,>addt1=%r14
+mov $38,%r14
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#11,<addt1=int64#12
+# asm 2: cmovae <addt0=%r13,<addt1=%r14
+cmovae %r13,%r14
+
+# qhasm: carry? b0 += addt1
+# asm 1: add <addt1=int64#12,<b0=int64#7
+# asm 2: add <addt1=%r14,<b0=%rax
+add %r14,%rax
+
+# qhasm: carry? b1 += addt0 + carry
+# asm 1: adc <addt0=int64#11,<b1=int64#8
+# asm 2: adc <addt0=%r13,<b1=%r10
+adc %r13,%r10
+
+# qhasm: carry? b2 += addt0 + carry
+# asm 1: adc <addt0=int64#11,<b2=int64#9
+# asm 2: adc <addt0=%r13,<b2=%r11
+adc %r13,%r11
+
+# qhasm: carry? b3 += addt0 + carry
+# asm 1: adc <addt0=int64#11,<b3=int64#10
+# asm 2: adc <addt0=%r13,<b3=%r12
+adc %r13,%r12
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#12,<addt0=int64#11
+# asm 2: cmovc <addt1=%r14,<addt0=%r13
+cmovc %r14,%r13
+
+# qhasm: b0 += addt0
+# asm 1: add <addt0=int64#11,<b0=int64#7
+# asm 2: add <addt0=%r13,<b0=%rax
+add %r13,%rax
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#3,>a0_stack=stack64#8
+# asm 2: movq <a0=%rdx,>a0_stack=56(%rsp)
+movq %rdx,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#4,>a1_stack=stack64#9
+# asm 2: movq <a1=%rcx,>a1_stack=64(%rsp)
+movq %rcx,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#5,>a2_stack=stack64#10
+# asm 2: movq <a2=%r8,>a2_stack=72(%rsp)
+movq %r8,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#6,>a3_stack=stack64#11
+# asm 2: movq <a3=%r9,>a3_stack=80(%rsp)
+movq %r9,80(%rsp)
+
+# qhasm: b0_stack = b0
+# asm 1: movq <b0=int64#7,>b0_stack=stack64#12
+# asm 2: movq <b0=%rax,>b0_stack=88(%rsp)
+movq %rax,88(%rsp)
+
+# qhasm: b1_stack = b1
+# asm 1: movq <b1=int64#8,>b1_stack=stack64#13
+# asm 2: movq <b1=%r10,>b1_stack=96(%rsp)
+movq %r10,96(%rsp)
+
+# qhasm: b2_stack = b2
+# asm 1: movq <b2=int64#9,>b2_stack=stack64#14
+# asm 2: movq <b2=%r11,>b2_stack=104(%rsp)
+movq %r11,104(%rsp)
+
+# qhasm: b3_stack = b3
+# asm 1: movq <b3=int64#10,>b3_stack=stack64#15
+# asm 2: movq <b3=%r12,>b3_stack=112(%rsp)
+movq %r12,112(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = a0_stack
+# asm 1: movq <a0_stack=stack64#8,>mulx0=int64#9
+# asm 2: movq <a0_stack=56(%rsp),>mulx0=%r11
+movq 56(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rsi),>mulrax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: a0 = mulrax
+# asm 1: mov <mulrax=int64#7,>a0=int64#10
+# asm 2: mov <mulrax=%rax,>a0=%r12
+mov %rax,%r12
+
+# qhasm: a1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>a1=int64#11
+# asm 2: mov <mulrdx=%rdx,>a1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rsi),>mulrax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#11
+# asm 2: add <mulrax=%rax,<a1=%r13
+add %rax,%r13
+
+# qhasm: a2 = 0
+# asm 1: mov $0,>a2=int64#12
+# asm 2: mov $0,>a2=%r14
+mov $0,%r14
+
+# qhasm: a2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a2=int64#12
+# asm 2: adc <mulrdx=%rdx,<a2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rsi),>mulrax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#12
+# asm 2: add <mulrax=%rax,<a2=%r14
+add %rax,%r14
+
+# qhasm: a3 = 0
+# asm 1: mov $0,>a3=int64#13
+# asm 2: mov $0,>a3=%r15
+mov $0,%r15
+
+# qhasm: a3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a3=int64#13
+# asm 2: adc <mulrdx=%rdx,<a3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rsi),>mulrax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#13
+# asm 2: add <mulrax=%rax,<a3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = a1_stack
+# asm 1: movq <a1_stack=stack64#9,>mulx1=int64#9
+# asm 2: movq <a1_stack=64(%rsp),>mulx1=%r11
+movq 64(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rsi),>mulrax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#11
+# asm 2: add <mulrax=%rax,<a1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rsi),>mulrax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#12
+# asm 2: add <mulrax=%rax,<a2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a2 += mulc
+# asm 1: add <mulc=int64#14,<a2=int64#12
+# asm 2: add <mulc=%rbx,<a2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rsi),>mulrax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#13
+# asm 2: add <mulrax=%rax,<a3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#14,<a3=int64#13
+# asm 2: add <mulc=%rbx,<a3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rsi),>mulrax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = a2_stack
+# asm 1: movq <a2_stack=stack64#10,>mulx2=int64#9
+# asm 2: movq <a2_stack=72(%rsp),>mulx2=%r11
+movq 72(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rsi),>mulrax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#12
+# asm 2: add <mulrax=%rax,<a2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rsi),>mulrax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#13
+# asm 2: add <mulrax=%rax,<a3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#14,<a3=int64#13
+# asm 2: add <mulc=%rbx,<a3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rsi),>mulrax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rsi),>mulrax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = a3_stack
+# asm 1: movq <a3_stack=stack64#11,>mulx3=int64#9
+# asm 2: movq <a3_stack=80(%rsp),>mulx3=%r11
+movq 80(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rsi),>mulrax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#13
+# asm 2: add <mulrax=%rax,<a3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rsi),>mulrax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rsi),>mulrax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rsi),>mulrax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? a0 += mulr4
+# asm 1: add <mulr4=int64#4,<a0=int64#10
+# asm 2: add <mulr4=%rcx,<a0=%r12
+add %rcx,%r12
+
+# qhasm: carry? a1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<a1=int64#11
+# asm 2: adc <mulr5=%r8,<a1=%r13
+adc %r8,%r13
+
+# qhasm: carry? a2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<a2=int64#12
+# asm 2: adc <mulr6=%r9,<a2=%r14
+adc %r9,%r14
+
+# qhasm: carry? a3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<a3=int64#13
+# asm 2: adc <mulr7=%r10,<a3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? a0 += mulr8
+# asm 1: add <mulr8=int64#4,<a0=int64#10
+# asm 2: add <mulr8=%rcx,<a0=%r12
+add %rcx,%r12
+
+# qhasm: carry? a1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a1=int64#11
+# asm 2: adc <mulzero=%rdx,<a1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? a2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a2=int64#12
+# asm 2: adc <mulzero=%rdx,<a2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? a3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a3=int64#13
+# asm 2: adc <mulzero=%rdx,<a3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: a0 += mulzero
+# asm 1: add <mulzero=int64#3,<a0=int64#10
+# asm 2: add <mulzero=%rdx,<a0=%r12
+add %rdx,%r12
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#10,>a0_stack=stack64#8
+# asm 2: movq <a0=%r12,>a0_stack=56(%rsp)
+movq %r12,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#11,>a1_stack=stack64#9
+# asm 2: movq <a1=%r13,>a1_stack=64(%rsp)
+movq %r13,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#12,>a2_stack=stack64#10
+# asm 2: movq <a2=%r14,>a2_stack=72(%rsp)
+movq %r14,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#13,>a3_stack=stack64#11
+# asm 2: movq <a3=%r15,>a3_stack=80(%rsp)
+movq %r15,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = b0_stack
+# asm 1: movq <b0_stack=stack64#12,>mulx0=int64#9
+# asm 2: movq <b0_stack=88(%rsp),>mulx0=%r11
+movq 88(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: e0 = mulrax
+# asm 1: mov <mulrax=int64#7,>e0=int64#10
+# asm 2: mov <mulrax=%rax,>e0=%r12
+mov %rax,%r12
+
+# qhasm: e1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>e1=int64#11
+# asm 2: mov <mulrdx=%rdx,>e1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? e1 += mulrax
+# asm 1: add <mulrax=int64#7,<e1=int64#11
+# asm 2: add <mulrax=%rax,<e1=%r13
+add %rax,%r13
+
+# qhasm: e2 = 0
+# asm 1: mov $0,>e2=int64#12
+# asm 2: mov $0,>e2=%r14
+mov $0,%r14
+
+# qhasm: e2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<e2=int64#12
+# asm 2: adc <mulrdx=%rdx,<e2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? e2 += mulrax
+# asm 1: add <mulrax=int64#7,<e2=int64#12
+# asm 2: add <mulrax=%rax,<e2=%r14
+add %rax,%r14
+
+# qhasm: e3 = 0
+# asm 1: mov $0,>e3=int64#13
+# asm 2: mov $0,>e3=%r15
+mov $0,%r15
+
+# qhasm: e3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<e3=int64#13
+# asm 2: adc <mulrdx=%rdx,<e3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#13
+# asm 2: add <mulrax=%rax,<e3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = b1_stack
+# asm 1: movq <b1_stack=stack64#13,>mulx1=int64#9
+# asm 2: movq <b1_stack=96(%rsp),>mulx1=%r11
+movq 96(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? e1 += mulrax
+# asm 1: add <mulrax=int64#7,<e1=int64#11
+# asm 2: add <mulrax=%rax,<e1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? e2 += mulrax
+# asm 1: add <mulrax=int64#7,<e2=int64#12
+# asm 2: add <mulrax=%rax,<e2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? e2 += mulc
+# asm 1: add <mulc=int64#14,<e2=int64#12
+# asm 2: add <mulc=%rbx,<e2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#13
+# asm 2: add <mulrax=%rax,<e3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? e3 += mulc
+# asm 1: add <mulc=int64#14,<e3=int64#13
+# asm 2: add <mulc=%rbx,<e3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = b2_stack
+# asm 1: movq <b2_stack=stack64#14,>mulx2=int64#9
+# asm 2: movq <b2_stack=104(%rsp),>mulx2=%r11
+movq 104(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? e2 += mulrax
+# asm 1: add <mulrax=int64#7,<e2=int64#12
+# asm 2: add <mulrax=%rax,<e2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#13
+# asm 2: add <mulrax=%rax,<e3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? e3 += mulc
+# asm 1: add <mulc=int64#14,<e3=int64#13
+# asm 2: add <mulc=%rbx,<e3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = b3_stack
+# asm 1: movq <b3_stack=stack64#15,>mulx3=int64#9
+# asm 2: movq <b3_stack=112(%rsp),>mulx3=%r11
+movq 112(%rsp),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#13
+# asm 2: add <mulrax=%rax,<e3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? e0 += mulr4
+# asm 1: add <mulr4=int64#4,<e0=int64#10
+# asm 2: add <mulr4=%rcx,<e0=%r12
+add %rcx,%r12
+
+# qhasm: carry? e1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<e1=int64#11
+# asm 2: adc <mulr5=%r8,<e1=%r13
+adc %r8,%r13
+
+# qhasm: carry? e2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<e2=int64#12
+# asm 2: adc <mulr6=%r9,<e2=%r14
+adc %r9,%r14
+
+# qhasm: carry? e3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<e3=int64#13
+# asm 2: adc <mulr7=%r10,<e3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? e0 += mulr8
+# asm 1: add <mulr8=int64#4,<e0=int64#10
+# asm 2: add <mulr8=%rcx,<e0=%r12
+add %rcx,%r12
+
+# qhasm: carry? e1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<e1=int64#11
+# asm 2: adc <mulzero=%rdx,<e1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? e2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<e2=int64#12
+# asm 2: adc <mulzero=%rdx,<e2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? e3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<e3=int64#13
+# asm 2: adc <mulzero=%rdx,<e3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: e0 += mulzero
+# asm 1: add <mulzero=int64#3,<e0=int64#10
+# asm 2: add <mulzero=%rdx,<e0=%r12
+add %rdx,%r12
+
+# qhasm: h0 = e0
+# asm 1: mov <e0=int64#10,>h0=int64#3
+# asm 2: mov <e0=%r12,>h0=%rdx
+mov %r12,%rdx
+
+# qhasm: h1 = e1
+# asm 1: mov <e1=int64#11,>h1=int64#4
+# asm 2: mov <e1=%r13,>h1=%rcx
+mov %r13,%rcx
+
+# qhasm: h2 = e2
+# asm 1: mov <e2=int64#12,>h2=int64#5
+# asm 2: mov <e2=%r14,>h2=%r8
+mov %r14,%r8
+
+# qhasm: h3 = e3
+# asm 1: mov <e3=int64#13,>h3=int64#6
+# asm 2: mov <e3=%r15,>h3=%r9
+mov %r15,%r9
+
+# qhasm: carry? e0 -= a0_stack
+# asm 1: subq <a0_stack=stack64#8,<e0=int64#10
+# asm 2: subq <a0_stack=56(%rsp),<e0=%r12
+subq 56(%rsp),%r12
+
+# qhasm: carry? e1 -= a1_stack - carry
+# asm 1: sbbq <a1_stack=stack64#9,<e1=int64#11
+# asm 2: sbbq <a1_stack=64(%rsp),<e1=%r13
+sbbq 64(%rsp),%r13
+
+# qhasm: carry? e2 -= a2_stack - carry
+# asm 1: sbbq <a2_stack=stack64#10,<e2=int64#12
+# asm 2: sbbq <a2_stack=72(%rsp),<e2=%r14
+sbbq 72(%rsp),%r14
+
+# qhasm: carry? e3 -= a3_stack - carry
+# asm 1: sbbq <a3_stack=stack64#11,<e3=int64#13
+# asm 2: sbbq <a3_stack=80(%rsp),<e3=%r15
+sbbq 80(%rsp),%r15
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#7
+# asm 2: mov $0,>subt0=%rax
+mov $0,%rax
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#8
+# asm 2: mov $38,>subt1=%r10
+mov $38,%r10
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#7,<subt1=int64#8
+# asm 2: cmovae <subt0=%rax,<subt1=%r10
+cmovae %rax,%r10
+
+# qhasm: carry? e0 -= subt1
+# asm 1: sub <subt1=int64#8,<e0=int64#10
+# asm 2: sub <subt1=%r10,<e0=%r12
+sub %r10,%r12
+
+# qhasm: carry? e1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#7,<e1=int64#11
+# asm 2: sbb <subt0=%rax,<e1=%r13
+sbb %rax,%r13
+
+# qhasm: carry? e2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#7,<e2=int64#12
+# asm 2: sbb <subt0=%rax,<e2=%r14
+sbb %rax,%r14
+
+# qhasm: carry? e3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#7,<e3=int64#13
+# asm 2: sbb <subt0=%rax,<e3=%r15
+sbb %rax,%r15
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#8,<subt0=int64#7
+# asm 2: cmovc <subt1=%r10,<subt0=%rax
+cmovc %r10,%rax
+
+# qhasm: e0 -= subt0
+# asm 1: sub <subt0=int64#7,<e0=int64#10
+# asm 2: sub <subt0=%rax,<e0=%r12
+sub %rax,%r12
+
+# qhasm: carry? h0 += a0_stack
+# asm 1: addq <a0_stack=stack64#8,<h0=int64#3
+# asm 2: addq <a0_stack=56(%rsp),<h0=%rdx
+addq 56(%rsp),%rdx
+
+# qhasm: carry? h1 += a1_stack + carry
+# asm 1: adcq <a1_stack=stack64#9,<h1=int64#4
+# asm 2: adcq <a1_stack=64(%rsp),<h1=%rcx
+adcq 64(%rsp),%rcx
+
+# qhasm: carry? h2 += a2_stack + carry
+# asm 1: adcq <a2_stack=stack64#10,<h2=int64#5
+# asm 2: adcq <a2_stack=72(%rsp),<h2=%r8
+adcq 72(%rsp),%r8
+
+# qhasm: carry? h3 += a3_stack + carry
+# asm 1: adcq <a3_stack=stack64#11,<h3=int64#6
+# asm 2: adcq <a3_stack=80(%rsp),<h3=%r9
+adcq 80(%rsp),%r9
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#7
+# asm 2: mov $0,>addt0=%rax
+mov $0,%rax
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#8
+# asm 2: mov $38,>addt1=%r10
+mov $38,%r10
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#7,<addt1=int64#8
+# asm 2: cmovae <addt0=%rax,<addt1=%r10
+cmovae %rax,%r10
+
+# qhasm: carry? h0 += addt1
+# asm 1: add <addt1=int64#8,<h0=int64#3
+# asm 2: add <addt1=%r10,<h0=%rdx
+add %r10,%rdx
+
+# qhasm: carry? h1 += addt0 + carry
+# asm 1: adc <addt0=int64#7,<h1=int64#4
+# asm 2: adc <addt0=%rax,<h1=%rcx
+adc %rax,%rcx
+
+# qhasm: carry? h2 += addt0 + carry
+# asm 1: adc <addt0=int64#7,<h2=int64#5
+# asm 2: adc <addt0=%rax,<h2=%r8
+adc %rax,%r8
+
+# qhasm: carry? h3 += addt0 + carry
+# asm 1: adc <addt0=int64#7,<h3=int64#6
+# asm 2: adc <addt0=%rax,<h3=%r9
+adc %rax,%r9
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#8,<addt0=int64#7
+# asm 2: cmovc <addt1=%r10,<addt0=%rax
+cmovc %r10,%rax
+
+# qhasm: h0 += addt0
+# asm 1: add <addt0=int64#7,<h0=int64#3
+# asm 2: add <addt0=%rax,<h0=%rdx
+add %rax,%rdx
+
+# qhasm: h0_stack = h0
+# asm 1: movq <h0=int64#3,>h0_stack=stack64#8
+# asm 2: movq <h0=%rdx,>h0_stack=56(%rsp)
+movq %rdx,56(%rsp)
+
+# qhasm: h1_stack = h1
+# asm 1: movq <h1=int64#4,>h1_stack=stack64#9
+# asm 2: movq <h1=%rcx,>h1_stack=64(%rsp)
+movq %rcx,64(%rsp)
+
+# qhasm: h2_stack = h2
+# asm 1: movq <h2=int64#5,>h2_stack=stack64#10
+# asm 2: movq <h2=%r8,>h2_stack=72(%rsp)
+movq %r8,72(%rsp)
+
+# qhasm: h3_stack = h3
+# asm 1: movq <h3=int64#6,>h3_stack=stack64#11
+# asm 2: movq <h3=%r9,>h3_stack=80(%rsp)
+movq %r9,80(%rsp)
+
+# qhasm: e0_stack = e0
+# asm 1: movq <e0=int64#10,>e0_stack=stack64#12
+# asm 2: movq <e0=%r12,>e0_stack=88(%rsp)
+movq %r12,88(%rsp)
+
+# qhasm: e1_stack = e1
+# asm 1: movq <e1=int64#11,>e1_stack=stack64#13
+# asm 2: movq <e1=%r13,>e1_stack=96(%rsp)
+movq %r13,96(%rsp)
+
+# qhasm: e2_stack = e2
+# asm 1: movq <e2=int64#12,>e2_stack=stack64#14
+# asm 2: movq <e2=%r14,>e2_stack=104(%rsp)
+movq %r14,104(%rsp)
+
+# qhasm: e3_stack = e3
+# asm 1: movq <e3=int64#13,>e3_stack=stack64#15
+# asm 2: movq <e3=%r15,>e3_stack=112(%rsp)
+movq %r15,112(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(rp + 96)
+# asm 1: movq 96(<rp=int64#1),>mulx0=int64#9
+# asm 2: movq 96(<rp=%rdi),>mulx0=%r11
+movq 96(%rdi),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: c0 = mulrax
+# asm 1: mov <mulrax=int64#7,>c0=int64#10
+# asm 2: mov <mulrax=%rax,>c0=%r12
+mov %rax,%r12
+
+# qhasm: c1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>c1=int64#11
+# asm 2: mov <mulrdx=%rdx,>c1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#11
+# asm 2: add <mulrax=%rax,<c1=%r13
+add %rax,%r13
+
+# qhasm: c2 = 0
+# asm 1: mov $0,>c2=int64#12
+# asm 2: mov $0,>c2=%r14
+mov $0,%r14
+
+# qhasm: c2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c2=int64#12
+# asm 2: adc <mulrdx=%rdx,<c2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#12
+# asm 2: add <mulrax=%rax,<c2=%r14
+add %rax,%r14
+
+# qhasm: c3 = 0
+# asm 1: mov $0,>c3=int64#13
+# asm 2: mov $0,>c3=%r15
+mov $0,%r15
+
+# qhasm: c3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c3=int64#13
+# asm 2: adc <mulrdx=%rdx,<c3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#13
+# asm 2: add <mulrax=%rax,<c3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(rp + 104)
+# asm 1: movq 104(<rp=int64#1),>mulx1=int64#9
+# asm 2: movq 104(<rp=%rdi),>mulx1=%r11
+movq 104(%rdi),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#11
+# asm 2: add <mulrax=%rax,<c1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#12
+# asm 2: add <mulrax=%rax,<c2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c2 += mulc
+# asm 1: add <mulc=int64#14,<c2=int64#12
+# asm 2: add <mulc=%rbx,<c2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#13
+# asm 2: add <mulrax=%rax,<c3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#14,<c3=int64#13
+# asm 2: add <mulc=%rbx,<c3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(rp + 112)
+# asm 1: movq 112(<rp=int64#1),>mulx2=int64#9
+# asm 2: movq 112(<rp=%rdi),>mulx2=%r11
+movq 112(%rdi),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#12
+# asm 2: add <mulrax=%rax,<c2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#13
+# asm 2: add <mulrax=%rax,<c3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#14,<c3=int64#13
+# asm 2: add <mulc=%rbx,<c3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(rp + 120)
+# asm 1: movq 120(<rp=int64#1),>mulx3=int64#9
+# asm 2: movq 120(<rp=%rdi),>mulx3=%r11
+movq 120(%rdi),%r11
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#13
+# asm 2: add <mulrax=%rax,<c3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? c0 += mulr4
+# asm 1: add <mulr4=int64#2,<c0=int64#10
+# asm 2: add <mulr4=%rsi,<c0=%r12
+add %rsi,%r12
+
+# qhasm: carry? c1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<c1=int64#11
+# asm 2: adc <mulr5=%rcx,<c1=%r13
+adc %rcx,%r13
+
+# qhasm: carry? c2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<c2=int64#12
+# asm 2: adc <mulr6=%r8,<c2=%r14
+adc %r8,%r14
+
+# qhasm: carry? c3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<c3=int64#13
+# asm 2: adc <mulr7=%r9,<c3=%r15
+adc %r9,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? c0 += mulr8
+# asm 1: add <mulr8=int64#3,<c0=int64#10
+# asm 2: add <mulr8=%rdx,<c0=%r12
+add %rdx,%r12
+
+# qhasm: carry? c1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<c1=int64#11
+# asm 2: adc <mulzero=%rsi,<c1=%r13
+adc %rsi,%r13
+
+# qhasm: carry? c2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<c2=int64#12
+# asm 2: adc <mulzero=%rsi,<c2=%r14
+adc %rsi,%r14
+
+# qhasm: carry? c3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<c3=int64#13
+# asm 2: adc <mulzero=%rsi,<c3=%r15
+adc %rsi,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: c0 += mulzero
+# asm 1: add <mulzero=int64#2,<c0=int64#10
+# asm 2: add <mulzero=%rsi,<c0=%r12
+add %rsi,%r12
+
+# qhasm: f0 = *(uint64 *)(rp + 64)
+# asm 1: movq 64(<rp=int64#1),>f0=int64#2
+# asm 2: movq 64(<rp=%rdi),>f0=%rsi
+movq 64(%rdi),%rsi
+
+# qhasm: f1 = *(uint64 *)(rp + 72)
+# asm 1: movq 72(<rp=int64#1),>f1=int64#3
+# asm 2: movq 72(<rp=%rdi),>f1=%rdx
+movq 72(%rdi),%rdx
+
+# qhasm: f2 = *(uint64 *)(rp + 80)
+# asm 1: movq 80(<rp=int64#1),>f2=int64#4
+# asm 2: movq 80(<rp=%rdi),>f2=%rcx
+movq 80(%rdi),%rcx
+
+# qhasm: f3 = *(uint64 *)(rp + 88)
+# asm 1: movq 88(<rp=int64#1),>f3=int64#5
+# asm 2: movq 88(<rp=%rdi),>f3=%r8
+movq 88(%rdi),%r8
+
+# qhasm: carry? f0 += f0
+# asm 1: add <f0=int64#2,<f0=int64#2
+# asm 2: add <f0=%rsi,<f0=%rsi
+add %rsi,%rsi
+
+# qhasm: carry? f1 += f1 + carry
+# asm 1: adc <f1=int64#3,<f1=int64#3
+# asm 2: adc <f1=%rdx,<f1=%rdx
+adc %rdx,%rdx
+
+# qhasm: carry? f2 += f2 + carry
+# asm 1: adc <f2=int64#4,<f2=int64#4
+# asm 2: adc <f2=%rcx,<f2=%rcx
+adc %rcx,%rcx
+
+# qhasm: carry? f3 += f3 + carry
+# asm 1: adc <f3=int64#5,<f3=int64#5
+# asm 2: adc <f3=%r8,<f3=%r8
+adc %r8,%r8
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#6
+# asm 2: mov $0,>addt0=%r9
+mov $0,%r9
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#7
+# asm 2: mov $38,>addt1=%rax
+mov $38,%rax
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#6,<addt1=int64#7
+# asm 2: cmovae <addt0=%r9,<addt1=%rax
+cmovae %r9,%rax
+
+# qhasm: carry? f0 += addt1
+# asm 1: add <addt1=int64#7,<f0=int64#2
+# asm 2: add <addt1=%rax,<f0=%rsi
+add %rax,%rsi
+
+# qhasm: carry? f1 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<f1=int64#3
+# asm 2: adc <addt0=%r9,<f1=%rdx
+adc %r9,%rdx
+
+# qhasm: carry? f2 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<f2=int64#4
+# asm 2: adc <addt0=%r9,<f2=%rcx
+adc %r9,%rcx
+
+# qhasm: carry? f3 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<f3=int64#5
+# asm 2: adc <addt0=%r9,<f3=%r8
+adc %r9,%r8
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#7,<addt0=int64#6
+# asm 2: cmovc <addt1=%rax,<addt0=%r9
+cmovc %rax,%r9
+
+# qhasm: f0 += addt0
+# asm 1: add <addt0=int64#6,<f0=int64#2
+# asm 2: add <addt0=%r9,<f0=%rsi
+add %r9,%rsi
+
+# qhasm: g0 = f0
+# asm 1: mov <f0=int64#2,>g0=int64#6
+# asm 2: mov <f0=%rsi,>g0=%r9
+mov %rsi,%r9
+
+# qhasm: g1 = f1
+# asm 1: mov <f1=int64#3,>g1=int64#7
+# asm 2: mov <f1=%rdx,>g1=%rax
+mov %rdx,%rax
+
+# qhasm: g2 = f2
+# asm 1: mov <f2=int64#4,>g2=int64#8
+# asm 2: mov <f2=%rcx,>g2=%r10
+mov %rcx,%r10
+
+# qhasm: g3 = f3
+# asm 1: mov <f3=int64#5,>g3=int64#9
+# asm 2: mov <f3=%r8,>g3=%r11
+mov %r8,%r11
+
+# qhasm: carry? f0 -= c0
+# asm 1: sub <c0=int64#10,<f0=int64#2
+# asm 2: sub <c0=%r12,<f0=%rsi
+sub %r12,%rsi
+
+# qhasm: carry? f1 -= c1 - carry
+# asm 1: sbb <c1=int64#11,<f1=int64#3
+# asm 2: sbb <c1=%r13,<f1=%rdx
+sbb %r13,%rdx
+
+# qhasm: carry? f2 -= c2 - carry
+# asm 1: sbb <c2=int64#12,<f2=int64#4
+# asm 2: sbb <c2=%r14,<f2=%rcx
+sbb %r14,%rcx
+
+# qhasm: carry? f3 -= c3 - carry
+# asm 1: sbb <c3=int64#13,<f3=int64#5
+# asm 2: sbb <c3=%r15,<f3=%r8
+sbb %r15,%r8
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#14
+# asm 2: mov $0,>subt0=%rbx
+mov $0,%rbx
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#15
+# asm 2: mov $38,>subt1=%rbp
+mov $38,%rbp
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#14,<subt1=int64#15
+# asm 2: cmovae <subt0=%rbx,<subt1=%rbp
+cmovae %rbx,%rbp
+
+# qhasm: carry? f0 -= subt1
+# asm 1: sub <subt1=int64#15,<f0=int64#2
+# asm 2: sub <subt1=%rbp,<f0=%rsi
+sub %rbp,%rsi
+
+# qhasm: carry? f1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#14,<f1=int64#3
+# asm 2: sbb <subt0=%rbx,<f1=%rdx
+sbb %rbx,%rdx
+
+# qhasm: carry? f2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#14,<f2=int64#4
+# asm 2: sbb <subt0=%rbx,<f2=%rcx
+sbb %rbx,%rcx
+
+# qhasm: carry? f3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#14,<f3=int64#5
+# asm 2: sbb <subt0=%rbx,<f3=%r8
+sbb %rbx,%r8
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#15,<subt0=int64#14
+# asm 2: cmovc <subt1=%rbp,<subt0=%rbx
+cmovc %rbp,%rbx
+
+# qhasm: f0 -= subt0
+# asm 1: sub <subt0=int64#14,<f0=int64#2
+# asm 2: sub <subt0=%rbx,<f0=%rsi
+sub %rbx,%rsi
+
+# qhasm: carry? g0 += c0
+# asm 1: add <c0=int64#10,<g0=int64#6
+# asm 2: add <c0=%r12,<g0=%r9
+add %r12,%r9
+
+# qhasm: carry? g1 += c1 + carry
+# asm 1: adc <c1=int64#11,<g1=int64#7
+# asm 2: adc <c1=%r13,<g1=%rax
+adc %r13,%rax
+
+# qhasm: carry? g2 += c2 + carry
+# asm 1: adc <c2=int64#12,<g2=int64#8
+# asm 2: adc <c2=%r14,<g2=%r10
+adc %r14,%r10
+
+# qhasm: carry? g3 += c3 + carry
+# asm 1: adc <c3=int64#13,<g3=int64#9
+# asm 2: adc <c3=%r15,<g3=%r11
+adc %r15,%r11
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#10
+# asm 2: mov $0,>addt0=%r12
+mov $0,%r12
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#11
+# asm 2: mov $38,>addt1=%r13
+mov $38,%r13
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#10,<addt1=int64#11
+# asm 2: cmovae <addt0=%r12,<addt1=%r13
+cmovae %r12,%r13
+
+# qhasm: carry? g0 += addt1
+# asm 1: add <addt1=int64#11,<g0=int64#6
+# asm 2: add <addt1=%r13,<g0=%r9
+add %r13,%r9
+
+# qhasm: carry? g1 += addt0 + carry
+# asm 1: adc <addt0=int64#10,<g1=int64#7
+# asm 2: adc <addt0=%r12,<g1=%rax
+adc %r12,%rax
+
+# qhasm: carry? g2 += addt0 + carry
+# asm 1: adc <addt0=int64#10,<g2=int64#8
+# asm 2: adc <addt0=%r12,<g2=%r10
+adc %r12,%r10
+
+# qhasm: carry? g3 += addt0 + carry
+# asm 1: adc <addt0=int64#10,<g3=int64#9
+# asm 2: adc <addt0=%r12,<g3=%r11
+adc %r12,%r11
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#11,<addt0=int64#10
+# asm 2: cmovc <addt1=%r13,<addt0=%r12
+cmovc %r13,%r12
+
+# qhasm: g0 += addt0
+# asm 1: add <addt0=int64#10,<g0=int64#6
+# asm 2: add <addt0=%r12,<g0=%r9
+add %r12,%r9
+
+# qhasm: g0_stack = g0
+# asm 1: movq <g0=int64#6,>g0_stack=stack64#16
+# asm 2: movq <g0=%r9,>g0_stack=120(%rsp)
+movq %r9,120(%rsp)
+
+# qhasm: g1_stack = g1
+# asm 1: movq <g1=int64#7,>g1_stack=stack64#17
+# asm 2: movq <g1=%rax,>g1_stack=128(%rsp)
+movq %rax,128(%rsp)
+
+# qhasm: g2_stack = g2
+# asm 1: movq <g2=int64#8,>g2_stack=stack64#18
+# asm 2: movq <g2=%r10,>g2_stack=136(%rsp)
+movq %r10,136(%rsp)
+
+# qhasm: g3_stack = g3
+# asm 1: movq <g3=int64#9,>g3_stack=stack64#19
+# asm 2: movq <g3=%r11,>g3_stack=144(%rsp)
+movq %r11,144(%rsp)
+
+# qhasm: f0_stack = f0
+# asm 1: movq <f0=int64#2,>f0_stack=stack64#20
+# asm 2: movq <f0=%rsi,>f0_stack=152(%rsp)
+movq %rsi,152(%rsp)
+
+# qhasm: f1_stack = f1
+# asm 1: movq <f1=int64#3,>f1_stack=stack64#21
+# asm 2: movq <f1=%rdx,>f1_stack=160(%rsp)
+movq %rdx,160(%rsp)
+
+# qhasm: f2_stack = f2
+# asm 1: movq <f2=int64#4,>f2_stack=stack64#22
+# asm 2: movq <f2=%rcx,>f2_stack=168(%rsp)
+movq %rcx,168(%rsp)
+
+# qhasm: f3_stack = f3
+# asm 1: movq <f3=int64#5,>f3_stack=stack64#23
+# asm 2: movq <f3=%r8,>f3_stack=176(%rsp)
+movq %r8,176(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#2
+# asm 2: mov $0,>mulr4=%rsi
+mov $0,%rsi
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#4
+# asm 2: mov $0,>mulr5=%rcx
+mov $0,%rcx
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulx0 = e0_stack
+# asm 1: movq <e0_stack=stack64#12,>mulx0=int64#8
+# asm 2: movq <e0_stack=88(%rsp),>mulx0=%r10
+movq 88(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: rx0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rx0=int64#9
+# asm 2: mov <mulrax=%rax,>rx0=%r11
+mov %rax,%r11
+
+# qhasm: rx1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rx1=int64#10
+# asm 2: mov <mulrdx=%rdx,>rx1=%r12
+mov %rdx,%r12
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#10
+# asm 2: add <mulrax=%rax,<rx1=%r12
+add %rax,%r12
+
+# qhasm: rx2 = 0
+# asm 1: mov $0,>rx2=int64#11
+# asm 2: mov $0,>rx2=%r13
+mov $0,%r13
+
+# qhasm: rx2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx2=int64#11
+# asm 2: adc <mulrdx=%rdx,<rx2=%r13
+adc %rdx,%r13
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#11
+# asm 2: add <mulrax=%rax,<rx2=%r13
+add %rax,%r13
+
+# qhasm: rx3 = 0
+# asm 1: mov $0,>rx3=int64#12
+# asm 2: mov $0,>rx3=%r14
+mov $0,%r14
+
+# qhasm: rx3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx3=int64#12
+# asm 2: adc <mulrdx=%rdx,<rx3=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#12
+# asm 2: add <mulrax=%rax,<rx3=%r14
+add %rax,%r14
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#2
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rsi
+adc %rdx,%rsi
+
+# qhasm: mulx1 = e1_stack
+# asm 1: movq <e1_stack=stack64#13,>mulx1=int64#8
+# asm 2: movq <e1_stack=96(%rsp),>mulx1=%r10
+movq 96(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#10
+# asm 2: add <mulrax=%rax,<rx1=%r12
+add %rax,%r12
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#11
+# asm 2: add <mulrax=%rax,<rx2=%r13
+add %rax,%r13
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx2 += mulc
+# asm 1: add <mulc=int64#13,<rx2=int64#11
+# asm 2: add <mulc=%r15,<rx2=%r13
+add %r15,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#12
+# asm 2: add <mulrax=%rax,<rx3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#13,<rx3=int64#12
+# asm 2: add <mulc=%r15,<rx3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr5=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx2 = e2_stack
+# asm 1: movq <e2_stack=stack64#14,>mulx2=int64#8
+# asm 2: movq <e2_stack=104(%rsp),>mulx2=%r10
+movq 104(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#11
+# asm 2: add <mulrax=%rax,<rx2=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#12
+# asm 2: add <mulrax=%rax,<rx3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#13,<rx3=int64#12
+# asm 2: add <mulc=%r15,<rx3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: mulx3 = e3_stack
+# asm 1: movq <e3_stack=stack64#15,>mulx3=int64#8
+# asm 2: movq <e3_stack=112(%rsp),>mulx3=%r10
+movq 112(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#12
+# asm 2: add <mulrax=%rax,<rx3=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#13,<mulr6=int64#5
+# asm 2: add <mulc=%r15,<mulr6=%r8
+add %r15,%r8
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#2,>mulrax=int64#7
+# asm 2: mov <mulr4=%rsi,>mulrax=%rax
+mov %rsi,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr5=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr6=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr7=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rx0 += mulr4
+# asm 1: add <mulr4=int64#2,<rx0=int64#9
+# asm 2: add <mulr4=%rsi,<rx0=%r11
+add %rsi,%r11
+
+# qhasm: carry? rx1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rx1=int64#10
+# asm 2: adc <mulr5=%rcx,<rx1=%r12
+adc %rcx,%r12
+
+# qhasm: carry? rx2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rx2=int64#11
+# asm 2: adc <mulr6=%r8,<rx2=%r13
+adc %r8,%r13
+
+# qhasm: carry? rx3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rx3=int64#12
+# asm 2: adc <mulr7=%r9,<rx3=%r14
+adc %r9,%r14
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rx0 += mulr8
+# asm 1: add <mulr8=int64#3,<rx0=int64#9
+# asm 2: add <mulr8=%rdx,<rx0=%r11
+add %rdx,%r11
+
+# qhasm: carry? rx1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rx1=int64#10
+# asm 2: adc <mulzero=%rsi,<rx1=%r12
+adc %rsi,%r12
+
+# qhasm: carry? rx2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rx2=int64#11
+# asm 2: adc <mulzero=%rsi,<rx2=%r13
+adc %rsi,%r13
+
+# qhasm: carry? rx3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rx3=int64#12
+# asm 2: adc <mulzero=%rsi,<rx3=%r14
+adc %rsi,%r14
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rx0 += mulzero
+# asm 1: add <mulzero=int64#2,<rx0=int64#9
+# asm 2: add <mulzero=%rsi,<rx0=%r11
+add %rsi,%r11
+
+# qhasm: *(uint64 *)(rp + 0) = rx0
+# asm 1: movq <rx0=int64#9,0(<rp=int64#1)
+# asm 2: movq <rx0=%r11,0(<rp=%rdi)
+movq %r11,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = rx1
+# asm 1: movq <rx1=int64#10,8(<rp=int64#1)
+# asm 2: movq <rx1=%r12,8(<rp=%rdi)
+movq %r12,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = rx2
+# asm 1: movq <rx2=int64#11,16(<rp=int64#1)
+# asm 2: movq <rx2=%r13,16(<rp=%rdi)
+movq %r13,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = rx3
+# asm 1: movq <rx3=int64#12,24(<rp=int64#1)
+# asm 2: movq <rx3=%r14,24(<rp=%rdi)
+movq %r14,24(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#2
+# asm 2: mov $0,>mulr4=%rsi
+mov $0,%rsi
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#4
+# asm 2: mov $0,>mulr5=%rcx
+mov $0,%rcx
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulx0 = h0_stack
+# asm 1: movq <h0_stack=stack64#8,>mulx0=int64#8
+# asm 2: movq <h0_stack=56(%rsp),>mulx0=%r10
+movq 56(%rsp),%r10
+
+# qhasm: mulrax = g0_stack
+# asm 1: movq <g0_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <g0_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: ry0 = mulrax
+# asm 1: mov <mulrax=int64#7,>ry0=int64#9
+# asm 2: mov <mulrax=%rax,>ry0=%r11
+mov %rax,%r11
+
+# qhasm: ry1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>ry1=int64#10
+# asm 2: mov <mulrdx=%rdx,>ry1=%r12
+mov %rdx,%r12
+
+# qhasm: mulrax = g1_stack
+# asm 1: movq <g1_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <g1_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? ry1 += mulrax
+# asm 1: add <mulrax=int64#7,<ry1=int64#10
+# asm 2: add <mulrax=%rax,<ry1=%r12
+add %rax,%r12
+
+# qhasm: ry2 = 0
+# asm 1: mov $0,>ry2=int64#11
+# asm 2: mov $0,>ry2=%r13
+mov $0,%r13
+
+# qhasm: ry2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<ry2=int64#11
+# asm 2: adc <mulrdx=%rdx,<ry2=%r13
+adc %rdx,%r13
+
+# qhasm: mulrax = g2_stack
+# asm 1: movq <g2_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <g2_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#11
+# asm 2: add <mulrax=%rax,<ry2=%r13
+add %rax,%r13
+
+# qhasm: ry3 = 0
+# asm 1: mov $0,>ry3=int64#12
+# asm 2: mov $0,>ry3=%r14
+mov $0,%r14
+
+# qhasm: ry3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<ry3=int64#12
+# asm 2: adc <mulrdx=%rdx,<ry3=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = g3_stack
+# asm 1: movq <g3_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <g3_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#12
+# asm 2: add <mulrax=%rax,<ry3=%r14
+add %rax,%r14
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#2
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rsi
+adc %rdx,%rsi
+
+# qhasm: mulx1 = h1_stack
+# asm 1: movq <h1_stack=stack64#9,>mulx1=int64#8
+# asm 2: movq <h1_stack=64(%rsp),>mulx1=%r10
+movq 64(%rsp),%r10
+
+# qhasm: mulrax = g0_stack
+# asm 1: movq <g0_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <g0_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? ry1 += mulrax
+# asm 1: add <mulrax=int64#7,<ry1=int64#10
+# asm 2: add <mulrax=%rax,<ry1=%r12
+add %rax,%r12
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g1_stack
+# asm 1: movq <g1_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <g1_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#11
+# asm 2: add <mulrax=%rax,<ry2=%r13
+add %rax,%r13
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry2 += mulc
+# asm 1: add <mulc=int64#13,<ry2=int64#11
+# asm 2: add <mulc=%r15,<ry2=%r13
+add %r15,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g2_stack
+# asm 1: movq <g2_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <g2_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#12
+# asm 2: add <mulrax=%rax,<ry3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry3 += mulc
+# asm 1: add <mulc=int64#13,<ry3=int64#12
+# asm 2: add <mulc=%r15,<ry3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g3_stack
+# asm 1: movq <g3_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <g3_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr5=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx2 = h2_stack
+# asm 1: movq <h2_stack=stack64#10,>mulx2=int64#8
+# asm 2: movq <h2_stack=72(%rsp),>mulx2=%r10
+movq 72(%rsp),%r10
+
+# qhasm: mulrax = g0_stack
+# asm 1: movq <g0_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <g0_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#11
+# asm 2: add <mulrax=%rax,<ry2=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g1_stack
+# asm 1: movq <g1_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <g1_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#12
+# asm 2: add <mulrax=%rax,<ry3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry3 += mulc
+# asm 1: add <mulc=int64#13,<ry3=int64#12
+# asm 2: add <mulc=%r15,<ry3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g2_stack
+# asm 1: movq <g2_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <g2_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g3_stack
+# asm 1: movq <g3_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <g3_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: mulx3 = h3_stack
+# asm 1: movq <h3_stack=stack64#11,>mulx3=int64#8
+# asm 2: movq <h3_stack=80(%rsp),>mulx3=%r10
+movq 80(%rsp),%r10
+
+# qhasm: mulrax = g0_stack
+# asm 1: movq <g0_stack=stack64#16,>mulrax=int64#7
+# asm 2: movq <g0_stack=120(%rsp),>mulrax=%rax
+movq 120(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#12
+# asm 2: add <mulrax=%rax,<ry3=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g1_stack
+# asm 1: movq <g1_stack=stack64#17,>mulrax=int64#7
+# asm 2: movq <g1_stack=128(%rsp),>mulrax=%rax
+movq 128(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g2_stack
+# asm 1: movq <g2_stack=stack64#18,>mulrax=int64#7
+# asm 2: movq <g2_stack=136(%rsp),>mulrax=%rax
+movq 136(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = g3_stack
+# asm 1: movq <g3_stack=stack64#19,>mulrax=int64#7
+# asm 2: movq <g3_stack=144(%rsp),>mulrax=%rax
+movq 144(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#13,<mulr6=int64#5
+# asm 2: add <mulc=%r15,<mulr6=%r8
+add %r15,%r8
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#2,>mulrax=int64#7
+# asm 2: mov <mulr4=%rsi,>mulrax=%rax
+mov %rsi,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr5=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr6=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr7=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? ry0 += mulr4
+# asm 1: add <mulr4=int64#2,<ry0=int64#9
+# asm 2: add <mulr4=%rsi,<ry0=%r11
+add %rsi,%r11
+
+# qhasm: carry? ry1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<ry1=int64#10
+# asm 2: adc <mulr5=%rcx,<ry1=%r12
+adc %rcx,%r12
+
+# qhasm: carry? ry2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<ry2=int64#11
+# asm 2: adc <mulr6=%r8,<ry2=%r13
+adc %r8,%r13
+
+# qhasm: carry? ry3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<ry3=int64#12
+# asm 2: adc <mulr7=%r9,<ry3=%r14
+adc %r9,%r14
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? ry0 += mulr8
+# asm 1: add <mulr8=int64#3,<ry0=int64#9
+# asm 2: add <mulr8=%rdx,<ry0=%r11
+add %rdx,%r11
+
+# qhasm: carry? ry1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<ry1=int64#10
+# asm 2: adc <mulzero=%rsi,<ry1=%r12
+adc %rsi,%r12
+
+# qhasm: carry? ry2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<ry2=int64#11
+# asm 2: adc <mulzero=%rsi,<ry2=%r13
+adc %rsi,%r13
+
+# qhasm: carry? ry3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<ry3=int64#12
+# asm 2: adc <mulzero=%rsi,<ry3=%r14
+adc %rsi,%r14
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: ry0 += mulzero
+# asm 1: add <mulzero=int64#2,<ry0=int64#9
+# asm 2: add <mulzero=%rsi,<ry0=%r11
+add %rsi,%r11
+
+# qhasm: *(uint64 *)(rp + 32) = ry0
+# asm 1: movq <ry0=int64#9,32(<rp=int64#1)
+# asm 2: movq <ry0=%r11,32(<rp=%rdi)
+movq %r11,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = ry1
+# asm 1: movq <ry1=int64#10,40(<rp=int64#1)
+# asm 2: movq <ry1=%r12,40(<rp=%rdi)
+movq %r12,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = ry2
+# asm 1: movq <ry2=int64#11,48(<rp=int64#1)
+# asm 2: movq <ry2=%r13,48(<rp=%rdi)
+movq %r13,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = ry3
+# asm 1: movq <ry3=int64#12,56(<rp=int64#1)
+# asm 2: movq <ry3=%r14,56(<rp=%rdi)
+movq %r14,56(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#2
+# asm 2: mov $0,>mulr4=%rsi
+mov $0,%rsi
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#4
+# asm 2: mov $0,>mulr5=%rcx
+mov $0,%rcx
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulx0 = g0_stack
+# asm 1: movq <g0_stack=stack64#16,>mulx0=int64#8
+# asm 2: movq <g0_stack=120(%rsp),>mulx0=%r10
+movq 120(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: rz0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rz0=int64#9
+# asm 2: mov <mulrax=%rax,>rz0=%r11
+mov %rax,%r11
+
+# qhasm: rz1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rz1=int64#10
+# asm 2: mov <mulrdx=%rdx,>rz1=%r12
+mov %rdx,%r12
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rz1 += mulrax
+# asm 1: add <mulrax=int64#7,<rz1=int64#10
+# asm 2: add <mulrax=%rax,<rz1=%r12
+add %rax,%r12
+
+# qhasm: rz2 = 0
+# asm 1: mov $0,>rz2=int64#11
+# asm 2: mov $0,>rz2=%r13
+mov $0,%r13
+
+# qhasm: rz2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rz2=int64#11
+# asm 2: adc <mulrdx=%rdx,<rz2=%r13
+adc %rdx,%r13
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#11
+# asm 2: add <mulrax=%rax,<rz2=%r13
+add %rax,%r13
+
+# qhasm: rz3 = 0
+# asm 1: mov $0,>rz3=int64#12
+# asm 2: mov $0,>rz3=%r14
+mov $0,%r14
+
+# qhasm: rz3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rz3=int64#12
+# asm 2: adc <mulrdx=%rdx,<rz3=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#12
+# asm 2: add <mulrax=%rax,<rz3=%r14
+add %rax,%r14
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#2
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rsi
+adc %rdx,%rsi
+
+# qhasm: mulx1 = g1_stack
+# asm 1: movq <g1_stack=stack64#17,>mulx1=int64#8
+# asm 2: movq <g1_stack=128(%rsp),>mulx1=%r10
+movq 128(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rz1 += mulrax
+# asm 1: add <mulrax=int64#7,<rz1=int64#10
+# asm 2: add <mulrax=%rax,<rz1=%r12
+add %rax,%r12
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#11
+# asm 2: add <mulrax=%rax,<rz2=%r13
+add %rax,%r13
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz2 += mulc
+# asm 1: add <mulc=int64#13,<rz2=int64#11
+# asm 2: add <mulc=%r15,<rz2=%r13
+add %r15,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#12
+# asm 2: add <mulrax=%rax,<rz3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz3 += mulc
+# asm 1: add <mulc=int64#13,<rz3=int64#12
+# asm 2: add <mulc=%r15,<rz3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr5=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx2 = g2_stack
+# asm 1: movq <g2_stack=stack64#18,>mulx2=int64#8
+# asm 2: movq <g2_stack=136(%rsp),>mulx2=%r10
+movq 136(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#11
+# asm 2: add <mulrax=%rax,<rz2=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#12
+# asm 2: add <mulrax=%rax,<rz3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz3 += mulc
+# asm 1: add <mulc=int64#13,<rz3=int64#12
+# asm 2: add <mulc=%r15,<rz3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: mulx3 = g3_stack
+# asm 1: movq <g3_stack=stack64#19,>mulx3=int64#8
+# asm 2: movq <g3_stack=144(%rsp),>mulx3=%r10
+movq 144(%rsp),%r10
+
+# qhasm: mulrax = f0_stack
+# asm 1: movq <f0_stack=stack64#20,>mulrax=int64#7
+# asm 2: movq <f0_stack=152(%rsp),>mulrax=%rax
+movq 152(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#12
+# asm 2: add <mulrax=%rax,<rz3=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f1_stack
+# asm 1: movq <f1_stack=stack64#21,>mulrax=int64#7
+# asm 2: movq <f1_stack=160(%rsp),>mulrax=%rax
+movq 160(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f2_stack
+# asm 1: movq <f2_stack=stack64#22,>mulrax=int64#7
+# asm 2: movq <f2_stack=168(%rsp),>mulrax=%rax
+movq 168(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = f3_stack
+# asm 1: movq <f3_stack=stack64#23,>mulrax=int64#7
+# asm 2: movq <f3_stack=176(%rsp),>mulrax=%rax
+movq 176(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#13,<mulr6=int64#5
+# asm 2: add <mulc=%r15,<mulr6=%r8
+add %r15,%r8
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#2,>mulrax=int64#7
+# asm 2: mov <mulr4=%rsi,>mulrax=%rax
+mov %rsi,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr5=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr6=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr7=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rz0 += mulr4
+# asm 1: add <mulr4=int64#2,<rz0=int64#9
+# asm 2: add <mulr4=%rsi,<rz0=%r11
+add %rsi,%r11
+
+# qhasm: carry? rz1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rz1=int64#10
+# asm 2: adc <mulr5=%rcx,<rz1=%r12
+adc %rcx,%r12
+
+# qhasm: carry? rz2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rz2=int64#11
+# asm 2: adc <mulr6=%r8,<rz2=%r13
+adc %r8,%r13
+
+# qhasm: carry? rz3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rz3=int64#12
+# asm 2: adc <mulr7=%r9,<rz3=%r14
+adc %r9,%r14
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rz0 += mulr8
+# asm 1: add <mulr8=int64#3,<rz0=int64#9
+# asm 2: add <mulr8=%rdx,<rz0=%r11
+add %rdx,%r11
+
+# qhasm: carry? rz1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rz1=int64#10
+# asm 2: adc <mulzero=%rsi,<rz1=%r12
+adc %rsi,%r12
+
+# qhasm: carry? rz2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rz2=int64#11
+# asm 2: adc <mulzero=%rsi,<rz2=%r13
+adc %rsi,%r13
+
+# qhasm: carry? rz3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rz3=int64#12
+# asm 2: adc <mulzero=%rsi,<rz3=%r14
+adc %rsi,%r14
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rz0 += mulzero
+# asm 1: add <mulzero=int64#2,<rz0=int64#9
+# asm 2: add <mulzero=%rsi,<rz0=%r11
+add %rsi,%r11
+
+# qhasm: *(uint64 *)(rp + 64) = rz0
+# asm 1: movq <rz0=int64#9,64(<rp=int64#1)
+# asm 2: movq <rz0=%r11,64(<rp=%rdi)
+movq %r11,64(%rdi)
+
+# qhasm: *(uint64 *)(rp + 72) = rz1
+# asm 1: movq <rz1=int64#10,72(<rp=int64#1)
+# asm 2: movq <rz1=%r12,72(<rp=%rdi)
+movq %r12,72(%rdi)
+
+# qhasm: *(uint64 *)(rp + 80) = rz2
+# asm 1: movq <rz2=int64#11,80(<rp=int64#1)
+# asm 2: movq <rz2=%r13,80(<rp=%rdi)
+movq %r13,80(%rdi)
+
+# qhasm: *(uint64 *)(rp + 88) = rz3
+# asm 1: movq <rz3=int64#12,88(<rp=int64#1)
+# asm 2: movq <rz3=%r14,88(<rp=%rdi)
+movq %r14,88(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#2
+# asm 2: mov $0,>mulr4=%rsi
+mov $0,%rsi
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#4
+# asm 2: mov $0,>mulr5=%rcx
+mov $0,%rcx
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulx0 = e0_stack
+# asm 1: movq <e0_stack=stack64#12,>mulx0=int64#8
+# asm 2: movq <e0_stack=88(%rsp),>mulx0=%r10
+movq 88(%rsp),%r10
+
+# qhasm: mulrax = h0_stack
+# asm 1: movq <h0_stack=stack64#8,>mulrax=int64#7
+# asm 2: movq <h0_stack=56(%rsp),>mulrax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: rt0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rt0=int64#9
+# asm 2: mov <mulrax=%rax,>rt0=%r11
+mov %rax,%r11
+
+# qhasm: rt1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rt1=int64#10
+# asm 2: mov <mulrdx=%rdx,>rt1=%r12
+mov %rdx,%r12
+
+# qhasm: mulrax = h1_stack
+# asm 1: movq <h1_stack=stack64#9,>mulrax=int64#7
+# asm 2: movq <h1_stack=64(%rsp),>mulrax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#10
+# asm 2: add <mulrax=%rax,<rt1=%r12
+add %rax,%r12
+
+# qhasm: rt2 = 0
+# asm 1: mov $0,>rt2=int64#11
+# asm 2: mov $0,>rt2=%r13
+mov $0,%r13
+
+# qhasm: rt2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt2=int64#11
+# asm 2: adc <mulrdx=%rdx,<rt2=%r13
+adc %rdx,%r13
+
+# qhasm: mulrax = h2_stack
+# asm 1: movq <h2_stack=stack64#10,>mulrax=int64#7
+# asm 2: movq <h2_stack=72(%rsp),>mulrax=%rax
+movq 72(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#11
+# asm 2: add <mulrax=%rax,<rt2=%r13
+add %rax,%r13
+
+# qhasm: rt3 = 0
+# asm 1: mov $0,>rt3=int64#12
+# asm 2: mov $0,>rt3=%r14
+mov $0,%r14
+
+# qhasm: rt3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt3=int64#12
+# asm 2: adc <mulrdx=%rdx,<rt3=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = h3_stack
+# asm 1: movq <h3_stack=stack64#11,>mulrax=int64#7
+# asm 2: movq <h3_stack=80(%rsp),>mulrax=%rax
+movq 80(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#8
+# asm 2: mul <mulx0=%r10
+mul %r10
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#12
+# asm 2: add <mulrax=%rax,<rt3=%r14
+add %rax,%r14
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#2
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rsi
+adc %rdx,%rsi
+
+# qhasm: mulx1 = e1_stack
+# asm 1: movq <e1_stack=stack64#13,>mulx1=int64#8
+# asm 2: movq <e1_stack=96(%rsp),>mulx1=%r10
+movq 96(%rsp),%r10
+
+# qhasm: mulrax = h0_stack
+# asm 1: movq <h0_stack=stack64#8,>mulrax=int64#7
+# asm 2: movq <h0_stack=56(%rsp),>mulrax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#10
+# asm 2: add <mulrax=%rax,<rt1=%r12
+add %rax,%r12
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h1_stack
+# asm 1: movq <h1_stack=stack64#9,>mulrax=int64#7
+# asm 2: movq <h1_stack=64(%rsp),>mulrax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#11
+# asm 2: add <mulrax=%rax,<rt2=%r13
+add %rax,%r13
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt2 += mulc
+# asm 1: add <mulc=int64#13,<rt2=int64#11
+# asm 2: add <mulc=%r15,<rt2=%r13
+add %r15,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h2_stack
+# asm 1: movq <h2_stack=stack64#10,>mulrax=int64#7
+# asm 2: movq <h2_stack=72(%rsp),>mulrax=%rax
+movq 72(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#12
+# asm 2: add <mulrax=%rax,<rt3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#13,<rt3=int64#12
+# asm 2: add <mulc=%r15,<rt3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h3_stack
+# asm 1: movq <h3_stack=stack64#11,>mulrax=int64#7
+# asm 2: movq <h3_stack=80(%rsp),>mulrax=%rax
+movq 80(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#8
+# asm 2: mul <mulx1=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr5=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx2 = e2_stack
+# asm 1: movq <e2_stack=stack64#14,>mulx2=int64#8
+# asm 2: movq <e2_stack=104(%rsp),>mulx2=%r10
+movq 104(%rsp),%r10
+
+# qhasm: mulrax = h0_stack
+# asm 1: movq <h0_stack=stack64#8,>mulrax=int64#7
+# asm 2: movq <h0_stack=56(%rsp),>mulrax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#11
+# asm 2: add <mulrax=%rax,<rt2=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h1_stack
+# asm 1: movq <h1_stack=stack64#9,>mulrax=int64#7
+# asm 2: movq <h1_stack=64(%rsp),>mulrax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#12
+# asm 2: add <mulrax=%rax,<rt3=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#13,<rt3=int64#12
+# asm 2: add <mulc=%r15,<rt3=%r14
+add %r15,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h2_stack
+# asm 1: movq <h2_stack=stack64#10,>mulrax=int64#7
+# asm 2: movq <h2_stack=72(%rsp),>mulrax=%rax
+movq 72(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h3_stack
+# asm 1: movq <h3_stack=stack64#11,>mulrax=int64#7
+# asm 2: movq <h3_stack=80(%rsp),>mulrax=%rax
+movq 80(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#8
+# asm 2: mul <mulx2=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: mulx3 = e3_stack
+# asm 1: movq <e3_stack=stack64#15,>mulx3=int64#8
+# asm 2: movq <e3_stack=112(%rsp),>mulx3=%r10
+movq 112(%rsp),%r10
+
+# qhasm: mulrax = h0_stack
+# asm 1: movq <h0_stack=stack64#8,>mulrax=int64#7
+# asm 2: movq <h0_stack=56(%rsp),>mulrax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#12
+# asm 2: add <mulrax=%rax,<rt3=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h1_stack
+# asm 1: movq <h1_stack=stack64#9,>mulrax=int64#7
+# asm 2: movq <h1_stack=64(%rsp),>mulrax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#2
+# asm 2: add <mulrax=%rax,<mulr4=%rsi
+add %rax,%rsi
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#13,<mulr4=int64#2
+# asm 2: add <mulc=%r15,<mulr4=%rsi
+add %r15,%rsi
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h2_stack
+# asm 1: movq <h2_stack=stack64#10,>mulrax=int64#7
+# asm 2: movq <h2_stack=72(%rsp),>mulrax=%rax
+movq 72(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#13,<mulr5=int64#4
+# asm 2: add <mulc=%r15,<mulr5=%rcx
+add %r15,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#13
+# asm 2: mov $0,>mulc=%r15
+mov $0,%r15
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#13
+# asm 2: adc <mulrdx=%rdx,<mulc=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = h3_stack
+# asm 1: movq <h3_stack=stack64#11,>mulrax=int64#7
+# asm 2: movq <h3_stack=80(%rsp),>mulrax=%rax
+movq 80(%rsp),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#8
+# asm 2: mul <mulx3=%r10
+mul %r10
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#13,<mulr6=int64#5
+# asm 2: add <mulc=%r15,<mulr6=%r8
+add %r15,%r8
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#2,>mulrax=int64#7
+# asm 2: mov <mulr4=%rsi,>mulrax=%rax
+mov %rsi,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr5=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr6=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr7=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rt0 += mulr4
+# asm 1: add <mulr4=int64#2,<rt0=int64#9
+# asm 2: add <mulr4=%rsi,<rt0=%r11
+add %rsi,%r11
+
+# qhasm: carry? rt1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rt1=int64#10
+# asm 2: adc <mulr5=%rcx,<rt1=%r12
+adc %rcx,%r12
+
+# qhasm: carry? rt2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rt2=int64#11
+# asm 2: adc <mulr6=%r8,<rt2=%r13
+adc %r8,%r13
+
+# qhasm: carry? rt3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rt3=int64#12
+# asm 2: adc <mulr7=%r9,<rt3=%r14
+adc %r9,%r14
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rt0 += mulr8
+# asm 1: add <mulr8=int64#3,<rt0=int64#9
+# asm 2: add <mulr8=%rdx,<rt0=%r11
+add %rdx,%r11
+
+# qhasm: carry? rt1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt1=int64#10
+# asm 2: adc <mulzero=%rsi,<rt1=%r12
+adc %rsi,%r12
+
+# qhasm: carry? rt2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt2=int64#11
+# asm 2: adc <mulzero=%rsi,<rt2=%r13
+adc %rsi,%r13
+
+# qhasm: carry? rt3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt3=int64#12
+# asm 2: adc <mulzero=%rsi,<rt3=%r14
+adc %rsi,%r14
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rt0 += mulzero
+# asm 1: add <mulzero=int64#2,<rt0=int64#9
+# asm 2: add <mulzero=%rsi,<rt0=%r11
+add %rsi,%r11
+
+# qhasm: *(uint64 *)(rp + 96) = rt0
+# asm 1: movq <rt0=int64#9,96(<rp=int64#1)
+# asm 2: movq <rt0=%r11,96(<rp=%rdi)
+movq %r11,96(%rdi)
+
+# qhasm: *(uint64 *)(rp + 104) = rt1
+# asm 1: movq <rt1=int64#10,104(<rp=int64#1)
+# asm 2: movq <rt1=%r12,104(<rp=%rdi)
+movq %r12,104(%rdi)
+
+# qhasm: *(uint64 *)(rp + 112) = rt2
+# asm 1: movq <rt2=int64#11,112(<rp=int64#1)
+# asm 2: movq <rt2=%r13,112(<rp=%rdi)
+movq %r13,112(%rdi)
+
+# qhasm: *(uint64 *)(rp + 120) = rt3
+# asm 1: movq <rt3=int64#12,120(<rp=int64#1)
+# asm 2: movq <rt3=%r14,120(<rp=%rdi)
+movq %r14,120(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s b/ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s
new file mode 100644
index 00000000..b5629462
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_nielsadd_p1p1.s
@@ -0,0 +1,3072 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 pp
+
+# qhasm: int64 qp
+
+# qhasm: input rp
+
+# qhasm: input pp
+
+# qhasm: input qp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 a0
+
+# qhasm: int64 a1
+
+# qhasm: int64 a2
+
+# qhasm: int64 a3
+
+# qhasm: stack64 a0_stack
+
+# qhasm: stack64 a1_stack
+
+# qhasm: stack64 a2_stack
+
+# qhasm: stack64 a3_stack
+
+# qhasm: int64 b0
+
+# qhasm: int64 b1
+
+# qhasm: int64 b2
+
+# qhasm: int64 b3
+
+# qhasm: stack64 b0_stack
+
+# qhasm: stack64 b1_stack
+
+# qhasm: stack64 b2_stack
+
+# qhasm: stack64 b3_stack
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: stack64 c0_stack
+
+# qhasm: stack64 c1_stack
+
+# qhasm: stack64 c2_stack
+
+# qhasm: stack64 c3_stack
+
+# qhasm: int64 d0
+
+# qhasm: int64 d1
+
+# qhasm: int64 d2
+
+# qhasm: int64 d3
+
+# qhasm: stack64 d0_stack
+
+# qhasm: stack64 d1_stack
+
+# qhasm: stack64 d2_stack
+
+# qhasm: stack64 d3_stack
+
+# qhasm: int64 e0
+
+# qhasm: int64 e1
+
+# qhasm: int64 e2
+
+# qhasm: int64 e3
+
+# qhasm: stack64 e0_stack
+
+# qhasm: stack64 e1_stack
+
+# qhasm: stack64 e2_stack
+
+# qhasm: stack64 e3_stack
+
+# qhasm: int64 f0
+
+# qhasm: int64 f1
+
+# qhasm: int64 f2
+
+# qhasm: int64 f3
+
+# qhasm: stack64 f0_stack
+
+# qhasm: stack64 f1_stack
+
+# qhasm: stack64 f2_stack
+
+# qhasm: stack64 f3_stack
+
+# qhasm: int64 g0
+
+# qhasm: int64 g1
+
+# qhasm: int64 g2
+
+# qhasm: int64 g3
+
+# qhasm: stack64 g0_stack
+
+# qhasm: stack64 g1_stack
+
+# qhasm: stack64 g2_stack
+
+# qhasm: stack64 g3_stack
+
+# qhasm: int64 h0
+
+# qhasm: int64 h1
+
+# qhasm: int64 h2
+
+# qhasm: int64 h3
+
+# qhasm: stack64 h0_stack
+
+# qhasm: stack64 h1_stack
+
+# qhasm: stack64 h2_stack
+
+# qhasm: stack64 h3_stack
+
+# qhasm: int64 qt0
+
+# qhasm: int64 qt1
+
+# qhasm: int64 qt2
+
+# qhasm: int64 qt3
+
+# qhasm: stack64 qt0_stack
+
+# qhasm: stack64 qt1_stack
+
+# qhasm: stack64 qt2_stack
+
+# qhasm: stack64 qt3_stack
+
+# qhasm: int64 t10
+
+# qhasm: int64 t11
+
+# qhasm: int64 t12
+
+# qhasm: int64 t13
+
+# qhasm: stack64 t10_stack
+
+# qhasm: stack64 t11_stack
+
+# qhasm: stack64 t12_stack
+
+# qhasm: stack64 t13_stack
+
+# qhasm: int64 t20
+
+# qhasm: int64 t21
+
+# qhasm: int64 t22
+
+# qhasm: int64 t23
+
+# qhasm: stack64 t20_stack
+
+# qhasm: stack64 t21_stack
+
+# qhasm: stack64 t22_stack
+
+# qhasm: stack64 t23_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 rt0
+
+# qhasm: int64 rt1
+
+# qhasm: int64 rt2
+
+# qhasm: int64 rt3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: int64 addt0
+
+# qhasm: int64 addt1
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1
+.globl crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1
+_crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1:
+crypto_sign_ed25519_amd64_64_ge25519_nielsadd_p1p1:
+mov %rsp,%r11
+and $31,%r11
+add $128,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: qp = qp
+# asm 1: mov <qp=int64#3,>qp=int64#4
+# asm 2: mov <qp=%rdx,>qp=%rcx
+mov %rdx,%rcx
+
+# qhasm: a0 = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>a0=int64#3
+# asm 2: movq 32(<pp=%rsi),>a0=%rdx
+movq 32(%rsi),%rdx
+
+# qhasm: a1 = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>a1=int64#5
+# asm 2: movq 40(<pp=%rsi),>a1=%r8
+movq 40(%rsi),%r8
+
+# qhasm: a2 = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>a2=int64#6
+# asm 2: movq 48(<pp=%rsi),>a2=%r9
+movq 48(%rsi),%r9
+
+# qhasm: a3 = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>a3=int64#7
+# asm 2: movq 56(<pp=%rsi),>a3=%rax
+movq 56(%rsi),%rax
+
+# qhasm: b0 = a0
+# asm 1: mov <a0=int64#3,>b0=int64#8
+# asm 2: mov <a0=%rdx,>b0=%r10
+mov %rdx,%r10
+
+# qhasm: b1 = a1
+# asm 1: mov <a1=int64#5,>b1=int64#9
+# asm 2: mov <a1=%r8,>b1=%r11
+mov %r8,%r11
+
+# qhasm: b2 = a2
+# asm 1: mov <a2=int64#6,>b2=int64#10
+# asm 2: mov <a2=%r9,>b2=%r12
+mov %r9,%r12
+
+# qhasm: b3 = a3
+# asm 1: mov <a3=int64#7,>b3=int64#11
+# asm 2: mov <a3=%rax,>b3=%r13
+mov %rax,%r13
+
+# qhasm: carry? a0 -= *(uint64 *) (pp + 0)
+# asm 1: subq 0(<pp=int64#2),<a0=int64#3
+# asm 2: subq 0(<pp=%rsi),<a0=%rdx
+subq 0(%rsi),%rdx
+
+# qhasm: carry? a1 -= *(uint64 *) (pp + 8) - carry
+# asm 1: sbbq 8(<pp=int64#2),<a1=int64#5
+# asm 2: sbbq 8(<pp=%rsi),<a1=%r8
+sbbq 8(%rsi),%r8
+
+# qhasm: carry? a2 -= *(uint64 *) (pp + 16) - carry
+# asm 1: sbbq 16(<pp=int64#2),<a2=int64#6
+# asm 2: sbbq 16(<pp=%rsi),<a2=%r9
+sbbq 16(%rsi),%r9
+
+# qhasm: carry? a3 -= *(uint64 *) (pp + 24) - carry
+# asm 1: sbbq 24(<pp=int64#2),<a3=int64#7
+# asm 2: sbbq 24(<pp=%rsi),<a3=%rax
+sbbq 24(%rsi),%rax
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#12
+# asm 2: mov $0,>subt0=%r14
+mov $0,%r14
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#13
+# asm 2: mov $38,>subt1=%r15
+mov $38,%r15
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#12,<subt1=int64#13
+# asm 2: cmovae <subt0=%r14,<subt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? a0 -= subt1
+# asm 1: sub <subt1=int64#13,<a0=int64#3
+# asm 2: sub <subt1=%r15,<a0=%rdx
+sub %r15,%rdx
+
+# qhasm: carry? a1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a1=int64#5
+# asm 2: sbb <subt0=%r14,<a1=%r8
+sbb %r14,%r8
+
+# qhasm: carry? a2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a2=int64#6
+# asm 2: sbb <subt0=%r14,<a2=%r9
+sbb %r14,%r9
+
+# qhasm: carry? a3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a3=int64#7
+# asm 2: sbb <subt0=%r14,<a3=%rax
+sbb %r14,%rax
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#13,<subt0=int64#12
+# asm 2: cmovc <subt1=%r15,<subt0=%r14
+cmovc %r15,%r14
+
+# qhasm: a0 -= subt0
+# asm 1: sub <subt0=int64#12,<a0=int64#3
+# asm 2: sub <subt0=%r14,<a0=%rdx
+sub %r14,%rdx
+
+# qhasm: carry? b0 += *(uint64 *) (pp + 0)
+# asm 1: addq 0(<pp=int64#2),<b0=int64#8
+# asm 2: addq 0(<pp=%rsi),<b0=%r10
+addq 0(%rsi),%r10
+
+# qhasm: carry? b1 += *(uint64 *) (pp + 8) + carry
+# asm 1: adcq 8(<pp=int64#2),<b1=int64#9
+# asm 2: adcq 8(<pp=%rsi),<b1=%r11
+adcq 8(%rsi),%r11
+
+# qhasm: carry? b2 += *(uint64 *) (pp + 16) + carry
+# asm 1: adcq 16(<pp=int64#2),<b2=int64#10
+# asm 2: adcq 16(<pp=%rsi),<b2=%r12
+adcq 16(%rsi),%r12
+
+# qhasm: carry? b3 += *(uint64 *) (pp + 24) + carry
+# asm 1: adcq 24(<pp=int64#2),<b3=int64#11
+# asm 2: adcq 24(<pp=%rsi),<b3=%r13
+adcq 24(%rsi),%r13
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#12
+# asm 2: mov $0,>addt0=%r14
+mov $0,%r14
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#13
+# asm 2: mov $38,>addt1=%r15
+mov $38,%r15
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#12,<addt1=int64#13
+# asm 2: cmovae <addt0=%r14,<addt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? b0 += addt1
+# asm 1: add <addt1=int64#13,<b0=int64#8
+# asm 2: add <addt1=%r15,<b0=%r10
+add %r15,%r10
+
+# qhasm: carry? b1 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b1=int64#9
+# asm 2: adc <addt0=%r14,<b1=%r11
+adc %r14,%r11
+
+# qhasm: carry? b2 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b2=int64#10
+# asm 2: adc <addt0=%r14,<b2=%r12
+adc %r14,%r12
+
+# qhasm: carry? b3 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b3=int64#11
+# asm 2: adc <addt0=%r14,<b3=%r13
+adc %r14,%r13
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#13,<addt0=int64#12
+# asm 2: cmovc <addt1=%r15,<addt0=%r14
+cmovc %r15,%r14
+
+# qhasm: b0 += addt0
+# asm 1: add <addt0=int64#12,<b0=int64#8
+# asm 2: add <addt0=%r14,<b0=%r10
+add %r14,%r10
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#3,>a0_stack=stack64#8
+# asm 2: movq <a0=%rdx,>a0_stack=56(%rsp)
+movq %rdx,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#5,>a1_stack=stack64#9
+# asm 2: movq <a1=%r8,>a1_stack=64(%rsp)
+movq %r8,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#6,>a2_stack=stack64#10
+# asm 2: movq <a2=%r9,>a2_stack=72(%rsp)
+movq %r9,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#7,>a3_stack=stack64#11
+# asm 2: movq <a3=%rax,>a3_stack=80(%rsp)
+movq %rax,80(%rsp)
+
+# qhasm: b0_stack = b0
+# asm 1: movq <b0=int64#8,>b0_stack=stack64#12
+# asm 2: movq <b0=%r10,>b0_stack=88(%rsp)
+movq %r10,88(%rsp)
+
+# qhasm: b1_stack = b1
+# asm 1: movq <b1=int64#9,>b1_stack=stack64#13
+# asm 2: movq <b1=%r11,>b1_stack=96(%rsp)
+movq %r11,96(%rsp)
+
+# qhasm: b2_stack = b2
+# asm 1: movq <b2=int64#10,>b2_stack=stack64#14
+# asm 2: movq <b2=%r12,>b2_stack=104(%rsp)
+movq %r12,104(%rsp)
+
+# qhasm: b3_stack = b3
+# asm 1: movq <b3=int64#11,>b3_stack=stack64#15
+# asm 2: movq <b3=%r13,>b3_stack=112(%rsp)
+movq %r13,112(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = a0_stack
+# asm 1: movq <a0_stack=stack64#8,>mulx0=int64#10
+# asm 2: movq <a0_stack=56(%rsp),>mulx0=%r12
+movq 56(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: a0 = mulrax
+# asm 1: mov <mulrax=int64#7,>a0=int64#11
+# asm 2: mov <mulrax=%rax,>a0=%r13
+mov %rax,%r13
+
+# qhasm: a1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>a1=int64#12
+# asm 2: mov <mulrdx=%rdx,>a1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#12
+# asm 2: add <mulrax=%rax,<a1=%r14
+add %rax,%r14
+
+# qhasm: a2 = 0
+# asm 1: mov $0,>a2=int64#13
+# asm 2: mov $0,>a2=%r15
+mov $0,%r15
+
+# qhasm: a2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a2=int64#13
+# asm 2: adc <mulrdx=%rdx,<a2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: a3 = 0
+# asm 1: mov $0,>a3=int64#14
+# asm 2: mov $0,>a3=%rbx
+mov $0,%rbx
+
+# qhasm: a3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a3=int64#14
+# asm 2: adc <mulrdx=%rdx,<a3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = a1_stack
+# asm 1: movq <a1_stack=stack64#9,>mulx1=int64#10
+# asm 2: movq <a1_stack=64(%rsp),>mulx1=%r12
+movq 64(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#12
+# asm 2: add <mulrax=%rax,<a1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a2 += mulc
+# asm 1: add <mulc=int64#15,<a2=int64#13
+# asm 2: add <mulc=%rbp,<a2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#15,<a3=int64#14
+# asm 2: add <mulc=%rbp,<a3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = a2_stack
+# asm 1: movq <a2_stack=stack64#10,>mulx2=int64#10
+# asm 2: movq <a2_stack=72(%rsp),>mulx2=%r12
+movq 72(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#15,<a3=int64#14
+# asm 2: add <mulc=%rbp,<a3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = a3_stack
+# asm 1: movq <a3_stack=stack64#11,>mulx3=int64#10
+# asm 2: movq <a3_stack=80(%rsp),>mulx3=%r12
+movq 80(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? a0 += mulr4
+# asm 1: add <mulr4=int64#5,<a0=int64#11
+# asm 2: add <mulr4=%r8,<a0=%r13
+add %r8,%r13
+
+# qhasm: carry? a1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<a1=int64#12
+# asm 2: adc <mulr5=%r9,<a1=%r14
+adc %r9,%r14
+
+# qhasm: carry? a2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<a2=int64#13
+# asm 2: adc <mulr6=%r10,<a2=%r15
+adc %r10,%r15
+
+# qhasm: carry? a3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<a3=int64#14
+# asm 2: adc <mulr7=%r11,<a3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? a0 += mulr8
+# asm 1: add <mulr8=int64#5,<a0=int64#11
+# asm 2: add <mulr8=%r8,<a0=%r13
+add %r8,%r13
+
+# qhasm: carry? a1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a1=int64#12
+# asm 2: adc <mulzero=%rdx,<a1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? a2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a2=int64#13
+# asm 2: adc <mulzero=%rdx,<a2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? a3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a3=int64#14
+# asm 2: adc <mulzero=%rdx,<a3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: a0 += mulzero
+# asm 1: add <mulzero=int64#3,<a0=int64#11
+# asm 2: add <mulzero=%rdx,<a0=%r13
+add %rdx,%r13
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#11,>a0_stack=stack64#8
+# asm 2: movq <a0=%r13,>a0_stack=56(%rsp)
+movq %r13,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#12,>a1_stack=stack64#9
+# asm 2: movq <a1=%r14,>a1_stack=64(%rsp)
+movq %r14,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#13,>a2_stack=stack64#10
+# asm 2: movq <a2=%r15,>a2_stack=72(%rsp)
+movq %r15,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#14,>a3_stack=stack64#11
+# asm 2: movq <a3=%rbx,>a3_stack=80(%rsp)
+movq %rbx,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = b0_stack
+# asm 1: movq <b0_stack=stack64#12,>mulx0=int64#10
+# asm 2: movq <b0_stack=88(%rsp),>mulx0=%r12
+movq 88(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: e0 = mulrax
+# asm 1: mov <mulrax=int64#7,>e0=int64#11
+# asm 2: mov <mulrax=%rax,>e0=%r13
+mov %rax,%r13
+
+# qhasm: e1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>e1=int64#12
+# asm 2: mov <mulrdx=%rdx,>e1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? e1 += mulrax
+# asm 1: add <mulrax=int64#7,<e1=int64#12
+# asm 2: add <mulrax=%rax,<e1=%r14
+add %rax,%r14
+
+# qhasm: e2 = 0
+# asm 1: mov $0,>e2=int64#13
+# asm 2: mov $0,>e2=%r15
+mov $0,%r15
+
+# qhasm: e2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<e2=int64#13
+# asm 2: adc <mulrdx=%rdx,<e2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? e2 += mulrax
+# asm 1: add <mulrax=int64#7,<e2=int64#13
+# asm 2: add <mulrax=%rax,<e2=%r15
+add %rax,%r15
+
+# qhasm: e3 = 0
+# asm 1: mov $0,>e3=int64#14
+# asm 2: mov $0,>e3=%rbx
+mov $0,%rbx
+
+# qhasm: e3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<e3=int64#14
+# asm 2: adc <mulrdx=%rdx,<e3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#14
+# asm 2: add <mulrax=%rax,<e3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = b1_stack
+# asm 1: movq <b1_stack=stack64#13,>mulx1=int64#10
+# asm 2: movq <b1_stack=96(%rsp),>mulx1=%r12
+movq 96(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? e1 += mulrax
+# asm 1: add <mulrax=int64#7,<e1=int64#12
+# asm 2: add <mulrax=%rax,<e1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? e2 += mulrax
+# asm 1: add <mulrax=int64#7,<e2=int64#13
+# asm 2: add <mulrax=%rax,<e2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? e2 += mulc
+# asm 1: add <mulc=int64#15,<e2=int64#13
+# asm 2: add <mulc=%rbp,<e2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#14
+# asm 2: add <mulrax=%rax,<e3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? e3 += mulc
+# asm 1: add <mulc=int64#15,<e3=int64#14
+# asm 2: add <mulc=%rbp,<e3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = b2_stack
+# asm 1: movq <b2_stack=stack64#14,>mulx2=int64#10
+# asm 2: movq <b2_stack=104(%rsp),>mulx2=%r12
+movq 104(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? e2 += mulrax
+# asm 1: add <mulrax=int64#7,<e2=int64#13
+# asm 2: add <mulrax=%rax,<e2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#14
+# asm 2: add <mulrax=%rax,<e3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? e3 += mulc
+# asm 1: add <mulc=int64#15,<e3=int64#14
+# asm 2: add <mulc=%rbp,<e3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = b3_stack
+# asm 1: movq <b3_stack=stack64#15,>mulx3=int64#10
+# asm 2: movq <b3_stack=112(%rsp),>mulx3=%r12
+movq 112(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? e3 += mulrax
+# asm 1: add <mulrax=int64#7,<e3=int64#14
+# asm 2: add <mulrax=%rax,<e3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? e0 += mulr4
+# asm 1: add <mulr4=int64#5,<e0=int64#11
+# asm 2: add <mulr4=%r8,<e0=%r13
+add %r8,%r13
+
+# qhasm: carry? e1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<e1=int64#12
+# asm 2: adc <mulr5=%r9,<e1=%r14
+adc %r9,%r14
+
+# qhasm: carry? e2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<e2=int64#13
+# asm 2: adc <mulr6=%r10,<e2=%r15
+adc %r10,%r15
+
+# qhasm: carry? e3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<e3=int64#14
+# asm 2: adc <mulr7=%r11,<e3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? e0 += mulr8
+# asm 1: add <mulr8=int64#5,<e0=int64#11
+# asm 2: add <mulr8=%r8,<e0=%r13
+add %r8,%r13
+
+# qhasm: carry? e1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<e1=int64#12
+# asm 2: adc <mulzero=%rdx,<e1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? e2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<e2=int64#13
+# asm 2: adc <mulzero=%rdx,<e2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? e3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<e3=int64#14
+# asm 2: adc <mulzero=%rdx,<e3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: e0 += mulzero
+# asm 1: add <mulzero=int64#3,<e0=int64#11
+# asm 2: add <mulzero=%rdx,<e0=%r13
+add %rdx,%r13
+
+# qhasm: h0 = e0
+# asm 1: mov <e0=int64#11,>h0=int64#3
+# asm 2: mov <e0=%r13,>h0=%rdx
+mov %r13,%rdx
+
+# qhasm: h1 = e1
+# asm 1: mov <e1=int64#12,>h1=int64#5
+# asm 2: mov <e1=%r14,>h1=%r8
+mov %r14,%r8
+
+# qhasm: h2 = e2
+# asm 1: mov <e2=int64#13,>h2=int64#6
+# asm 2: mov <e2=%r15,>h2=%r9
+mov %r15,%r9
+
+# qhasm: h3 = e3
+# asm 1: mov <e3=int64#14,>h3=int64#7
+# asm 2: mov <e3=%rbx,>h3=%rax
+mov %rbx,%rax
+
+# qhasm: carry? e0 -= a0_stack
+# asm 1: subq <a0_stack=stack64#8,<e0=int64#11
+# asm 2: subq <a0_stack=56(%rsp),<e0=%r13
+subq 56(%rsp),%r13
+
+# qhasm: carry? e1 -= a1_stack - carry
+# asm 1: sbbq <a1_stack=stack64#9,<e1=int64#12
+# asm 2: sbbq <a1_stack=64(%rsp),<e1=%r14
+sbbq 64(%rsp),%r14
+
+# qhasm: carry? e2 -= a2_stack - carry
+# asm 1: sbbq <a2_stack=stack64#10,<e2=int64#13
+# asm 2: sbbq <a2_stack=72(%rsp),<e2=%r15
+sbbq 72(%rsp),%r15
+
+# qhasm: carry? e3 -= a3_stack - carry
+# asm 1: sbbq <a3_stack=stack64#11,<e3=int64#14
+# asm 2: sbbq <a3_stack=80(%rsp),<e3=%rbx
+sbbq 80(%rsp),%rbx
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#8
+# asm 2: mov $0,>subt0=%r10
+mov $0,%r10
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#9
+# asm 2: mov $38,>subt1=%r11
+mov $38,%r11
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#8,<subt1=int64#9
+# asm 2: cmovae <subt0=%r10,<subt1=%r11
+cmovae %r10,%r11
+
+# qhasm: carry? e0 -= subt1
+# asm 1: sub <subt1=int64#9,<e0=int64#11
+# asm 2: sub <subt1=%r11,<e0=%r13
+sub %r11,%r13
+
+# qhasm: carry? e1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<e1=int64#12
+# asm 2: sbb <subt0=%r10,<e1=%r14
+sbb %r10,%r14
+
+# qhasm: carry? e2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<e2=int64#13
+# asm 2: sbb <subt0=%r10,<e2=%r15
+sbb %r10,%r15
+
+# qhasm: carry? e3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<e3=int64#14
+# asm 2: sbb <subt0=%r10,<e3=%rbx
+sbb %r10,%rbx
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#9,<subt0=int64#8
+# asm 2: cmovc <subt1=%r11,<subt0=%r10
+cmovc %r11,%r10
+
+# qhasm: e0 -= subt0
+# asm 1: sub <subt0=int64#8,<e0=int64#11
+# asm 2: sub <subt0=%r10,<e0=%r13
+sub %r10,%r13
+
+# qhasm: carry? h0 += a0_stack
+# asm 1: addq <a0_stack=stack64#8,<h0=int64#3
+# asm 2: addq <a0_stack=56(%rsp),<h0=%rdx
+addq 56(%rsp),%rdx
+
+# qhasm: carry? h1 += a1_stack + carry
+# asm 1: adcq <a1_stack=stack64#9,<h1=int64#5
+# asm 2: adcq <a1_stack=64(%rsp),<h1=%r8
+adcq 64(%rsp),%r8
+
+# qhasm: carry? h2 += a2_stack + carry
+# asm 1: adcq <a2_stack=stack64#10,<h2=int64#6
+# asm 2: adcq <a2_stack=72(%rsp),<h2=%r9
+adcq 72(%rsp),%r9
+
+# qhasm: carry? h3 += a3_stack + carry
+# asm 1: adcq <a3_stack=stack64#11,<h3=int64#7
+# asm 2: adcq <a3_stack=80(%rsp),<h3=%rax
+adcq 80(%rsp),%rax
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#8
+# asm 2: mov $0,>addt0=%r10
+mov $0,%r10
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#9
+# asm 2: mov $38,>addt1=%r11
+mov $38,%r11
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#8,<addt1=int64#9
+# asm 2: cmovae <addt0=%r10,<addt1=%r11
+cmovae %r10,%r11
+
+# qhasm: carry? h0 += addt1
+# asm 1: add <addt1=int64#9,<h0=int64#3
+# asm 2: add <addt1=%r11,<h0=%rdx
+add %r11,%rdx
+
+# qhasm: carry? h1 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<h1=int64#5
+# asm 2: adc <addt0=%r10,<h1=%r8
+adc %r10,%r8
+
+# qhasm: carry? h2 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<h2=int64#6
+# asm 2: adc <addt0=%r10,<h2=%r9
+adc %r10,%r9
+
+# qhasm: carry? h3 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<h3=int64#7
+# asm 2: adc <addt0=%r10,<h3=%rax
+adc %r10,%rax
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#9,<addt0=int64#8
+# asm 2: cmovc <addt1=%r11,<addt0=%r10
+cmovc %r11,%r10
+
+# qhasm: h0 += addt0
+# asm 1: add <addt0=int64#8,<h0=int64#3
+# asm 2: add <addt0=%r10,<h0=%rdx
+add %r10,%rdx
+
+# qhasm: *(uint64 *)(rp + 64) = h0
+# asm 1: movq <h0=int64#3,64(<rp=int64#1)
+# asm 2: movq <h0=%rdx,64(<rp=%rdi)
+movq %rdx,64(%rdi)
+
+# qhasm: *(uint64 *)(rp + 72) = h1
+# asm 1: movq <h1=int64#5,72(<rp=int64#1)
+# asm 2: movq <h1=%r8,72(<rp=%rdi)
+movq %r8,72(%rdi)
+
+# qhasm: *(uint64 *)(rp + 80) = h2
+# asm 1: movq <h2=int64#6,80(<rp=int64#1)
+# asm 2: movq <h2=%r9,80(<rp=%rdi)
+movq %r9,80(%rdi)
+
+# qhasm: *(uint64 *)(rp + 88) = h3
+# asm 1: movq <h3=int64#7,88(<rp=int64#1)
+# asm 2: movq <h3=%rax,88(<rp=%rdi)
+movq %rax,88(%rdi)
+
+# qhasm: *(uint64 *)(rp + 0) = e0
+# asm 1: movq <e0=int64#11,0(<rp=int64#1)
+# asm 2: movq <e0=%r13,0(<rp=%rdi)
+movq %r13,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = e1
+# asm 1: movq <e1=int64#12,8(<rp=int64#1)
+# asm 2: movq <e1=%r14,8(<rp=%rdi)
+movq %r14,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = e2
+# asm 1: movq <e2=int64#13,16(<rp=int64#1)
+# asm 2: movq <e2=%r15,16(<rp=%rdi)
+movq %r15,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = e3
+# asm 1: movq <e3=int64#14,24(<rp=int64#1)
+# asm 2: movq <e3=%rbx,24(<rp=%rdi)
+movq %rbx,24(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulx0=int64#10
+# asm 2: movq 96(<pp=%rsi),>mulx0=%r12
+movq 96(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: c0 = mulrax
+# asm 1: mov <mulrax=int64#7,>c0=int64#11
+# asm 2: mov <mulrax=%rax,>c0=%r13
+mov %rax,%r13
+
+# qhasm: c1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>c1=int64#12
+# asm 2: mov <mulrdx=%rdx,>c1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: c2 = 0
+# asm 1: mov $0,>c2=int64#13
+# asm 2: mov $0,>c2=%r15
+mov $0,%r15
+
+# qhasm: c2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c2=int64#13
+# asm 2: adc <mulrdx=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: c3 = 0
+# asm 1: mov $0,>c3=int64#14
+# asm 2: mov $0,>c3=%rbx
+mov $0,%rbx
+
+# qhasm: c3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c3=int64#14
+# asm 2: adc <mulrdx=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulx1=int64#10
+# asm 2: movq 104(<pp=%rsi),>mulx1=%r12
+movq 104(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c2 += mulc
+# asm 1: add <mulc=int64#15,<c2=int64#13
+# asm 2: add <mulc=%rbp,<c2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulx2=int64#10
+# asm 2: movq 112(<pp=%rsi),>mulx2=%r12
+movq 112(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulx3=int64#10
+# asm 2: movq 120(<pp=%rsi),>mulx3=%r12
+movq 120(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? c0 += mulr4
+# asm 1: add <mulr4=int64#4,<c0=int64#11
+# asm 2: add <mulr4=%rcx,<c0=%r13
+add %rcx,%r13
+
+# qhasm: carry? c1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<c1=int64#12
+# asm 2: adc <mulr5=%r8,<c1=%r14
+adc %r8,%r14
+
+# qhasm: carry? c2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<c2=int64#13
+# asm 2: adc <mulr6=%r9,<c2=%r15
+adc %r9,%r15
+
+# qhasm: carry? c3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<c3=int64#14
+# asm 2: adc <mulr7=%r10,<c3=%rbx
+adc %r10,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? c0 += mulr8
+# asm 1: add <mulr8=int64#4,<c0=int64#11
+# asm 2: add <mulr8=%rcx,<c0=%r13
+add %rcx,%r13
+
+# qhasm: carry? c1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c1=int64#12
+# asm 2: adc <mulzero=%rdx,<c1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? c2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c2=int64#13
+# asm 2: adc <mulzero=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? c3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c3=int64#14
+# asm 2: adc <mulzero=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: c0 += mulzero
+# asm 1: add <mulzero=int64#3,<c0=int64#11
+# asm 2: add <mulzero=%rdx,<c0=%r13
+add %rdx,%r13
+
+# qhasm: f0 = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>f0=int64#3
+# asm 2: movq 64(<pp=%rsi),>f0=%rdx
+movq 64(%rsi),%rdx
+
+# qhasm: f1 = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>f1=int64#4
+# asm 2: movq 72(<pp=%rsi),>f1=%rcx
+movq 72(%rsi),%rcx
+
+# qhasm: f2 = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>f2=int64#5
+# asm 2: movq 80(<pp=%rsi),>f2=%r8
+movq 80(%rsi),%r8
+
+# qhasm: f3 = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>f3=int64#2
+# asm 2: movq 88(<pp=%rsi),>f3=%rsi
+movq 88(%rsi),%rsi
+
+# qhasm: carry? f0 += f0
+# asm 1: add <f0=int64#3,<f0=int64#3
+# asm 2: add <f0=%rdx,<f0=%rdx
+add %rdx,%rdx
+
+# qhasm: carry? f1 += f1 + carry
+# asm 1: adc <f1=int64#4,<f1=int64#4
+# asm 2: adc <f1=%rcx,<f1=%rcx
+adc %rcx,%rcx
+
+# qhasm: carry? f2 += f2 + carry
+# asm 1: adc <f2=int64#5,<f2=int64#5
+# asm 2: adc <f2=%r8,<f2=%r8
+adc %r8,%r8
+
+# qhasm: carry? f3 += f3 + carry
+# asm 1: adc <f3=int64#2,<f3=int64#2
+# asm 2: adc <f3=%rsi,<f3=%rsi
+adc %rsi,%rsi
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#6
+# asm 2: mov $0,>addt0=%r9
+mov $0,%r9
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#7
+# asm 2: mov $38,>addt1=%rax
+mov $38,%rax
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#6,<addt1=int64#7
+# asm 2: cmovae <addt0=%r9,<addt1=%rax
+cmovae %r9,%rax
+
+# qhasm: carry? f0 += addt1
+# asm 1: add <addt1=int64#7,<f0=int64#3
+# asm 2: add <addt1=%rax,<f0=%rdx
+add %rax,%rdx
+
+# qhasm: carry? f1 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<f1=int64#4
+# asm 2: adc <addt0=%r9,<f1=%rcx
+adc %r9,%rcx
+
+# qhasm: carry? f2 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<f2=int64#5
+# asm 2: adc <addt0=%r9,<f2=%r8
+adc %r9,%r8
+
+# qhasm: carry? f3 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<f3=int64#2
+# asm 2: adc <addt0=%r9,<f3=%rsi
+adc %r9,%rsi
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#7,<addt0=int64#6
+# asm 2: cmovc <addt1=%rax,<addt0=%r9
+cmovc %rax,%r9
+
+# qhasm: f0 += addt0
+# asm 1: add <addt0=int64#6,<f0=int64#3
+# asm 2: add <addt0=%r9,<f0=%rdx
+add %r9,%rdx
+
+# qhasm: g0 = f0
+# asm 1: mov <f0=int64#3,>g0=int64#6
+# asm 2: mov <f0=%rdx,>g0=%r9
+mov %rdx,%r9
+
+# qhasm: g1 = f1
+# asm 1: mov <f1=int64#4,>g1=int64#7
+# asm 2: mov <f1=%rcx,>g1=%rax
+mov %rcx,%rax
+
+# qhasm: g2 = f2
+# asm 1: mov <f2=int64#5,>g2=int64#8
+# asm 2: mov <f2=%r8,>g2=%r10
+mov %r8,%r10
+
+# qhasm: g3 = f3
+# asm 1: mov <f3=int64#2,>g3=int64#9
+# asm 2: mov <f3=%rsi,>g3=%r11
+mov %rsi,%r11
+
+# qhasm: carry? f0 -= c0
+# asm 1: sub <c0=int64#11,<f0=int64#3
+# asm 2: sub <c0=%r13,<f0=%rdx
+sub %r13,%rdx
+
+# qhasm: carry? f1 -= c1 - carry
+# asm 1: sbb <c1=int64#12,<f1=int64#4
+# asm 2: sbb <c1=%r14,<f1=%rcx
+sbb %r14,%rcx
+
+# qhasm: carry? f2 -= c2 - carry
+# asm 1: sbb <c2=int64#13,<f2=int64#5
+# asm 2: sbb <c2=%r15,<f2=%r8
+sbb %r15,%r8
+
+# qhasm: carry? f3 -= c3 - carry
+# asm 1: sbb <c3=int64#14,<f3=int64#2
+# asm 2: sbb <c3=%rbx,<f3=%rsi
+sbb %rbx,%rsi
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#10
+# asm 2: mov $0,>subt0=%r12
+mov $0,%r12
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#15
+# asm 2: mov $38,>subt1=%rbp
+mov $38,%rbp
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#10,<subt1=int64#15
+# asm 2: cmovae <subt0=%r12,<subt1=%rbp
+cmovae %r12,%rbp
+
+# qhasm: carry? f0 -= subt1
+# asm 1: sub <subt1=int64#15,<f0=int64#3
+# asm 2: sub <subt1=%rbp,<f0=%rdx
+sub %rbp,%rdx
+
+# qhasm: carry? f1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#10,<f1=int64#4
+# asm 2: sbb <subt0=%r12,<f1=%rcx
+sbb %r12,%rcx
+
+# qhasm: carry? f2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#10,<f2=int64#5
+# asm 2: sbb <subt0=%r12,<f2=%r8
+sbb %r12,%r8
+
+# qhasm: carry? f3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#10,<f3=int64#2
+# asm 2: sbb <subt0=%r12,<f3=%rsi
+sbb %r12,%rsi
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#15,<subt0=int64#10
+# asm 2: cmovc <subt1=%rbp,<subt0=%r12
+cmovc %rbp,%r12
+
+# qhasm: f0 -= subt0
+# asm 1: sub <subt0=int64#10,<f0=int64#3
+# asm 2: sub <subt0=%r12,<f0=%rdx
+sub %r12,%rdx
+
+# qhasm: carry? g0 += c0
+# asm 1: add <c0=int64#11,<g0=int64#6
+# asm 2: add <c0=%r13,<g0=%r9
+add %r13,%r9
+
+# qhasm: carry? g1 += c1 + carry
+# asm 1: adc <c1=int64#12,<g1=int64#7
+# asm 2: adc <c1=%r14,<g1=%rax
+adc %r14,%rax
+
+# qhasm: carry? g2 += c2 + carry
+# asm 1: adc <c2=int64#13,<g2=int64#8
+# asm 2: adc <c2=%r15,<g2=%r10
+adc %r15,%r10
+
+# qhasm: carry? g3 += c3 + carry
+# asm 1: adc <c3=int64#14,<g3=int64#9
+# asm 2: adc <c3=%rbx,<g3=%r11
+adc %rbx,%r11
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#10
+# asm 2: mov $0,>addt0=%r12
+mov $0,%r12
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#11
+# asm 2: mov $38,>addt1=%r13
+mov $38,%r13
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#10,<addt1=int64#11
+# asm 2: cmovae <addt0=%r12,<addt1=%r13
+cmovae %r12,%r13
+
+# qhasm: carry? g0 += addt1
+# asm 1: add <addt1=int64#11,<g0=int64#6
+# asm 2: add <addt1=%r13,<g0=%r9
+add %r13,%r9
+
+# qhasm: carry? g1 += addt0 + carry
+# asm 1: adc <addt0=int64#10,<g1=int64#7
+# asm 2: adc <addt0=%r12,<g1=%rax
+adc %r12,%rax
+
+# qhasm: carry? g2 += addt0 + carry
+# asm 1: adc <addt0=int64#10,<g2=int64#8
+# asm 2: adc <addt0=%r12,<g2=%r10
+adc %r12,%r10
+
+# qhasm: carry? g3 += addt0 + carry
+# asm 1: adc <addt0=int64#10,<g3=int64#9
+# asm 2: adc <addt0=%r12,<g3=%r11
+adc %r12,%r11
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#11,<addt0=int64#10
+# asm 2: cmovc <addt1=%r13,<addt0=%r12
+cmovc %r13,%r12
+
+# qhasm: g0 += addt0
+# asm 1: add <addt0=int64#10,<g0=int64#6
+# asm 2: add <addt0=%r12,<g0=%r9
+add %r12,%r9
+
+# qhasm: *(uint64 *)(rp + 32) = g0
+# asm 1: movq <g0=int64#6,32(<rp=int64#1)
+# asm 2: movq <g0=%r9,32(<rp=%rdi)
+movq %r9,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = g1
+# asm 1: movq <g1=int64#7,40(<rp=int64#1)
+# asm 2: movq <g1=%rax,40(<rp=%rdi)
+movq %rax,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = g2
+# asm 1: movq <g2=int64#8,48(<rp=int64#1)
+# asm 2: movq <g2=%r10,48(<rp=%rdi)
+movq %r10,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = g3
+# asm 1: movq <g3=int64#9,56(<rp=int64#1)
+# asm 2: movq <g3=%r11,56(<rp=%rdi)
+movq %r11,56(%rdi)
+
+# qhasm: *(uint64 *)(rp + 96) = f0
+# asm 1: movq <f0=int64#3,96(<rp=int64#1)
+# asm 2: movq <f0=%rdx,96(<rp=%rdi)
+movq %rdx,96(%rdi)
+
+# qhasm: *(uint64 *)(rp + 104) = f1
+# asm 1: movq <f1=int64#4,104(<rp=int64#1)
+# asm 2: movq <f1=%rcx,104(<rp=%rdi)
+movq %rcx,104(%rdi)
+
+# qhasm: *(uint64 *)(rp + 112) = f2
+# asm 1: movq <f2=int64#5,112(<rp=int64#1)
+# asm 2: movq <f2=%r8,112(<rp=%rdi)
+movq %r8,112(%rdi)
+
+# qhasm: *(uint64 *)(rp + 120) = f3
+# asm 1: movq <f3=int64#2,120(<rp=int64#1)
+# asm 2: movq <f3=%rsi,120(<rp=%rdi)
+movq %rsi,120(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s b/ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s
new file mode 100644
index 00000000..beddbc79
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_p1p1_to_p2.s
@@ -0,0 +1,2236 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 pp
+
+# qhasm: input rp
+
+# qhasm: input pp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2
+.globl crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2
+_crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2:
+crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p2:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 0)
+# asm 1: movq 0(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 0(<pp=%rsi),>mulx0=%r11
+movq 0(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: rx0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rx0=int64#10
+# asm 2: mov <mulrax=%rax,>rx0=%r12
+mov %rax,%r12
+
+# qhasm: rx1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rx1=int64#11
+# asm 2: mov <mulrdx=%rdx,>rx1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#11
+# asm 2: add <mulrax=%rax,<rx1=%r13
+add %rax,%r13
+
+# qhasm: rx2 = 0
+# asm 1: mov $0,>rx2=int64#12
+# asm 2: mov $0,>rx2=%r14
+mov $0,%r14
+
+# qhasm: rx2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx2=int64#12
+# asm 2: adc <mulrdx=%rdx,<rx2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#12
+# asm 2: add <mulrax=%rax,<rx2=%r14
+add %rax,%r14
+
+# qhasm: rx3 = 0
+# asm 1: mov $0,>rx3=int64#13
+# asm 2: mov $0,>rx3=%r15
+mov $0,%r15
+
+# qhasm: rx3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx3=int64#13
+# asm 2: adc <mulrdx=%rdx,<rx3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 8)
+# asm 1: movq 8(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 8(<pp=%rsi),>mulx1=%r11
+movq 8(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#11
+# asm 2: add <mulrax=%rax,<rx1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#12
+# asm 2: add <mulrax=%rax,<rx2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx2 += mulc
+# asm 1: add <mulc=int64#14,<rx2=int64#12
+# asm 2: add <mulc=%rbx,<rx2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#14,<rx3=int64#13
+# asm 2: add <mulc=%rbx,<rx3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 16(<pp=%rsi),>mulx2=%r11
+movq 16(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#12
+# asm 2: add <mulrax=%rax,<rx2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#14,<rx3=int64#13
+# asm 2: add <mulc=%rbx,<rx3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 24(<pp=%rsi),>mulx3=%r11
+movq 24(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rx0 += mulr4
+# asm 1: add <mulr4=int64#4,<rx0=int64#10
+# asm 2: add <mulr4=%rcx,<rx0=%r12
+add %rcx,%r12
+
+# qhasm: carry? rx1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<rx1=int64#11
+# asm 2: adc <mulr5=%r8,<rx1=%r13
+adc %r8,%r13
+
+# qhasm: carry? rx2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<rx2=int64#12
+# asm 2: adc <mulr6=%r9,<rx2=%r14
+adc %r9,%r14
+
+# qhasm: carry? rx3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<rx3=int64#13
+# asm 2: adc <mulr7=%r10,<rx3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? rx0 += mulr8
+# asm 1: add <mulr8=int64#4,<rx0=int64#10
+# asm 2: add <mulr8=%rcx,<rx0=%r12
+add %rcx,%r12
+
+# qhasm: carry? rx1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx1=int64#11
+# asm 2: adc <mulzero=%rdx,<rx1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? rx2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx2=int64#12
+# asm 2: adc <mulzero=%rdx,<rx2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? rx3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx3=int64#13
+# asm 2: adc <mulzero=%rdx,<rx3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: rx0 += mulzero
+# asm 1: add <mulzero=int64#3,<rx0=int64#10
+# asm 2: add <mulzero=%rdx,<rx0=%r12
+add %rdx,%r12
+
+# qhasm: *(uint64 *)(rp + 0) = rx0
+# asm 1: movq <rx0=int64#10,0(<rp=int64#1)
+# asm 2: movq <rx0=%r12,0(<rp=%rdi)
+movq %r12,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = rx1
+# asm 1: movq <rx1=int64#11,8(<rp=int64#1)
+# asm 2: movq <rx1=%r13,8(<rp=%rdi)
+movq %r13,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = rx2
+# asm 1: movq <rx2=int64#12,16(<rp=int64#1)
+# asm 2: movq <rx2=%r14,16(<rp=%rdi)
+movq %r14,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = rx3
+# asm 1: movq <rx3=int64#13,24(<rp=int64#1)
+# asm 2: movq <rx3=%r15,24(<rp=%rdi)
+movq %r15,24(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 64(<pp=%rsi),>mulx0=%r11
+movq 64(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: ry0 = mulrax
+# asm 1: mov <mulrax=int64#7,>ry0=int64#10
+# asm 2: mov <mulrax=%rax,>ry0=%r12
+mov %rax,%r12
+
+# qhasm: ry1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>ry1=int64#11
+# asm 2: mov <mulrdx=%rdx,>ry1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? ry1 += mulrax
+# asm 1: add <mulrax=int64#7,<ry1=int64#11
+# asm 2: add <mulrax=%rax,<ry1=%r13
+add %rax,%r13
+
+# qhasm: ry2 = 0
+# asm 1: mov $0,>ry2=int64#12
+# asm 2: mov $0,>ry2=%r14
+mov $0,%r14
+
+# qhasm: ry2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<ry2=int64#12
+# asm 2: adc <mulrdx=%rdx,<ry2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#12
+# asm 2: add <mulrax=%rax,<ry2=%r14
+add %rax,%r14
+
+# qhasm: ry3 = 0
+# asm 1: mov $0,>ry3=int64#13
+# asm 2: mov $0,>ry3=%r15
+mov $0,%r15
+
+# qhasm: ry3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<ry3=int64#13
+# asm 2: adc <mulrdx=%rdx,<ry3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 72(<pp=%rsi),>mulx1=%r11
+movq 72(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? ry1 += mulrax
+# asm 1: add <mulrax=int64#7,<ry1=int64#11
+# asm 2: add <mulrax=%rax,<ry1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#12
+# asm 2: add <mulrax=%rax,<ry2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry2 += mulc
+# asm 1: add <mulc=int64#14,<ry2=int64#12
+# asm 2: add <mulc=%rbx,<ry2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry3 += mulc
+# asm 1: add <mulc=int64#14,<ry3=int64#13
+# asm 2: add <mulc=%rbx,<ry3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 80(<pp=%rsi),>mulx2=%r11
+movq 80(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#12
+# asm 2: add <mulrax=%rax,<ry2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry3 += mulc
+# asm 1: add <mulc=int64#14,<ry3=int64#13
+# asm 2: add <mulc=%rbx,<ry3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 88(<pp=%rsi),>mulx3=%r11
+movq 88(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? ry0 += mulr4
+# asm 1: add <mulr4=int64#4,<ry0=int64#10
+# asm 2: add <mulr4=%rcx,<ry0=%r12
+add %rcx,%r12
+
+# qhasm: carry? ry1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<ry1=int64#11
+# asm 2: adc <mulr5=%r8,<ry1=%r13
+adc %r8,%r13
+
+# qhasm: carry? ry2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<ry2=int64#12
+# asm 2: adc <mulr6=%r9,<ry2=%r14
+adc %r9,%r14
+
+# qhasm: carry? ry3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<ry3=int64#13
+# asm 2: adc <mulr7=%r10,<ry3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? ry0 += mulr8
+# asm 1: add <mulr8=int64#4,<ry0=int64#10
+# asm 2: add <mulr8=%rcx,<ry0=%r12
+add %rcx,%r12
+
+# qhasm: carry? ry1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<ry1=int64#11
+# asm 2: adc <mulzero=%rdx,<ry1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? ry2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<ry2=int64#12
+# asm 2: adc <mulzero=%rdx,<ry2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? ry3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<ry3=int64#13
+# asm 2: adc <mulzero=%rdx,<ry3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: ry0 += mulzero
+# asm 1: add <mulzero=int64#3,<ry0=int64#10
+# asm 2: add <mulzero=%rdx,<ry0=%r12
+add %rdx,%r12
+
+# qhasm: *(uint64 *)(rp + 32) = ry0
+# asm 1: movq <ry0=int64#10,32(<rp=int64#1)
+# asm 2: movq <ry0=%r12,32(<rp=%rdi)
+movq %r12,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = ry1
+# asm 1: movq <ry1=int64#11,40(<rp=int64#1)
+# asm 2: movq <ry1=%r13,40(<rp=%rdi)
+movq %r13,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = ry2
+# asm 1: movq <ry2=int64#12,48(<rp=int64#1)
+# asm 2: movq <ry2=%r14,48(<rp=%rdi)
+movq %r14,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = ry3
+# asm 1: movq <ry3=int64#13,56(<rp=int64#1)
+# asm 2: movq <ry3=%r15,56(<rp=%rdi)
+movq %r15,56(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 32(<pp=%rsi),>mulx0=%r11
+movq 32(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: rz0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rz0=int64#10
+# asm 2: mov <mulrax=%rax,>rz0=%r12
+mov %rax,%r12
+
+# qhasm: rz1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rz1=int64#11
+# asm 2: mov <mulrdx=%rdx,>rz1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rz1 += mulrax
+# asm 1: add <mulrax=int64#7,<rz1=int64#11
+# asm 2: add <mulrax=%rax,<rz1=%r13
+add %rax,%r13
+
+# qhasm: rz2 = 0
+# asm 1: mov $0,>rz2=int64#12
+# asm 2: mov $0,>rz2=%r14
+mov $0,%r14
+
+# qhasm: rz2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rz2=int64#12
+# asm 2: adc <mulrdx=%rdx,<rz2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#12
+# asm 2: add <mulrax=%rax,<rz2=%r14
+add %rax,%r14
+
+# qhasm: rz3 = 0
+# asm 1: mov $0,>rz3=int64#13
+# asm 2: mov $0,>rz3=%r15
+mov $0,%r15
+
+# qhasm: rz3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rz3=int64#13
+# asm 2: adc <mulrdx=%rdx,<rz3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 40(<pp=%rsi),>mulx1=%r11
+movq 40(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rz1 += mulrax
+# asm 1: add <mulrax=int64#7,<rz1=int64#11
+# asm 2: add <mulrax=%rax,<rz1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#12
+# asm 2: add <mulrax=%rax,<rz2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz2 += mulc
+# asm 1: add <mulc=int64#14,<rz2=int64#12
+# asm 2: add <mulc=%rbx,<rz2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz3 += mulc
+# asm 1: add <mulc=int64#14,<rz3=int64#13
+# asm 2: add <mulc=%rbx,<rz3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 48(<pp=%rsi),>mulx2=%r11
+movq 48(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#12
+# asm 2: add <mulrax=%rax,<rz2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz3 += mulc
+# asm 1: add <mulc=int64#14,<rz3=int64#13
+# asm 2: add <mulc=%rbx,<rz3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 56(<pp=%rsi),>mulx3=%r11
+movq 56(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rz0 += mulr4
+# asm 1: add <mulr4=int64#2,<rz0=int64#10
+# asm 2: add <mulr4=%rsi,<rz0=%r12
+add %rsi,%r12
+
+# qhasm: carry? rz1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rz1=int64#11
+# asm 2: adc <mulr5=%rcx,<rz1=%r13
+adc %rcx,%r13
+
+# qhasm: carry? rz2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rz2=int64#12
+# asm 2: adc <mulr6=%r8,<rz2=%r14
+adc %r8,%r14
+
+# qhasm: carry? rz3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rz3=int64#13
+# asm 2: adc <mulr7=%r9,<rz3=%r15
+adc %r9,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rz0 += mulr8
+# asm 1: add <mulr8=int64#3,<rz0=int64#10
+# asm 2: add <mulr8=%rdx,<rz0=%r12
+add %rdx,%r12
+
+# qhasm: carry? rz1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rz1=int64#11
+# asm 2: adc <mulzero=%rsi,<rz1=%r13
+adc %rsi,%r13
+
+# qhasm: carry? rz2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rz2=int64#12
+# asm 2: adc <mulzero=%rsi,<rz2=%r14
+adc %rsi,%r14
+
+# qhasm: carry? rz3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rz3=int64#13
+# asm 2: adc <mulzero=%rsi,<rz3=%r15
+adc %rsi,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rz0 += mulzero
+# asm 1: add <mulzero=int64#2,<rz0=int64#10
+# asm 2: add <mulzero=%rsi,<rz0=%r12
+add %rsi,%r12
+
+# qhasm: *(uint64 *)(rp + 64) = rz0
+# asm 1: movq <rz0=int64#10,64(<rp=int64#1)
+# asm 2: movq <rz0=%r12,64(<rp=%rdi)
+movq %r12,64(%rdi)
+
+# qhasm: *(uint64 *)(rp + 72) = rz1
+# asm 1: movq <rz1=int64#11,72(<rp=int64#1)
+# asm 2: movq <rz1=%r13,72(<rp=%rdi)
+movq %r13,72(%rdi)
+
+# qhasm: *(uint64 *)(rp + 80) = rz2
+# asm 1: movq <rz2=int64#12,80(<rp=int64#1)
+# asm 2: movq <rz2=%r14,80(<rp=%rdi)
+movq %r14,80(%rdi)
+
+# qhasm: *(uint64 *)(rp + 88) = rz3
+# asm 1: movq <rz3=int64#13,88(<rp=int64#1)
+# asm 2: movq <rz3=%r15,88(<rp=%rdi)
+movq %r15,88(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s b/ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s
new file mode 100644
index 00000000..82433fba
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_p1p1_to_p3.s
@@ -0,0 +1,2926 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 pp
+
+# qhasm: input rp
+
+# qhasm: input pp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 rt0
+
+# qhasm: int64 rt1
+
+# qhasm: int64 rt2
+
+# qhasm: int64 rt3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3
+.globl crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3
+_crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3:
+crypto_sign_ed25519_amd64_64_ge25519_p1p1_to_p3:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 0)
+# asm 1: movq 0(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 0(<pp=%rsi),>mulx0=%r11
+movq 0(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: rx0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rx0=int64#10
+# asm 2: mov <mulrax=%rax,>rx0=%r12
+mov %rax,%r12
+
+# qhasm: rx1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rx1=int64#11
+# asm 2: mov <mulrdx=%rdx,>rx1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#11
+# asm 2: add <mulrax=%rax,<rx1=%r13
+add %rax,%r13
+
+# qhasm: rx2 = 0
+# asm 1: mov $0,>rx2=int64#12
+# asm 2: mov $0,>rx2=%r14
+mov $0,%r14
+
+# qhasm: rx2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx2=int64#12
+# asm 2: adc <mulrdx=%rdx,<rx2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#12
+# asm 2: add <mulrax=%rax,<rx2=%r14
+add %rax,%r14
+
+# qhasm: rx3 = 0
+# asm 1: mov $0,>rx3=int64#13
+# asm 2: mov $0,>rx3=%r15
+mov $0,%r15
+
+# qhasm: rx3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx3=int64#13
+# asm 2: adc <mulrdx=%rdx,<rx3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 8)
+# asm 1: movq 8(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 8(<pp=%rsi),>mulx1=%r11
+movq 8(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#11
+# asm 2: add <mulrax=%rax,<rx1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#12
+# asm 2: add <mulrax=%rax,<rx2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx2 += mulc
+# asm 1: add <mulc=int64#14,<rx2=int64#12
+# asm 2: add <mulc=%rbx,<rx2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#14,<rx3=int64#13
+# asm 2: add <mulc=%rbx,<rx3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 16(<pp=%rsi),>mulx2=%r11
+movq 16(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#12
+# asm 2: add <mulrax=%rax,<rx2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#14,<rx3=int64#13
+# asm 2: add <mulc=%rbx,<rx3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 24(<pp=%rsi),>mulx3=%r11
+movq 24(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#13
+# asm 2: add <mulrax=%rax,<rx3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rx0 += mulr4
+# asm 1: add <mulr4=int64#4,<rx0=int64#10
+# asm 2: add <mulr4=%rcx,<rx0=%r12
+add %rcx,%r12
+
+# qhasm: carry? rx1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<rx1=int64#11
+# asm 2: adc <mulr5=%r8,<rx1=%r13
+adc %r8,%r13
+
+# qhasm: carry? rx2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<rx2=int64#12
+# asm 2: adc <mulr6=%r9,<rx2=%r14
+adc %r9,%r14
+
+# qhasm: carry? rx3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<rx3=int64#13
+# asm 2: adc <mulr7=%r10,<rx3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? rx0 += mulr8
+# asm 1: add <mulr8=int64#4,<rx0=int64#10
+# asm 2: add <mulr8=%rcx,<rx0=%r12
+add %rcx,%r12
+
+# qhasm: carry? rx1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx1=int64#11
+# asm 2: adc <mulzero=%rdx,<rx1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? rx2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx2=int64#12
+# asm 2: adc <mulzero=%rdx,<rx2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? rx3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx3=int64#13
+# asm 2: adc <mulzero=%rdx,<rx3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: rx0 += mulzero
+# asm 1: add <mulzero=int64#3,<rx0=int64#10
+# asm 2: add <mulzero=%rdx,<rx0=%r12
+add %rdx,%r12
+
+# qhasm: *(uint64 *)(rp + 0) = rx0
+# asm 1: movq <rx0=int64#10,0(<rp=int64#1)
+# asm 2: movq <rx0=%r12,0(<rp=%rdi)
+movq %r12,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = rx1
+# asm 1: movq <rx1=int64#11,8(<rp=int64#1)
+# asm 2: movq <rx1=%r13,8(<rp=%rdi)
+movq %r13,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = rx2
+# asm 1: movq <rx2=int64#12,16(<rp=int64#1)
+# asm 2: movq <rx2=%r14,16(<rp=%rdi)
+movq %r14,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = rx3
+# asm 1: movq <rx3=int64#13,24(<rp=int64#1)
+# asm 2: movq <rx3=%r15,24(<rp=%rdi)
+movq %r15,24(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 64(<pp=%rsi),>mulx0=%r11
+movq 64(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: ry0 = mulrax
+# asm 1: mov <mulrax=int64#7,>ry0=int64#10
+# asm 2: mov <mulrax=%rax,>ry0=%r12
+mov %rax,%r12
+
+# qhasm: ry1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>ry1=int64#11
+# asm 2: mov <mulrdx=%rdx,>ry1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? ry1 += mulrax
+# asm 1: add <mulrax=int64#7,<ry1=int64#11
+# asm 2: add <mulrax=%rax,<ry1=%r13
+add %rax,%r13
+
+# qhasm: ry2 = 0
+# asm 1: mov $0,>ry2=int64#12
+# asm 2: mov $0,>ry2=%r14
+mov $0,%r14
+
+# qhasm: ry2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<ry2=int64#12
+# asm 2: adc <mulrdx=%rdx,<ry2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#12
+# asm 2: add <mulrax=%rax,<ry2=%r14
+add %rax,%r14
+
+# qhasm: ry3 = 0
+# asm 1: mov $0,>ry3=int64#13
+# asm 2: mov $0,>ry3=%r15
+mov $0,%r15
+
+# qhasm: ry3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<ry3=int64#13
+# asm 2: adc <mulrdx=%rdx,<ry3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 72(<pp=%rsi),>mulx1=%r11
+movq 72(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? ry1 += mulrax
+# asm 1: add <mulrax=int64#7,<ry1=int64#11
+# asm 2: add <mulrax=%rax,<ry1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#12
+# asm 2: add <mulrax=%rax,<ry2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry2 += mulc
+# asm 1: add <mulc=int64#14,<ry2=int64#12
+# asm 2: add <mulc=%rbx,<ry2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry3 += mulc
+# asm 1: add <mulc=int64#14,<ry3=int64#13
+# asm 2: add <mulc=%rbx,<ry3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 80(<pp=%rsi),>mulx2=%r11
+movq 80(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? ry2 += mulrax
+# asm 1: add <mulrax=int64#7,<ry2=int64#12
+# asm 2: add <mulrax=%rax,<ry2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? ry3 += mulc
+# asm 1: add <mulc=int64#14,<ry3=int64#13
+# asm 2: add <mulc=%rbx,<ry3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 88(<pp=%rsi),>mulx3=%r11
+movq 88(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 32(<pp=%rsi),>mulrax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? ry3 += mulrax
+# asm 1: add <mulrax=int64#7,<ry3=int64#13
+# asm 2: add <mulrax=%rax,<ry3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 40(<pp=%rsi),>mulrax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 48(<pp=%rsi),>mulrax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 56(<pp=%rsi),>mulrax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? ry0 += mulr4
+# asm 1: add <mulr4=int64#4,<ry0=int64#10
+# asm 2: add <mulr4=%rcx,<ry0=%r12
+add %rcx,%r12
+
+# qhasm: carry? ry1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<ry1=int64#11
+# asm 2: adc <mulr5=%r8,<ry1=%r13
+adc %r8,%r13
+
+# qhasm: carry? ry2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<ry2=int64#12
+# asm 2: adc <mulr6=%r9,<ry2=%r14
+adc %r9,%r14
+
+# qhasm: carry? ry3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<ry3=int64#13
+# asm 2: adc <mulr7=%r10,<ry3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? ry0 += mulr8
+# asm 1: add <mulr8=int64#4,<ry0=int64#10
+# asm 2: add <mulr8=%rcx,<ry0=%r12
+add %rcx,%r12
+
+# qhasm: carry? ry1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<ry1=int64#11
+# asm 2: adc <mulzero=%rdx,<ry1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? ry2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<ry2=int64#12
+# asm 2: adc <mulzero=%rdx,<ry2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? ry3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<ry3=int64#13
+# asm 2: adc <mulzero=%rdx,<ry3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: ry0 += mulzero
+# asm 1: add <mulzero=int64#3,<ry0=int64#10
+# asm 2: add <mulzero=%rdx,<ry0=%r12
+add %rdx,%r12
+
+# qhasm: *(uint64 *)(rp + 32) = ry0
+# asm 1: movq <ry0=int64#10,32(<rp=int64#1)
+# asm 2: movq <ry0=%r12,32(<rp=%rdi)
+movq %r12,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = ry1
+# asm 1: movq <ry1=int64#11,40(<rp=int64#1)
+# asm 2: movq <ry1=%r13,40(<rp=%rdi)
+movq %r13,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = ry2
+# asm 1: movq <ry2=int64#12,48(<rp=int64#1)
+# asm 2: movq <ry2=%r14,48(<rp=%rdi)
+movq %r14,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = ry3
+# asm 1: movq <ry3=int64#13,56(<rp=int64#1)
+# asm 2: movq <ry3=%r15,56(<rp=%rdi)
+movq %r15,56(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 32(<pp=%rsi),>mulx0=%r11
+movq 32(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: rz0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rz0=int64#10
+# asm 2: mov <mulrax=%rax,>rz0=%r12
+mov %rax,%r12
+
+# qhasm: rz1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rz1=int64#11
+# asm 2: mov <mulrdx=%rdx,>rz1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rz1 += mulrax
+# asm 1: add <mulrax=int64#7,<rz1=int64#11
+# asm 2: add <mulrax=%rax,<rz1=%r13
+add %rax,%r13
+
+# qhasm: rz2 = 0
+# asm 1: mov $0,>rz2=int64#12
+# asm 2: mov $0,>rz2=%r14
+mov $0,%r14
+
+# qhasm: rz2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rz2=int64#12
+# asm 2: adc <mulrdx=%rdx,<rz2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#12
+# asm 2: add <mulrax=%rax,<rz2=%r14
+add %rax,%r14
+
+# qhasm: rz3 = 0
+# asm 1: mov $0,>rz3=int64#13
+# asm 2: mov $0,>rz3=%r15
+mov $0,%r15
+
+# qhasm: rz3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rz3=int64#13
+# asm 2: adc <mulrdx=%rdx,<rz3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 40(<pp=%rsi),>mulx1=%r11
+movq 40(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rz1 += mulrax
+# asm 1: add <mulrax=int64#7,<rz1=int64#11
+# asm 2: add <mulrax=%rax,<rz1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#12
+# asm 2: add <mulrax=%rax,<rz2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz2 += mulc
+# asm 1: add <mulc=int64#14,<rz2=int64#12
+# asm 2: add <mulc=%rbx,<rz2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz3 += mulc
+# asm 1: add <mulc=int64#14,<rz3=int64#13
+# asm 2: add <mulc=%rbx,<rz3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 48(<pp=%rsi),>mulx2=%r11
+movq 48(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rz2 += mulrax
+# asm 1: add <mulrax=int64#7,<rz2=int64#12
+# asm 2: add <mulrax=%rax,<rz2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rz3 += mulc
+# asm 1: add <mulc=int64#14,<rz3=int64#13
+# asm 2: add <mulc=%rbx,<rz3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 56(<pp=%rsi),>mulx3=%r11
+movq 56(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 96(<pp=%rsi),>mulrax=%rax
+movq 96(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? rz3 += mulrax
+# asm 1: add <mulrax=int64#7,<rz3=int64#13
+# asm 2: add <mulrax=%rax,<rz3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 104(<pp=%rsi),>mulrax=%rax
+movq 104(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 112(<pp=%rsi),>mulrax=%rax
+movq 112(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 120(<pp=%rsi),>mulrax=%rax
+movq 120(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#4
+# asm 2: mov <mulrax=%rax,>mulr4=%rcx
+mov %rax,%rcx
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#5
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r8
+mov %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#8
+# asm 2: add <mulrax=%rax,<mulr7=%r10
+add %rax,%r10
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rz0 += mulr4
+# asm 1: add <mulr4=int64#4,<rz0=int64#10
+# asm 2: add <mulr4=%rcx,<rz0=%r12
+add %rcx,%r12
+
+# qhasm: carry? rz1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#5,<rz1=int64#11
+# asm 2: adc <mulr5=%r8,<rz1=%r13
+adc %r8,%r13
+
+# qhasm: carry? rz2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#6,<rz2=int64#12
+# asm 2: adc <mulr6=%r9,<rz2=%r14
+adc %r9,%r14
+
+# qhasm: carry? rz3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#8,<rz3=int64#13
+# asm 2: adc <mulr7=%r10,<rz3=%r15
+adc %r10,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#4
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rcx
+imulq $38,%rax,%rcx
+
+# qhasm: carry? rz0 += mulr8
+# asm 1: add <mulr8=int64#4,<rz0=int64#10
+# asm 2: add <mulr8=%rcx,<rz0=%r12
+add %rcx,%r12
+
+# qhasm: carry? rz1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rz1=int64#11
+# asm 2: adc <mulzero=%rdx,<rz1=%r13
+adc %rdx,%r13
+
+# qhasm: carry? rz2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rz2=int64#12
+# asm 2: adc <mulzero=%rdx,<rz2=%r14
+adc %rdx,%r14
+
+# qhasm: carry? rz3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rz3=int64#13
+# asm 2: adc <mulzero=%rdx,<rz3=%r15
+adc %rdx,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: rz0 += mulzero
+# asm 1: add <mulzero=int64#3,<rz0=int64#10
+# asm 2: add <mulzero=%rdx,<rz0=%r12
+add %rdx,%r12
+
+# qhasm: *(uint64 *)(rp + 64) = rz0
+# asm 1: movq <rz0=int64#10,64(<rp=int64#1)
+# asm 2: movq <rz0=%r12,64(<rp=%rdi)
+movq %r12,64(%rdi)
+
+# qhasm: *(uint64 *)(rp + 72) = rz1
+# asm 1: movq <rz1=int64#11,72(<rp=int64#1)
+# asm 2: movq <rz1=%r13,72(<rp=%rdi)
+movq %r13,72(%rdi)
+
+# qhasm: *(uint64 *)(rp + 80) = rz2
+# asm 1: movq <rz2=int64#12,80(<rp=int64#1)
+# asm 2: movq <rz2=%r14,80(<rp=%rdi)
+movq %r14,80(%rdi)
+
+# qhasm: *(uint64 *)(rp + 88) = rz3
+# asm 1: movq <rz3=int64#13,88(<rp=int64#1)
+# asm 2: movq <rz3=%r15,88(<rp=%rdi)
+movq %r15,88(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#4
+# asm 2: mov $0,>mulr4=%rcx
+mov $0,%rcx
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#5
+# asm 2: mov $0,>mulr5=%r8
+mov $0,%r8
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#6
+# asm 2: mov $0,>mulr6=%r9
+mov $0,%r9
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#8
+# asm 2: mov $0,>mulr7=%r10
+mov $0,%r10
+
+# qhasm: mulx0 = *(uint64 *)(pp + 0)
+# asm 1: movq 0(<pp=int64#2),>mulx0=int64#9
+# asm 2: movq 0(<pp=%rsi),>mulx0=%r11
+movq 0(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<pp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: rt0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rt0=int64#10
+# asm 2: mov <mulrax=%rax,>rt0=%r12
+mov %rax,%r12
+
+# qhasm: rt1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rt1=int64#11
+# asm 2: mov <mulrdx=%rdx,>rt1=%r13
+mov %rdx,%r13
+
+# qhasm: mulrax = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<pp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#11
+# asm 2: add <mulrax=%rax,<rt1=%r13
+add %rax,%r13
+
+# qhasm: rt2 = 0
+# asm 1: mov $0,>rt2=int64#12
+# asm 2: mov $0,>rt2=%r14
+mov $0,%r14
+
+# qhasm: rt2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt2=int64#12
+# asm 2: adc <mulrdx=%rdx,<rt2=%r14
+adc %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<pp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#12
+# asm 2: add <mulrax=%rax,<rt2=%r14
+add %rax,%r14
+
+# qhasm: rt3 = 0
+# asm 1: mov $0,>rt3=int64#13
+# asm 2: mov $0,>rt3=%r15
+mov $0,%r15
+
+# qhasm: rt3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt3=int64#13
+# asm 2: adc <mulrdx=%rdx,<rt3=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<pp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#9
+# asm 2: mul <mulx0=%r11
+mul %r11
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#13
+# asm 2: add <mulrax=%rax,<rt3=%r15
+add %rax,%r15
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#4
+# asm 2: adc <mulrdx=%rdx,<mulr4=%rcx
+adc %rdx,%rcx
+
+# qhasm: mulx1 = *(uint64 *)(pp + 8)
+# asm 1: movq 8(<pp=int64#2),>mulx1=int64#9
+# asm 2: movq 8(<pp=%rsi),>mulx1=%r11
+movq 8(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<pp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#11
+# asm 2: add <mulrax=%rax,<rt1=%r13
+add %rax,%r13
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<pp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#12
+# asm 2: add <mulrax=%rax,<rt2=%r14
+add %rax,%r14
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt2 += mulc
+# asm 1: add <mulc=int64#14,<rt2=int64#12
+# asm 2: add <mulc=%rbx,<rt2=%r14
+add %rbx,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<pp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#13
+# asm 2: add <mulrax=%rax,<rt3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#14,<rt3=int64#13
+# asm 2: add <mulc=%rbx,<rt3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<pp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#9
+# asm 2: mul <mulx1=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r8
+adc %rdx,%r8
+
+# qhasm: mulx2 = *(uint64 *)(pp + 16)
+# asm 1: movq 16(<pp=int64#2),>mulx2=int64#9
+# asm 2: movq 16(<pp=%rsi),>mulx2=%r11
+movq 16(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<pp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#12
+# asm 2: add <mulrax=%rax,<rt2=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<pp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#13
+# asm 2: add <mulrax=%rax,<rt3=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#14,<rt3=int64#13
+# asm 2: add <mulc=%rbx,<rt3=%r15
+add %rbx,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<pp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<pp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#9
+# asm 2: mul <mulx2=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r9
+adc %rdx,%r9
+
+# qhasm: mulx3 = *(uint64 *)(pp + 24)
+# asm 1: movq 24(<pp=int64#2),>mulx3=int64#9
+# asm 2: movq 24(<pp=%rsi),>mulx3=%r11
+movq 24(%rsi),%r11
+
+# qhasm: mulrax = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 64(<pp=%rsi),>mulrax=%rax
+movq 64(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#13
+# asm 2: add <mulrax=%rax,<rt3=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 72(<pp=%rsi),>mulrax=%rax
+movq 72(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#4
+# asm 2: add <mulrax=%rax,<mulr4=%rcx
+add %rax,%rcx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#14,<mulr4=int64#4
+# asm 2: add <mulc=%rbx,<mulr4=%rcx
+add %rbx,%rcx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 80(<pp=%rsi),>mulrax=%rax
+movq 80(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#5
+# asm 2: add <mulrax=%rax,<mulr5=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#14,<mulr5=int64#5
+# asm 2: add <mulc=%rbx,<mulr5=%r8
+add %rbx,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#14
+# asm 2: mov $0,>mulc=%rbx
+mov $0,%rbx
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#14
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulrax=int64#7
+# asm 2: movq 88(<pp=%rsi),>mulrax=%rax
+movq 88(%rsi),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#9
+# asm 2: mul <mulx3=%r11
+mul %r11
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#6
+# asm 2: add <mulrax=%rax,<mulr6=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#14,<mulr6=int64#6
+# asm 2: add <mulc=%rbx,<mulr6=%r9
+add %rbx,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r10
+adc %rdx,%r10
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#4,>mulrax=int64#7
+# asm 2: mov <mulr4=%rcx,>mulrax=%rax
+mov %rcx,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr5=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr6=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr7=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rt0 += mulr4
+# asm 1: add <mulr4=int64#2,<rt0=int64#10
+# asm 2: add <mulr4=%rsi,<rt0=%r12
+add %rsi,%r12
+
+# qhasm: carry? rt1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rt1=int64#11
+# asm 2: adc <mulr5=%rcx,<rt1=%r13
+adc %rcx,%r13
+
+# qhasm: carry? rt2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rt2=int64#12
+# asm 2: adc <mulr6=%r8,<rt2=%r14
+adc %r8,%r14
+
+# qhasm: carry? rt3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rt3=int64#13
+# asm 2: adc <mulr7=%r9,<rt3=%r15
+adc %r9,%r15
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rt0 += mulr8
+# asm 1: add <mulr8=int64#3,<rt0=int64#10
+# asm 2: add <mulr8=%rdx,<rt0=%r12
+add %rdx,%r12
+
+# qhasm: carry? rt1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt1=int64#11
+# asm 2: adc <mulzero=%rsi,<rt1=%r13
+adc %rsi,%r13
+
+# qhasm: carry? rt2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt2=int64#12
+# asm 2: adc <mulzero=%rsi,<rt2=%r14
+adc %rsi,%r14
+
+# qhasm: carry? rt3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt3=int64#13
+# asm 2: adc <mulzero=%rsi,<rt3=%r15
+adc %rsi,%r15
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rt0 += mulzero
+# asm 1: add <mulzero=int64#2,<rt0=int64#10
+# asm 2: add <mulzero=%rsi,<rt0=%r12
+add %rsi,%r12
+
+# qhasm: *(uint64 *)(rp + 96) = rt0
+# asm 1: movq <rt0=int64#10,96(<rp=int64#1)
+# asm 2: movq <rt0=%r12,96(<rp=%rdi)
+movq %r12,96(%rdi)
+
+# qhasm: *(uint64 *)(rp + 104) = rt1
+# asm 1: movq <rt1=int64#11,104(<rp=int64#1)
+# asm 2: movq <rt1=%r13,104(<rp=%rdi)
+movq %r13,104(%rdi)
+
+# qhasm: *(uint64 *)(rp + 112) = rt2
+# asm 1: movq <rt2=int64#12,112(<rp=int64#1)
+# asm 2: movq <rt2=%r14,112(<rp=%rdi)
+movq %r14,112(%rdi)
+
+# qhasm: *(uint64 *)(rp + 120) = rt3
+# asm 1: movq <rt3=int64#13,120(<rp=int64#1)
+# asm 2: movq <rt3=%r15,120(<rp=%rdi)
+movq %r15,120(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_pack.c b/ext/ed25519-amd64-asm/ge25519_pack.c
new file mode 100644
index 00000000..f289fe57
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_pack.c
@@ -0,0 +1,13 @@
+#include "fe25519.h"
+#include "sc25519.h"
+#include "ge25519.h"
+
+void ge25519_pack(unsigned char r[32], const ge25519_p3 *p)
+{
+ fe25519 tx, ty, zi;
+ fe25519_invert(&zi, &p->z);
+ fe25519_mul(&tx, &p->x, &zi);
+ fe25519_mul(&ty, &p->y, &zi);
+ fe25519_pack(r, &ty);
+ r[31] ^= fe25519_getparity(&tx) << 7;
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s b/ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s
new file mode 100644
index 00000000..aff2e75d
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_pnielsadd_p1p1.s
@@ -0,0 +1,3662 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 pp
+
+# qhasm: int64 qp
+
+# qhasm: input rp
+
+# qhasm: input pp
+
+# qhasm: input qp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 a0
+
+# qhasm: int64 a1
+
+# qhasm: int64 a2
+
+# qhasm: int64 a3
+
+# qhasm: stack64 a0_stack
+
+# qhasm: stack64 a1_stack
+
+# qhasm: stack64 a2_stack
+
+# qhasm: stack64 a3_stack
+
+# qhasm: int64 b0
+
+# qhasm: int64 b1
+
+# qhasm: int64 b2
+
+# qhasm: int64 b3
+
+# qhasm: stack64 b0_stack
+
+# qhasm: stack64 b1_stack
+
+# qhasm: stack64 b2_stack
+
+# qhasm: stack64 b3_stack
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: stack64 c0_stack
+
+# qhasm: stack64 c1_stack
+
+# qhasm: stack64 c2_stack
+
+# qhasm: stack64 c3_stack
+
+# qhasm: int64 d0
+
+# qhasm: int64 d1
+
+# qhasm: int64 d2
+
+# qhasm: int64 d3
+
+# qhasm: stack64 d0_stack
+
+# qhasm: stack64 d1_stack
+
+# qhasm: stack64 d2_stack
+
+# qhasm: stack64 d3_stack
+
+# qhasm: int64 t10
+
+# qhasm: int64 t11
+
+# qhasm: int64 t12
+
+# qhasm: int64 t13
+
+# qhasm: stack64 t10_stack
+
+# qhasm: stack64 t11_stack
+
+# qhasm: stack64 t12_stack
+
+# qhasm: stack64 t13_stack
+
+# qhasm: int64 t20
+
+# qhasm: int64 t21
+
+# qhasm: int64 t22
+
+# qhasm: int64 t23
+
+# qhasm: stack64 t20_stack
+
+# qhasm: stack64 t21_stack
+
+# qhasm: stack64 t22_stack
+
+# qhasm: stack64 t23_stack
+
+# qhasm: int64 rx0
+
+# qhasm: int64 rx1
+
+# qhasm: int64 rx2
+
+# qhasm: int64 rx3
+
+# qhasm: int64 ry0
+
+# qhasm: int64 ry1
+
+# qhasm: int64 ry2
+
+# qhasm: int64 ry3
+
+# qhasm: int64 rz0
+
+# qhasm: int64 rz1
+
+# qhasm: int64 rz2
+
+# qhasm: int64 rz3
+
+# qhasm: int64 rt0
+
+# qhasm: int64 rt1
+
+# qhasm: int64 rt2
+
+# qhasm: int64 rt3
+
+# qhasm: int64 x0
+
+# qhasm: int64 x1
+
+# qhasm: int64 x2
+
+# qhasm: int64 x3
+
+# qhasm: int64 mulr4
+
+# qhasm: int64 mulr5
+
+# qhasm: int64 mulr6
+
+# qhasm: int64 mulr7
+
+# qhasm: int64 mulr8
+
+# qhasm: int64 mulrax
+
+# qhasm: int64 mulrdx
+
+# qhasm: int64 mulx0
+
+# qhasm: int64 mulx1
+
+# qhasm: int64 mulx2
+
+# qhasm: int64 mulx3
+
+# qhasm: int64 mulc
+
+# qhasm: int64 mulzero
+
+# qhasm: int64 muli38
+
+# qhasm: int64 addt0
+
+# qhasm: int64 addt1
+
+# qhasm: int64 subt0
+
+# qhasm: int64 subt1
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1
+.globl crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1
+_crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1:
+crypto_sign_ed25519_amd64_64_ge25519_pnielsadd_p1p1:
+mov %rsp,%r11
+and $31,%r11
+add $128,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: qp = qp
+# asm 1: mov <qp=int64#3,>qp=int64#4
+# asm 2: mov <qp=%rdx,>qp=%rcx
+mov %rdx,%rcx
+
+# qhasm: a0 = *(uint64 *)(pp + 32)
+# asm 1: movq 32(<pp=int64#2),>a0=int64#3
+# asm 2: movq 32(<pp=%rsi),>a0=%rdx
+movq 32(%rsi),%rdx
+
+# qhasm: a1 = *(uint64 *)(pp + 40)
+# asm 1: movq 40(<pp=int64#2),>a1=int64#5
+# asm 2: movq 40(<pp=%rsi),>a1=%r8
+movq 40(%rsi),%r8
+
+# qhasm: a2 = *(uint64 *)(pp + 48)
+# asm 1: movq 48(<pp=int64#2),>a2=int64#6
+# asm 2: movq 48(<pp=%rsi),>a2=%r9
+movq 48(%rsi),%r9
+
+# qhasm: a3 = *(uint64 *)(pp + 56)
+# asm 1: movq 56(<pp=int64#2),>a3=int64#7
+# asm 2: movq 56(<pp=%rsi),>a3=%rax
+movq 56(%rsi),%rax
+
+# qhasm: b0 = a0
+# asm 1: mov <a0=int64#3,>b0=int64#8
+# asm 2: mov <a0=%rdx,>b0=%r10
+mov %rdx,%r10
+
+# qhasm: b1 = a1
+# asm 1: mov <a1=int64#5,>b1=int64#9
+# asm 2: mov <a1=%r8,>b1=%r11
+mov %r8,%r11
+
+# qhasm: b2 = a2
+# asm 1: mov <a2=int64#6,>b2=int64#10
+# asm 2: mov <a2=%r9,>b2=%r12
+mov %r9,%r12
+
+# qhasm: b3 = a3
+# asm 1: mov <a3=int64#7,>b3=int64#11
+# asm 2: mov <a3=%rax,>b3=%r13
+mov %rax,%r13
+
+# qhasm: carry? a0 -= *(uint64 *)(pp + 0)
+# asm 1: subq 0(<pp=int64#2),<a0=int64#3
+# asm 2: subq 0(<pp=%rsi),<a0=%rdx
+subq 0(%rsi),%rdx
+
+# qhasm: carry? a1 -= *(uint64 *)(pp + 8) - carry
+# asm 1: sbbq 8(<pp=int64#2),<a1=int64#5
+# asm 2: sbbq 8(<pp=%rsi),<a1=%r8
+sbbq 8(%rsi),%r8
+
+# qhasm: carry? a2 -= *(uint64 *)(pp + 16) - carry
+# asm 1: sbbq 16(<pp=int64#2),<a2=int64#6
+# asm 2: sbbq 16(<pp=%rsi),<a2=%r9
+sbbq 16(%rsi),%r9
+
+# qhasm: carry? a3 -= *(uint64 *)(pp + 24) - carry
+# asm 1: sbbq 24(<pp=int64#2),<a3=int64#7
+# asm 2: sbbq 24(<pp=%rsi),<a3=%rax
+sbbq 24(%rsi),%rax
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#12
+# asm 2: mov $0,>subt0=%r14
+mov $0,%r14
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#13
+# asm 2: mov $38,>subt1=%r15
+mov $38,%r15
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#12,<subt1=int64#13
+# asm 2: cmovae <subt0=%r14,<subt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? a0 -= subt1
+# asm 1: sub <subt1=int64#13,<a0=int64#3
+# asm 2: sub <subt1=%r15,<a0=%rdx
+sub %r15,%rdx
+
+# qhasm: carry? a1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a1=int64#5
+# asm 2: sbb <subt0=%r14,<a1=%r8
+sbb %r14,%r8
+
+# qhasm: carry? a2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a2=int64#6
+# asm 2: sbb <subt0=%r14,<a2=%r9
+sbb %r14,%r9
+
+# qhasm: carry? a3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#12,<a3=int64#7
+# asm 2: sbb <subt0=%r14,<a3=%rax
+sbb %r14,%rax
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#13,<subt0=int64#12
+# asm 2: cmovc <subt1=%r15,<subt0=%r14
+cmovc %r15,%r14
+
+# qhasm: a0 -= subt0
+# asm 1: sub <subt0=int64#12,<a0=int64#3
+# asm 2: sub <subt0=%r14,<a0=%rdx
+sub %r14,%rdx
+
+# qhasm: carry? b0 += *(uint64 *)(pp + 0)
+# asm 1: addq 0(<pp=int64#2),<b0=int64#8
+# asm 2: addq 0(<pp=%rsi),<b0=%r10
+addq 0(%rsi),%r10
+
+# qhasm: carry? b1 += *(uint64 *)(pp + 8) + carry
+# asm 1: adcq 8(<pp=int64#2),<b1=int64#9
+# asm 2: adcq 8(<pp=%rsi),<b1=%r11
+adcq 8(%rsi),%r11
+
+# qhasm: carry? b2 += *(uint64 *)(pp + 16) + carry
+# asm 1: adcq 16(<pp=int64#2),<b2=int64#10
+# asm 2: adcq 16(<pp=%rsi),<b2=%r12
+adcq 16(%rsi),%r12
+
+# qhasm: carry? b3 += *(uint64 *)(pp + 24) + carry
+# asm 1: adcq 24(<pp=int64#2),<b3=int64#11
+# asm 2: adcq 24(<pp=%rsi),<b3=%r13
+adcq 24(%rsi),%r13
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#12
+# asm 2: mov $0,>addt0=%r14
+mov $0,%r14
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#13
+# asm 2: mov $38,>addt1=%r15
+mov $38,%r15
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#12,<addt1=int64#13
+# asm 2: cmovae <addt0=%r14,<addt1=%r15
+cmovae %r14,%r15
+
+# qhasm: carry? b0 += addt1
+# asm 1: add <addt1=int64#13,<b0=int64#8
+# asm 2: add <addt1=%r15,<b0=%r10
+add %r15,%r10
+
+# qhasm: carry? b1 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b1=int64#9
+# asm 2: adc <addt0=%r14,<b1=%r11
+adc %r14,%r11
+
+# qhasm: carry? b2 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b2=int64#10
+# asm 2: adc <addt0=%r14,<b2=%r12
+adc %r14,%r12
+
+# qhasm: carry? b3 += addt0 + carry
+# asm 1: adc <addt0=int64#12,<b3=int64#11
+# asm 2: adc <addt0=%r14,<b3=%r13
+adc %r14,%r13
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#13,<addt0=int64#12
+# asm 2: cmovc <addt1=%r15,<addt0=%r14
+cmovc %r15,%r14
+
+# qhasm: b0 += addt0
+# asm 1: add <addt0=int64#12,<b0=int64#8
+# asm 2: add <addt0=%r14,<b0=%r10
+add %r14,%r10
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#3,>a0_stack=stack64#8
+# asm 2: movq <a0=%rdx,>a0_stack=56(%rsp)
+movq %rdx,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#5,>a1_stack=stack64#9
+# asm 2: movq <a1=%r8,>a1_stack=64(%rsp)
+movq %r8,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#6,>a2_stack=stack64#10
+# asm 2: movq <a2=%r9,>a2_stack=72(%rsp)
+movq %r9,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#7,>a3_stack=stack64#11
+# asm 2: movq <a3=%rax,>a3_stack=80(%rsp)
+movq %rax,80(%rsp)
+
+# qhasm: b0_stack = b0
+# asm 1: movq <b0=int64#8,>b0_stack=stack64#12
+# asm 2: movq <b0=%r10,>b0_stack=88(%rsp)
+movq %r10,88(%rsp)
+
+# qhasm: b1_stack = b1
+# asm 1: movq <b1=int64#9,>b1_stack=stack64#13
+# asm 2: movq <b1=%r11,>b1_stack=96(%rsp)
+movq %r11,96(%rsp)
+
+# qhasm: b2_stack = b2
+# asm 1: movq <b2=int64#10,>b2_stack=stack64#14
+# asm 2: movq <b2=%r12,>b2_stack=104(%rsp)
+movq %r12,104(%rsp)
+
+# qhasm: b3_stack = b3
+# asm 1: movq <b3=int64#11,>b3_stack=stack64#15
+# asm 2: movq <b3=%r13,>b3_stack=112(%rsp)
+movq %r13,112(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = a0_stack
+# asm 1: movq <a0_stack=stack64#8,>mulx0=int64#10
+# asm 2: movq <a0_stack=56(%rsp),>mulx0=%r12
+movq 56(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: a0 = mulrax
+# asm 1: mov <mulrax=int64#7,>a0=int64#11
+# asm 2: mov <mulrax=%rax,>a0=%r13
+mov %rax,%r13
+
+# qhasm: a1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>a1=int64#12
+# asm 2: mov <mulrdx=%rdx,>a1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#12
+# asm 2: add <mulrax=%rax,<a1=%r14
+add %rax,%r14
+
+# qhasm: a2 = 0
+# asm 1: mov $0,>a2=int64#13
+# asm 2: mov $0,>a2=%r15
+mov $0,%r15
+
+# qhasm: a2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a2=int64#13
+# asm 2: adc <mulrdx=%rdx,<a2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: a3 = 0
+# asm 1: mov $0,>a3=int64#14
+# asm 2: mov $0,>a3=%rbx
+mov $0,%rbx
+
+# qhasm: a3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<a3=int64#14
+# asm 2: adc <mulrdx=%rdx,<a3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = a1_stack
+# asm 1: movq <a1_stack=stack64#9,>mulx1=int64#10
+# asm 2: movq <a1_stack=64(%rsp),>mulx1=%r12
+movq 64(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a1 += mulrax
+# asm 1: add <mulrax=int64#7,<a1=int64#12
+# asm 2: add <mulrax=%rax,<a1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a2 += mulc
+# asm 1: add <mulc=int64#15,<a2=int64#13
+# asm 2: add <mulc=%rbp,<a2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#15,<a3=int64#14
+# asm 2: add <mulc=%rbp,<a3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = a2_stack
+# asm 1: movq <a2_stack=stack64#10,>mulx2=int64#10
+# asm 2: movq <a2_stack=72(%rsp),>mulx2=%r12
+movq 72(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? a2 += mulrax
+# asm 1: add <mulrax=int64#7,<a2=int64#13
+# asm 2: add <mulrax=%rax,<a2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? a3 += mulc
+# asm 1: add <mulc=int64#15,<a3=int64#14
+# asm 2: add <mulc=%rbp,<a3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = a3_stack
+# asm 1: movq <a3_stack=stack64#11,>mulx3=int64#10
+# asm 2: movq <a3_stack=80(%rsp),>mulx3=%r12
+movq 80(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 0)
+# asm 1: movq 0(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 0(<qp=%rcx),>mulrax=%rax
+movq 0(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? a3 += mulrax
+# asm 1: add <mulrax=int64#7,<a3=int64#14
+# asm 2: add <mulrax=%rax,<a3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 8)
+# asm 1: movq 8(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 8(<qp=%rcx),>mulrax=%rax
+movq 8(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 16)
+# asm 1: movq 16(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 16(<qp=%rcx),>mulrax=%rax
+movq 16(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 24)
+# asm 1: movq 24(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 24(<qp=%rcx),>mulrax=%rax
+movq 24(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? a0 += mulr4
+# asm 1: add <mulr4=int64#5,<a0=int64#11
+# asm 2: add <mulr4=%r8,<a0=%r13
+add %r8,%r13
+
+# qhasm: carry? a1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<a1=int64#12
+# asm 2: adc <mulr5=%r9,<a1=%r14
+adc %r9,%r14
+
+# qhasm: carry? a2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<a2=int64#13
+# asm 2: adc <mulr6=%r10,<a2=%r15
+adc %r10,%r15
+
+# qhasm: carry? a3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<a3=int64#14
+# asm 2: adc <mulr7=%r11,<a3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? a0 += mulr8
+# asm 1: add <mulr8=int64#5,<a0=int64#11
+# asm 2: add <mulr8=%r8,<a0=%r13
+add %r8,%r13
+
+# qhasm: carry? a1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a1=int64#12
+# asm 2: adc <mulzero=%rdx,<a1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? a2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a2=int64#13
+# asm 2: adc <mulzero=%rdx,<a2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? a3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<a3=int64#14
+# asm 2: adc <mulzero=%rdx,<a3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: a0 += mulzero
+# asm 1: add <mulzero=int64#3,<a0=int64#11
+# asm 2: add <mulzero=%rdx,<a0=%r13
+add %rdx,%r13
+
+# qhasm: a0_stack = a0
+# asm 1: movq <a0=int64#11,>a0_stack=stack64#8
+# asm 2: movq <a0=%r13,>a0_stack=56(%rsp)
+movq %r13,56(%rsp)
+
+# qhasm: a1_stack = a1
+# asm 1: movq <a1=int64#12,>a1_stack=stack64#9
+# asm 2: movq <a1=%r14,>a1_stack=64(%rsp)
+movq %r14,64(%rsp)
+
+# qhasm: a2_stack = a2
+# asm 1: movq <a2=int64#13,>a2_stack=stack64#10
+# asm 2: movq <a2=%r15,>a2_stack=72(%rsp)
+movq %r15,72(%rsp)
+
+# qhasm: a3_stack = a3
+# asm 1: movq <a3=int64#14,>a3_stack=stack64#11
+# asm 2: movq <a3=%rbx,>a3_stack=80(%rsp)
+movq %rbx,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = b0_stack
+# asm 1: movq <b0_stack=stack64#12,>mulx0=int64#10
+# asm 2: movq <b0_stack=88(%rsp),>mulx0=%r12
+movq 88(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: rx0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rx0=int64#11
+# asm 2: mov <mulrax=%rax,>rx0=%r13
+mov %rax,%r13
+
+# qhasm: rx1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rx1=int64#12
+# asm 2: mov <mulrdx=%rdx,>rx1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#12
+# asm 2: add <mulrax=%rax,<rx1=%r14
+add %rax,%r14
+
+# qhasm: rx2 = 0
+# asm 1: mov $0,>rx2=int64#13
+# asm 2: mov $0,>rx2=%r15
+mov $0,%r15
+
+# qhasm: rx2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx2=int64#13
+# asm 2: adc <mulrdx=%rdx,<rx2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#13
+# asm 2: add <mulrax=%rax,<rx2=%r15
+add %rax,%r15
+
+# qhasm: rx3 = 0
+# asm 1: mov $0,>rx3=int64#14
+# asm 2: mov $0,>rx3=%rbx
+mov $0,%rbx
+
+# qhasm: rx3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rx3=int64#14
+# asm 2: adc <mulrdx=%rdx,<rx3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = b1_stack
+# asm 1: movq <b1_stack=stack64#13,>mulx1=int64#10
+# asm 2: movq <b1_stack=96(%rsp),>mulx1=%r12
+movq 96(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rx1 += mulrax
+# asm 1: add <mulrax=int64#7,<rx1=int64#12
+# asm 2: add <mulrax=%rax,<rx1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#13
+# asm 2: add <mulrax=%rax,<rx2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx2 += mulc
+# asm 1: add <mulc=int64#15,<rx2=int64#13
+# asm 2: add <mulc=%rbp,<rx2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#15,<rx3=int64#14
+# asm 2: add <mulc=%rbp,<rx3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = b2_stack
+# asm 1: movq <b2_stack=stack64#14,>mulx2=int64#10
+# asm 2: movq <b2_stack=104(%rsp),>mulx2=%r12
+movq 104(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rx2 += mulrax
+# asm 1: add <mulrax=int64#7,<rx2=int64#13
+# asm 2: add <mulrax=%rax,<rx2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rx3 += mulc
+# asm 1: add <mulc=int64#15,<rx3=int64#14
+# asm 2: add <mulc=%rbp,<rx3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = b3_stack
+# asm 1: movq <b3_stack=stack64#15,>mulx3=int64#10
+# asm 2: movq <b3_stack=112(%rsp),>mulx3=%r12
+movq 112(%rsp),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 32)
+# asm 1: movq 32(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 32(<qp=%rcx),>mulrax=%rax
+movq 32(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? rx3 += mulrax
+# asm 1: add <mulrax=int64#7,<rx3=int64#14
+# asm 2: add <mulrax=%rax,<rx3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 40)
+# asm 1: movq 40(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 40(<qp=%rcx),>mulrax=%rax
+movq 40(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 48)
+# asm 1: movq 48(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 48(<qp=%rcx),>mulrax=%rax
+movq 48(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 56)
+# asm 1: movq 56(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 56(<qp=%rcx),>mulrax=%rax
+movq 56(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rx0 += mulr4
+# asm 1: add <mulr4=int64#5,<rx0=int64#11
+# asm 2: add <mulr4=%r8,<rx0=%r13
+add %r8,%r13
+
+# qhasm: carry? rx1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<rx1=int64#12
+# asm 2: adc <mulr5=%r9,<rx1=%r14
+adc %r9,%r14
+
+# qhasm: carry? rx2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<rx2=int64#13
+# asm 2: adc <mulr6=%r10,<rx2=%r15
+adc %r10,%r15
+
+# qhasm: carry? rx3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<rx3=int64#14
+# asm 2: adc <mulr7=%r11,<rx3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? rx0 += mulr8
+# asm 1: add <mulr8=int64#5,<rx0=int64#11
+# asm 2: add <mulr8=%r8,<rx0=%r13
+add %r8,%r13
+
+# qhasm: carry? rx1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx1=int64#12
+# asm 2: adc <mulzero=%rdx,<rx1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? rx2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx2=int64#13
+# asm 2: adc <mulzero=%rdx,<rx2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? rx3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<rx3=int64#14
+# asm 2: adc <mulzero=%rdx,<rx3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: rx0 += mulzero
+# asm 1: add <mulzero=int64#3,<rx0=int64#11
+# asm 2: add <mulzero=%rdx,<rx0=%r13
+add %rdx,%r13
+
+# qhasm: ry0 = rx0
+# asm 1: mov <rx0=int64#11,>ry0=int64#3
+# asm 2: mov <rx0=%r13,>ry0=%rdx
+mov %r13,%rdx
+
+# qhasm: ry1 = rx1
+# asm 1: mov <rx1=int64#12,>ry1=int64#5
+# asm 2: mov <rx1=%r14,>ry1=%r8
+mov %r14,%r8
+
+# qhasm: ry2 = rx2
+# asm 1: mov <rx2=int64#13,>ry2=int64#6
+# asm 2: mov <rx2=%r15,>ry2=%r9
+mov %r15,%r9
+
+# qhasm: ry3 = rx3
+# asm 1: mov <rx3=int64#14,>ry3=int64#7
+# asm 2: mov <rx3=%rbx,>ry3=%rax
+mov %rbx,%rax
+
+# qhasm: carry? ry0 += a0_stack
+# asm 1: addq <a0_stack=stack64#8,<ry0=int64#3
+# asm 2: addq <a0_stack=56(%rsp),<ry0=%rdx
+addq 56(%rsp),%rdx
+
+# qhasm: carry? ry1 += a1_stack + carry
+# asm 1: adcq <a1_stack=stack64#9,<ry1=int64#5
+# asm 2: adcq <a1_stack=64(%rsp),<ry1=%r8
+adcq 64(%rsp),%r8
+
+# qhasm: carry? ry2 += a2_stack + carry
+# asm 1: adcq <a2_stack=stack64#10,<ry2=int64#6
+# asm 2: adcq <a2_stack=72(%rsp),<ry2=%r9
+adcq 72(%rsp),%r9
+
+# qhasm: carry? ry3 += a3_stack + carry
+# asm 1: adcq <a3_stack=stack64#11,<ry3=int64#7
+# asm 2: adcq <a3_stack=80(%rsp),<ry3=%rax
+adcq 80(%rsp),%rax
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#8
+# asm 2: mov $0,>addt0=%r10
+mov $0,%r10
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#9
+# asm 2: mov $38,>addt1=%r11
+mov $38,%r11
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#8,<addt1=int64#9
+# asm 2: cmovae <addt0=%r10,<addt1=%r11
+cmovae %r10,%r11
+
+# qhasm: carry? ry0 += addt1
+# asm 1: add <addt1=int64#9,<ry0=int64#3
+# asm 2: add <addt1=%r11,<ry0=%rdx
+add %r11,%rdx
+
+# qhasm: carry? ry1 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<ry1=int64#5
+# asm 2: adc <addt0=%r10,<ry1=%r8
+adc %r10,%r8
+
+# qhasm: carry? ry2 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<ry2=int64#6
+# asm 2: adc <addt0=%r10,<ry2=%r9
+adc %r10,%r9
+
+# qhasm: carry? ry3 += addt0 + carry
+# asm 1: adc <addt0=int64#8,<ry3=int64#7
+# asm 2: adc <addt0=%r10,<ry3=%rax
+adc %r10,%rax
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#9,<addt0=int64#8
+# asm 2: cmovc <addt1=%r11,<addt0=%r10
+cmovc %r11,%r10
+
+# qhasm: ry0 += addt0
+# asm 1: add <addt0=int64#8,<ry0=int64#3
+# asm 2: add <addt0=%r10,<ry0=%rdx
+add %r10,%rdx
+
+# qhasm: carry? rx0 -= a0_stack
+# asm 1: subq <a0_stack=stack64#8,<rx0=int64#11
+# asm 2: subq <a0_stack=56(%rsp),<rx0=%r13
+subq 56(%rsp),%r13
+
+# qhasm: carry? rx1 -= a1_stack - carry
+# asm 1: sbbq <a1_stack=stack64#9,<rx1=int64#12
+# asm 2: sbbq <a1_stack=64(%rsp),<rx1=%r14
+sbbq 64(%rsp),%r14
+
+# qhasm: carry? rx2 -= a2_stack - carry
+# asm 1: sbbq <a2_stack=stack64#10,<rx2=int64#13
+# asm 2: sbbq <a2_stack=72(%rsp),<rx2=%r15
+sbbq 72(%rsp),%r15
+
+# qhasm: carry? rx3 -= a3_stack - carry
+# asm 1: sbbq <a3_stack=stack64#11,<rx3=int64#14
+# asm 2: sbbq <a3_stack=80(%rsp),<rx3=%rbx
+sbbq 80(%rsp),%rbx
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#8
+# asm 2: mov $0,>subt0=%r10
+mov $0,%r10
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#9
+# asm 2: mov $38,>subt1=%r11
+mov $38,%r11
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#8,<subt1=int64#9
+# asm 2: cmovae <subt0=%r10,<subt1=%r11
+cmovae %r10,%r11
+
+# qhasm: carry? rx0 -= subt1
+# asm 1: sub <subt1=int64#9,<rx0=int64#11
+# asm 2: sub <subt1=%r11,<rx0=%r13
+sub %r11,%r13
+
+# qhasm: carry? rx1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<rx1=int64#12
+# asm 2: sbb <subt0=%r10,<rx1=%r14
+sbb %r10,%r14
+
+# qhasm: carry? rx2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<rx2=int64#13
+# asm 2: sbb <subt0=%r10,<rx2=%r15
+sbb %r10,%r15
+
+# qhasm: carry? rx3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#8,<rx3=int64#14
+# asm 2: sbb <subt0=%r10,<rx3=%rbx
+sbb %r10,%rbx
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#9,<subt0=int64#8
+# asm 2: cmovc <subt1=%r11,<subt0=%r10
+cmovc %r11,%r10
+
+# qhasm: rx0 -= subt0
+# asm 1: sub <subt0=int64#8,<rx0=int64#11
+# asm 2: sub <subt0=%r10,<rx0=%r13
+sub %r10,%r13
+
+# qhasm: *(uint64 *) (rp + 0) = rx0
+# asm 1: movq <rx0=int64#11,0(<rp=int64#1)
+# asm 2: movq <rx0=%r13,0(<rp=%rdi)
+movq %r13,0(%rdi)
+
+# qhasm: *(uint64 *) (rp + 8) = rx1
+# asm 1: movq <rx1=int64#12,8(<rp=int64#1)
+# asm 2: movq <rx1=%r14,8(<rp=%rdi)
+movq %r14,8(%rdi)
+
+# qhasm: *(uint64 *) (rp + 16) = rx2
+# asm 1: movq <rx2=int64#13,16(<rp=int64#1)
+# asm 2: movq <rx2=%r15,16(<rp=%rdi)
+movq %r15,16(%rdi)
+
+# qhasm: *(uint64 *) (rp + 24) = rx3
+# asm 1: movq <rx3=int64#14,24(<rp=int64#1)
+# asm 2: movq <rx3=%rbx,24(<rp=%rdi)
+movq %rbx,24(%rdi)
+
+# qhasm: *(uint64 *) (rp + 64) = ry0
+# asm 1: movq <ry0=int64#3,64(<rp=int64#1)
+# asm 2: movq <ry0=%rdx,64(<rp=%rdi)
+movq %rdx,64(%rdi)
+
+# qhasm: *(uint64 *) (rp + 72) = ry1
+# asm 1: movq <ry1=int64#5,72(<rp=int64#1)
+# asm 2: movq <ry1=%r8,72(<rp=%rdi)
+movq %r8,72(%rdi)
+
+# qhasm: *(uint64 *) (rp + 80) = ry2
+# asm 1: movq <ry2=int64#6,80(<rp=int64#1)
+# asm 2: movq <ry2=%r9,80(<rp=%rdi)
+movq %r9,80(%rdi)
+
+# qhasm: *(uint64 *) (rp + 88) = ry3
+# asm 1: movq <ry3=int64#7,88(<rp=int64#1)
+# asm 2: movq <ry3=%rax,88(<rp=%rdi)
+movq %rax,88(%rdi)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = *(uint64 *)(pp + 96)
+# asm 1: movq 96(<pp=int64#2),>mulx0=int64#10
+# asm 2: movq 96(<pp=%rsi),>mulx0=%r12
+movq 96(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: c0 = mulrax
+# asm 1: mov <mulrax=int64#7,>c0=int64#11
+# asm 2: mov <mulrax=%rax,>c0=%r13
+mov %rax,%r13
+
+# qhasm: c1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>c1=int64#12
+# asm 2: mov <mulrdx=%rdx,>c1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: c2 = 0
+# asm 1: mov $0,>c2=int64#13
+# asm 2: mov $0,>c2=%r15
+mov $0,%r15
+
+# qhasm: c2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c2=int64#13
+# asm 2: adc <mulrdx=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: c3 = 0
+# asm 1: mov $0,>c3=int64#14
+# asm 2: mov $0,>c3=%rbx
+mov $0,%rbx
+
+# qhasm: c3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<c3=int64#14
+# asm 2: adc <mulrdx=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = *(uint64 *)(pp + 104)
+# asm 1: movq 104(<pp=int64#2),>mulx1=int64#10
+# asm 2: movq 104(<pp=%rsi),>mulx1=%r12
+movq 104(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c1 += mulrax
+# asm 1: add <mulrax=int64#7,<c1=int64#12
+# asm 2: add <mulrax=%rax,<c1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c2 += mulc
+# asm 1: add <mulc=int64#15,<c2=int64#13
+# asm 2: add <mulc=%rbp,<c2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = *(uint64 *)(pp + 112)
+# asm 1: movq 112(<pp=int64#2),>mulx2=int64#10
+# asm 2: movq 112(<pp=%rsi),>mulx2=%r12
+movq 112(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c2 += mulrax
+# asm 1: add <mulrax=int64#7,<c2=int64#13
+# asm 2: add <mulrax=%rax,<c2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? c3 += mulc
+# asm 1: add <mulc=int64#15,<c3=int64#14
+# asm 2: add <mulc=%rbp,<c3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = *(uint64 *)(pp + 120)
+# asm 1: movq 120(<pp=int64#2),>mulx3=int64#10
+# asm 2: movq 120(<pp=%rsi),>mulx3=%r12
+movq 120(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 96)
+# asm 1: movq 96(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 96(<qp=%rcx),>mulrax=%rax
+movq 96(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? c3 += mulrax
+# asm 1: add <mulrax=int64#7,<c3=int64#14
+# asm 2: add <mulrax=%rax,<c3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 104)
+# asm 1: movq 104(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 104(<qp=%rcx),>mulrax=%rax
+movq 104(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 112)
+# asm 1: movq 112(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 112(<qp=%rcx),>mulrax=%rax
+movq 112(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 120)
+# asm 1: movq 120(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 120(<qp=%rcx),>mulrax=%rax
+movq 120(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#10
+# asm 2: mul <mulx3=%r12
+mul %r12
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#15,<mulr6=int64#8
+# asm 2: add <mulc=%rbp,<mulr6=%r10
+add %rbp,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#5
+# asm 2: mov <mulrax=%rax,>mulr4=%r8
+mov %rax,%r8
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#6
+# asm 2: mov <mulrdx=%rdx,>mulr5=%r9
+mov %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#9
+# asm 2: add <mulrax=%rax,<mulr7=%r11
+add %rax,%r11
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? c0 += mulr4
+# asm 1: add <mulr4=int64#5,<c0=int64#11
+# asm 2: add <mulr4=%r8,<c0=%r13
+add %r8,%r13
+
+# qhasm: carry? c1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#6,<c1=int64#12
+# asm 2: adc <mulr5=%r9,<c1=%r14
+adc %r9,%r14
+
+# qhasm: carry? c2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#8,<c2=int64#13
+# asm 2: adc <mulr6=%r10,<c2=%r15
+adc %r10,%r15
+
+# qhasm: carry? c3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#9,<c3=int64#14
+# asm 2: adc <mulr7=%r11,<c3=%rbx
+adc %r11,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#3
+# asm 2: mov $0,>mulzero=%rdx
+mov $0,%rdx
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulr8=int64#7
+# asm 2: adc <mulzero=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#5
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%r8
+imulq $38,%rax,%r8
+
+# qhasm: carry? c0 += mulr8
+# asm 1: add <mulr8=int64#5,<c0=int64#11
+# asm 2: add <mulr8=%r8,<c0=%r13
+add %r8,%r13
+
+# qhasm: carry? c1 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c1=int64#12
+# asm 2: adc <mulzero=%rdx,<c1=%r14
+adc %rdx,%r14
+
+# qhasm: carry? c2 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c2=int64#13
+# asm 2: adc <mulzero=%rdx,<c2=%r15
+adc %rdx,%r15
+
+# qhasm: carry? c3 += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<c3=int64#14
+# asm 2: adc <mulzero=%rdx,<c3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#3,<mulzero=int64#3
+# asm 2: adc <mulzero=%rdx,<mulzero=%rdx
+adc %rdx,%rdx
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#3,>mulzero=int64#3
+# asm 2: imulq $38,<mulzero=%rdx,>mulzero=%rdx
+imulq $38,%rdx,%rdx
+
+# qhasm: c0 += mulzero
+# asm 1: add <mulzero=int64#3,<c0=int64#11
+# asm 2: add <mulzero=%rdx,<c0=%r13
+add %rdx,%r13
+
+# qhasm: c0_stack = c0
+# asm 1: movq <c0=int64#11,>c0_stack=stack64#8
+# asm 2: movq <c0=%r13,>c0_stack=56(%rsp)
+movq %r13,56(%rsp)
+
+# qhasm: c1_stack = c1
+# asm 1: movq <c1=int64#12,>c1_stack=stack64#9
+# asm 2: movq <c1=%r14,>c1_stack=64(%rsp)
+movq %r14,64(%rsp)
+
+# qhasm: c2_stack = c2
+# asm 1: movq <c2=int64#13,>c2_stack=stack64#10
+# asm 2: movq <c2=%r15,>c2_stack=72(%rsp)
+movq %r15,72(%rsp)
+
+# qhasm: c3_stack = c3
+# asm 1: movq <c3=int64#14,>c3_stack=stack64#11
+# asm 2: movq <c3=%rbx,>c3_stack=80(%rsp)
+movq %rbx,80(%rsp)
+
+# qhasm: mulr4 = 0
+# asm 1: mov $0,>mulr4=int64#5
+# asm 2: mov $0,>mulr4=%r8
+mov $0,%r8
+
+# qhasm: mulr5 = 0
+# asm 1: mov $0,>mulr5=int64#6
+# asm 2: mov $0,>mulr5=%r9
+mov $0,%r9
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#8
+# asm 2: mov $0,>mulr6=%r10
+mov $0,%r10
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#9
+# asm 2: mov $0,>mulr7=%r11
+mov $0,%r11
+
+# qhasm: mulx0 = *(uint64 *)(pp + 64)
+# asm 1: movq 64(<pp=int64#2),>mulx0=int64#10
+# asm 2: movq 64(<pp=%rsi),>mulx0=%r12
+movq 64(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: rt0 = mulrax
+# asm 1: mov <mulrax=int64#7,>rt0=int64#11
+# asm 2: mov <mulrax=%rax,>rt0=%r13
+mov %rax,%r13
+
+# qhasm: rt1 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>rt1=int64#12
+# asm 2: mov <mulrdx=%rdx,>rt1=%r14
+mov %rdx,%r14
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#12
+# asm 2: add <mulrax=%rax,<rt1=%r14
+add %rax,%r14
+
+# qhasm: rt2 = 0
+# asm 1: mov $0,>rt2=int64#13
+# asm 2: mov $0,>rt2=%r15
+mov $0,%r15
+
+# qhasm: rt2 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt2=int64#13
+# asm 2: adc <mulrdx=%rdx,<rt2=%r15
+adc %rdx,%r15
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#13
+# asm 2: add <mulrax=%rax,<rt2=%r15
+add %rax,%r15
+
+# qhasm: rt3 = 0
+# asm 1: mov $0,>rt3=int64#14
+# asm 2: mov $0,>rt3=%rbx
+mov $0,%rbx
+
+# qhasm: rt3 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<rt3=int64#14
+# asm 2: adc <mulrdx=%rdx,<rt3=%rbx
+adc %rdx,%rbx
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx0
+# asm 1: mul <mulx0=int64#10
+# asm 2: mul <mulx0=%r12
+mul %r12
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulr4 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr4=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr4=%r8
+adc %rdx,%r8
+
+# qhasm: mulx1 = *(uint64 *)(pp + 72)
+# asm 1: movq 72(<pp=int64#2),>mulx1=int64#10
+# asm 2: movq 72(<pp=%rsi),>mulx1=%r12
+movq 72(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rt1 += mulrax
+# asm 1: add <mulrax=int64#7,<rt1=int64#12
+# asm 2: add <mulrax=%rax,<rt1=%r14
+add %rax,%r14
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#13
+# asm 2: add <mulrax=%rax,<rt2=%r15
+add %rax,%r15
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt2 += mulc
+# asm 1: add <mulc=int64#15,<rt2=int64#13
+# asm 2: add <mulc=%rbp,<rt2=%r15
+add %rbp,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#15,<rt3=int64#14
+# asm 2: add <mulc=%rbp,<rt3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx1
+# asm 1: mul <mulx1=int64#10
+# asm 2: mul <mulx1=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulr5 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr5=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr5=%r9
+adc %rdx,%r9
+
+# qhasm: mulx2 = *(uint64 *)(pp + 80)
+# asm 1: movq 80(<pp=int64#2),>mulx2=int64#10
+# asm 2: movq 80(<pp=%rsi),>mulx2=%r12
+movq 80(%rsi),%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rt2 += mulrax
+# asm 1: add <mulrax=int64#7,<rt2=int64#13
+# asm 2: add <mulrax=%rax,<rt2=%r15
+add %rax,%r15
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? rt3 += mulc
+# asm 1: add <mulc=int64#15,<rt3=int64#14
+# asm 2: add <mulc=%rbp,<rt3=%rbx
+add %rbp,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#15,<mulr4=int64#5
+# asm 2: add <mulc=%rbp,<mulr4=%r8
+add %rbp,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#15
+# asm 2: mov $0,>mulc=%rbp
+mov $0,%rbp
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#15
+# asm 2: adc <mulrdx=%rdx,<mulc=%rbp
+adc %rdx,%rbp
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx2
+# asm 1: mul <mulx2=int64#10
+# asm 2: mul <mulx2=%r12
+mul %r12
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#15,<mulr5=int64#6
+# asm 2: add <mulc=%rbp,<mulr5=%r9
+add %rbp,%r9
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#8
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r10
+adc %rdx,%r10
+
+# qhasm: mulx3 = *(uint64 *)(pp + 88)
+# asm 1: movq 88(<pp=int64#2),>mulx3=int64#2
+# asm 2: movq 88(<pp=%rsi),>mulx3=%rsi
+movq 88(%rsi),%rsi
+
+# qhasm: mulrax = *(uint64 *)(qp + 64)
+# asm 1: movq 64(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 64(<qp=%rcx),>mulrax=%rax
+movq 64(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? rt3 += mulrax
+# asm 1: add <mulrax=int64#7,<rt3=int64#14
+# asm 2: add <mulrax=%rax,<rt3=%rbx
+add %rax,%rbx
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 72)
+# asm 1: movq 72(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 72(<qp=%rcx),>mulrax=%rax
+movq 72(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr4 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr4=int64#5
+# asm 2: add <mulrax=%rax,<mulr4=%r8
+add %rax,%r8
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr4 += mulc
+# asm 1: add <mulc=int64#10,<mulr4=int64#5
+# asm 2: add <mulc=%r12,<mulr4=%r8
+add %r12,%r8
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 80)
+# asm 1: movq 80(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 80(<qp=%rcx),>mulrax=%rax
+movq 80(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#6
+# asm 2: add <mulrax=%rax,<mulr5=%r9
+add %rax,%r9
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr5 += mulc
+# asm 1: add <mulc=int64#10,<mulr5=int64#6
+# asm 2: add <mulc=%r12,<mulr5=%r9
+add %r12,%r9
+
+# qhasm: mulc = 0
+# asm 1: mov $0,>mulc=int64#10
+# asm 2: mov $0,>mulc=%r12
+mov $0,%r12
+
+# qhasm: mulc += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulc=int64#10
+# asm 2: adc <mulrdx=%rdx,<mulc=%r12
+adc %rdx,%r12
+
+# qhasm: mulrax = *(uint64 *)(qp + 88)
+# asm 1: movq 88(<qp=int64#4),>mulrax=int64#7
+# asm 2: movq 88(<qp=%rcx),>mulrax=%rax
+movq 88(%rcx),%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * mulx3
+# asm 1: mul <mulx3=int64#2
+# asm 2: mul <mulx3=%rsi
+mul %rsi
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#8
+# asm 2: add <mulrax=%rax,<mulr6=%r10
+add %rax,%r10
+
+# qhasm: mulrdx += 0 + carry
+# asm 1: adc $0,<mulrdx=int64#3
+# asm 2: adc $0,<mulrdx=%rdx
+adc $0,%rdx
+
+# qhasm: carry? mulr6 += mulc
+# asm 1: add <mulc=int64#10,<mulr6=int64#8
+# asm 2: add <mulc=%r12,<mulr6=%r10
+add %r12,%r10
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#9
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r11
+adc %rdx,%r11
+
+# qhasm: mulrax = mulr4
+# asm 1: mov <mulr4=int64#5,>mulrax=int64#7
+# asm 2: mov <mulr4=%r8,>mulrax=%rax
+mov %r8,%rax
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: mulr4 = mulrax
+# asm 1: mov <mulrax=int64#7,>mulr4=int64#2
+# asm 2: mov <mulrax=%rax,>mulr4=%rsi
+mov %rax,%rsi
+
+# qhasm: mulrax = mulr5
+# asm 1: mov <mulr5=int64#6,>mulrax=int64#7
+# asm 2: mov <mulr5=%r9,>mulrax=%rax
+mov %r9,%rax
+
+# qhasm: mulr5 = mulrdx
+# asm 1: mov <mulrdx=int64#3,>mulr5=int64#4
+# asm 2: mov <mulrdx=%rdx,>mulr5=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr5 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr5=int64#4
+# asm 2: add <mulrax=%rax,<mulr5=%rcx
+add %rax,%rcx
+
+# qhasm: mulrax = mulr6
+# asm 1: mov <mulr6=int64#8,>mulrax=int64#7
+# asm 2: mov <mulr6=%r10,>mulrax=%rax
+mov %r10,%rax
+
+# qhasm: mulr6 = 0
+# asm 1: mov $0,>mulr6=int64#5
+# asm 2: mov $0,>mulr6=%r8
+mov $0,%r8
+
+# qhasm: mulr6 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr6=int64#5
+# asm 2: adc <mulrdx=%rdx,<mulr6=%r8
+adc %rdx,%r8
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr6 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr6=int64#5
+# asm 2: add <mulrax=%rax,<mulr6=%r8
+add %rax,%r8
+
+# qhasm: mulrax = mulr7
+# asm 1: mov <mulr7=int64#9,>mulrax=int64#7
+# asm 2: mov <mulr7=%r11,>mulrax=%rax
+mov %r11,%rax
+
+# qhasm: mulr7 = 0
+# asm 1: mov $0,>mulr7=int64#6
+# asm 2: mov $0,>mulr7=%r9
+mov $0,%r9
+
+# qhasm: mulr7 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr7=int64#6
+# asm 2: adc <mulrdx=%rdx,<mulr7=%r9
+adc %rdx,%r9
+
+# qhasm: (uint128) mulrdx mulrax = mulrax * *(uint64 *)&crypto_sign_ed25519_amd64_64_38
+mulq crypto_sign_ed25519_amd64_64_38(%rip)
+
+# qhasm: carry? mulr7 += mulrax
+# asm 1: add <mulrax=int64#7,<mulr7=int64#6
+# asm 2: add <mulrax=%rax,<mulr7=%r9
+add %rax,%r9
+
+# qhasm: mulr8 = 0
+# asm 1: mov $0,>mulr8=int64#7
+# asm 2: mov $0,>mulr8=%rax
+mov $0,%rax
+
+# qhasm: mulr8 += mulrdx + carry
+# asm 1: adc <mulrdx=int64#3,<mulr8=int64#7
+# asm 2: adc <mulrdx=%rdx,<mulr8=%rax
+adc %rdx,%rax
+
+# qhasm: carry? rt0 += mulr4
+# asm 1: add <mulr4=int64#2,<rt0=int64#11
+# asm 2: add <mulr4=%rsi,<rt0=%r13
+add %rsi,%r13
+
+# qhasm: carry? rt1 += mulr5 + carry
+# asm 1: adc <mulr5=int64#4,<rt1=int64#12
+# asm 2: adc <mulr5=%rcx,<rt1=%r14
+adc %rcx,%r14
+
+# qhasm: carry? rt2 += mulr6 + carry
+# asm 1: adc <mulr6=int64#5,<rt2=int64#13
+# asm 2: adc <mulr6=%r8,<rt2=%r15
+adc %r8,%r15
+
+# qhasm: carry? rt3 += mulr7 + carry
+# asm 1: adc <mulr7=int64#6,<rt3=int64#14
+# asm 2: adc <mulr7=%r9,<rt3=%rbx
+adc %r9,%rbx
+
+# qhasm: mulzero = 0
+# asm 1: mov $0,>mulzero=int64#2
+# asm 2: mov $0,>mulzero=%rsi
+mov $0,%rsi
+
+# qhasm: mulr8 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulr8=int64#7
+# asm 2: adc <mulzero=%rsi,<mulr8=%rax
+adc %rsi,%rax
+
+# qhasm: mulr8 *= 38
+# asm 1: imulq $38,<mulr8=int64#7,>mulr8=int64#3
+# asm 2: imulq $38,<mulr8=%rax,>mulr8=%rdx
+imulq $38,%rax,%rdx
+
+# qhasm: carry? rt0 += mulr8
+# asm 1: add <mulr8=int64#3,<rt0=int64#11
+# asm 2: add <mulr8=%rdx,<rt0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rt1 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt1=int64#12
+# asm 2: adc <mulzero=%rsi,<rt1=%r14
+adc %rsi,%r14
+
+# qhasm: carry? rt2 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt2=int64#13
+# asm 2: adc <mulzero=%rsi,<rt2=%r15
+adc %rsi,%r15
+
+# qhasm: carry? rt3 += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<rt3=int64#14
+# asm 2: adc <mulzero=%rsi,<rt3=%rbx
+adc %rsi,%rbx
+
+# qhasm: mulzero += mulzero + carry
+# asm 1: adc <mulzero=int64#2,<mulzero=int64#2
+# asm 2: adc <mulzero=%rsi,<mulzero=%rsi
+adc %rsi,%rsi
+
+# qhasm: mulzero *= 38
+# asm 1: imulq $38,<mulzero=int64#2,>mulzero=int64#2
+# asm 2: imulq $38,<mulzero=%rsi,>mulzero=%rsi
+imulq $38,%rsi,%rsi
+
+# qhasm: rt0 += mulzero
+# asm 1: add <mulzero=int64#2,<rt0=int64#11
+# asm 2: add <mulzero=%rsi,<rt0=%r13
+add %rsi,%r13
+
+# qhasm: carry? rt0 += rt0
+# asm 1: add <rt0=int64#11,<rt0=int64#11
+# asm 2: add <rt0=%r13,<rt0=%r13
+add %r13,%r13
+
+# qhasm: carry? rt1 += rt1 + carry
+# asm 1: adc <rt1=int64#12,<rt1=int64#12
+# asm 2: adc <rt1=%r14,<rt1=%r14
+adc %r14,%r14
+
+# qhasm: carry? rt2 += rt2 + carry
+# asm 1: adc <rt2=int64#13,<rt2=int64#13
+# asm 2: adc <rt2=%r15,<rt2=%r15
+adc %r15,%r15
+
+# qhasm: carry? rt3 += rt3 + carry
+# asm 1: adc <rt3=int64#14,<rt3=int64#14
+# asm 2: adc <rt3=%rbx,<rt3=%rbx
+adc %rbx,%rbx
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#2
+# asm 2: mov $0,>addt0=%rsi
+mov $0,%rsi
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#3
+# asm 2: mov $38,>addt1=%rdx
+mov $38,%rdx
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#2,<addt1=int64#3
+# asm 2: cmovae <addt0=%rsi,<addt1=%rdx
+cmovae %rsi,%rdx
+
+# qhasm: carry? rt0 += addt1
+# asm 1: add <addt1=int64#3,<rt0=int64#11
+# asm 2: add <addt1=%rdx,<rt0=%r13
+add %rdx,%r13
+
+# qhasm: carry? rt1 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rt1=int64#12
+# asm 2: adc <addt0=%rsi,<rt1=%r14
+adc %rsi,%r14
+
+# qhasm: carry? rt2 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rt2=int64#13
+# asm 2: adc <addt0=%rsi,<rt2=%r15
+adc %rsi,%r15
+
+# qhasm: carry? rt3 += addt0 + carry
+# asm 1: adc <addt0=int64#2,<rt3=int64#14
+# asm 2: adc <addt0=%rsi,<rt3=%rbx
+adc %rsi,%rbx
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#3,<addt0=int64#2
+# asm 2: cmovc <addt1=%rdx,<addt0=%rsi
+cmovc %rdx,%rsi
+
+# qhasm: rt0 += addt0
+# asm 1: add <addt0=int64#2,<rt0=int64#11
+# asm 2: add <addt0=%rsi,<rt0=%r13
+add %rsi,%r13
+
+# qhasm: rz0 = rt0
+# asm 1: mov <rt0=int64#11,>rz0=int64#2
+# asm 2: mov <rt0=%r13,>rz0=%rsi
+mov %r13,%rsi
+
+# qhasm: rz1 = rt1
+# asm 1: mov <rt1=int64#12,>rz1=int64#3
+# asm 2: mov <rt1=%r14,>rz1=%rdx
+mov %r14,%rdx
+
+# qhasm: rz2 = rt2
+# asm 1: mov <rt2=int64#13,>rz2=int64#4
+# asm 2: mov <rt2=%r15,>rz2=%rcx
+mov %r15,%rcx
+
+# qhasm: rz3 = rt3
+# asm 1: mov <rt3=int64#14,>rz3=int64#5
+# asm 2: mov <rt3=%rbx,>rz3=%r8
+mov %rbx,%r8
+
+# qhasm: carry? rz0 += c0_stack
+# asm 1: addq <c0_stack=stack64#8,<rz0=int64#2
+# asm 2: addq <c0_stack=56(%rsp),<rz0=%rsi
+addq 56(%rsp),%rsi
+
+# qhasm: carry? rz1 += c1_stack + carry
+# asm 1: adcq <c1_stack=stack64#9,<rz1=int64#3
+# asm 2: adcq <c1_stack=64(%rsp),<rz1=%rdx
+adcq 64(%rsp),%rdx
+
+# qhasm: carry? rz2 += c2_stack + carry
+# asm 1: adcq <c2_stack=stack64#10,<rz2=int64#4
+# asm 2: adcq <c2_stack=72(%rsp),<rz2=%rcx
+adcq 72(%rsp),%rcx
+
+# qhasm: carry? rz3 += c3_stack + carry
+# asm 1: adcq <c3_stack=stack64#11,<rz3=int64#5
+# asm 2: adcq <c3_stack=80(%rsp),<rz3=%r8
+adcq 80(%rsp),%r8
+
+# qhasm: addt0 = 0
+# asm 1: mov $0,>addt0=int64#6
+# asm 2: mov $0,>addt0=%r9
+mov $0,%r9
+
+# qhasm: addt1 = 38
+# asm 1: mov $38,>addt1=int64#7
+# asm 2: mov $38,>addt1=%rax
+mov $38,%rax
+
+# qhasm: addt1 = addt0 if !carry
+# asm 1: cmovae <addt0=int64#6,<addt1=int64#7
+# asm 2: cmovae <addt0=%r9,<addt1=%rax
+cmovae %r9,%rax
+
+# qhasm: carry? rz0 += addt1
+# asm 1: add <addt1=int64#7,<rz0=int64#2
+# asm 2: add <addt1=%rax,<rz0=%rsi
+add %rax,%rsi
+
+# qhasm: carry? rz1 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<rz1=int64#3
+# asm 2: adc <addt0=%r9,<rz1=%rdx
+adc %r9,%rdx
+
+# qhasm: carry? rz2 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<rz2=int64#4
+# asm 2: adc <addt0=%r9,<rz2=%rcx
+adc %r9,%rcx
+
+# qhasm: carry? rz3 += addt0 + carry
+# asm 1: adc <addt0=int64#6,<rz3=int64#5
+# asm 2: adc <addt0=%r9,<rz3=%r8
+adc %r9,%r8
+
+# qhasm: addt0 = addt1 if carry
+# asm 1: cmovc <addt1=int64#7,<addt0=int64#6
+# asm 2: cmovc <addt1=%rax,<addt0=%r9
+cmovc %rax,%r9
+
+# qhasm: rz0 += addt0
+# asm 1: add <addt0=int64#6,<rz0=int64#2
+# asm 2: add <addt0=%r9,<rz0=%rsi
+add %r9,%rsi
+
+# qhasm: carry? rt0 -= c0_stack
+# asm 1: subq <c0_stack=stack64#8,<rt0=int64#11
+# asm 2: subq <c0_stack=56(%rsp),<rt0=%r13
+subq 56(%rsp),%r13
+
+# qhasm: carry? rt1 -= c1_stack - carry
+# asm 1: sbbq <c1_stack=stack64#9,<rt1=int64#12
+# asm 2: sbbq <c1_stack=64(%rsp),<rt1=%r14
+sbbq 64(%rsp),%r14
+
+# qhasm: carry? rt2 -= c2_stack - carry
+# asm 1: sbbq <c2_stack=stack64#10,<rt2=int64#13
+# asm 2: sbbq <c2_stack=72(%rsp),<rt2=%r15
+sbbq 72(%rsp),%r15
+
+# qhasm: carry? rt3 -= c3_stack - carry
+# asm 1: sbbq <c3_stack=stack64#11,<rt3=int64#14
+# asm 2: sbbq <c3_stack=80(%rsp),<rt3=%rbx
+sbbq 80(%rsp),%rbx
+
+# qhasm: subt0 = 0
+# asm 1: mov $0,>subt0=int64#6
+# asm 2: mov $0,>subt0=%r9
+mov $0,%r9
+
+# qhasm: subt1 = 38
+# asm 1: mov $38,>subt1=int64#7
+# asm 2: mov $38,>subt1=%rax
+mov $38,%rax
+
+# qhasm: subt1 = subt0 if !carry
+# asm 1: cmovae <subt0=int64#6,<subt1=int64#7
+# asm 2: cmovae <subt0=%r9,<subt1=%rax
+cmovae %r9,%rax
+
+# qhasm: carry? rt0 -= subt1
+# asm 1: sub <subt1=int64#7,<rt0=int64#11
+# asm 2: sub <subt1=%rax,<rt0=%r13
+sub %rax,%r13
+
+# qhasm: carry? rt1 -= subt0 - carry
+# asm 1: sbb <subt0=int64#6,<rt1=int64#12
+# asm 2: sbb <subt0=%r9,<rt1=%r14
+sbb %r9,%r14
+
+# qhasm: carry? rt2 -= subt0 - carry
+# asm 1: sbb <subt0=int64#6,<rt2=int64#13
+# asm 2: sbb <subt0=%r9,<rt2=%r15
+sbb %r9,%r15
+
+# qhasm: carry? rt3 -= subt0 - carry
+# asm 1: sbb <subt0=int64#6,<rt3=int64#14
+# asm 2: sbb <subt0=%r9,<rt3=%rbx
+sbb %r9,%rbx
+
+# qhasm: subt0 = subt1 if carry
+# asm 1: cmovc <subt1=int64#7,<subt0=int64#6
+# asm 2: cmovc <subt1=%rax,<subt0=%r9
+cmovc %rax,%r9
+
+# qhasm: rt0 -= subt0
+# asm 1: sub <subt0=int64#6,<rt0=int64#11
+# asm 2: sub <subt0=%r9,<rt0=%r13
+sub %r9,%r13
+
+# qhasm: *(uint64 *)(rp + 32) = rz0
+# asm 1: movq <rz0=int64#2,32(<rp=int64#1)
+# asm 2: movq <rz0=%rsi,32(<rp=%rdi)
+movq %rsi,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = rz1
+# asm 1: movq <rz1=int64#3,40(<rp=int64#1)
+# asm 2: movq <rz1=%rdx,40(<rp=%rdi)
+movq %rdx,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = rz2
+# asm 1: movq <rz2=int64#4,48(<rp=int64#1)
+# asm 2: movq <rz2=%rcx,48(<rp=%rdi)
+movq %rcx,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = rz3
+# asm 1: movq <rz3=int64#5,56(<rp=int64#1)
+# asm 2: movq <rz3=%r8,56(<rp=%rdi)
+movq %r8,56(%rdi)
+
+# qhasm: *(uint64 *)(rp + 96) = rt0
+# asm 1: movq <rt0=int64#11,96(<rp=int64#1)
+# asm 2: movq <rt0=%r13,96(<rp=%rdi)
+movq %r13,96(%rdi)
+
+# qhasm: *(uint64 *)(rp + 104) = rt1
+# asm 1: movq <rt1=int64#12,104(<rp=int64#1)
+# asm 2: movq <rt1=%r14,104(<rp=%rdi)
+movq %r14,104(%rdi)
+
+# qhasm: *(uint64 *)(rp + 112) = rt2
+# asm 1: movq <rt2=int64#13,112(<rp=int64#1)
+# asm 2: movq <rt2=%r15,112(<rp=%rdi)
+movq %r15,112(%rdi)
+
+# qhasm: *(uint64 *)(rp + 120) = rt3
+# asm 1: movq <rt3=int64#14,120(<rp=int64#1)
+# asm 2: movq <rt3=%rbx,120(<rp=%rdi)
+movq %rbx,120(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/ge25519_scalarmult_base.c b/ext/ed25519-amd64-asm/ge25519_scalarmult_base.c
new file mode 100644
index 00000000..986abaf6
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_scalarmult_base.c
@@ -0,0 +1,68 @@
+#include "fe25519.h"
+#include "sc25519.h"
+#include "ge25519.h"
+
+/* Multiples of the base point in Niels' representation */
+static const ge25519_niels ge25519_base_multiples_niels[] = {
+#ifdef SMALLTABLES
+#include "ge25519_base_niels_smalltables.data"
+#else
+#include "ge25519_base_niels.data"
+#endif
+};
+
+/* d */
+static const fe25519 ecd = {{0x75EB4DCA135978A3, 0x00700A4D4141D8AB, 0x8CC740797779E898, 0x52036CEE2B6FFE73}};
+
+void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s)
+{
+ signed char b[64];
+ int i;
+ ge25519_niels t;
+ fe25519 d;
+
+ sc25519_window4(b,s);
+
+#ifdef SMALLTABLES
+ ge25519_p1p1 tp1p1;
+ choose_t((ge25519_niels *)r, 0, (signed long long) b[1], ge25519_base_multiples_niels);
+ fe25519_sub(&d, &r->y, &r->x);
+ fe25519_add(&r->y, &r->y, &r->x);
+ r->x = d;
+ r->t = r->z;
+ fe25519_setint(&r->z,2);
+ for(i=3;i<64;i+=2)
+ {
+ choose_t(&t, (unsigned long long) i/2, (signed long long) b[i], ge25519_base_multiples_niels);
+ ge25519_nielsadd2(r, &t);
+ }
+ ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r);
+ ge25519_p1p1_to_p2((ge25519_p2 *)r, &tp1p1);
+ ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r);
+ ge25519_p1p1_to_p2((ge25519_p2 *)r, &tp1p1);
+ ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r);
+ ge25519_p1p1_to_p2((ge25519_p2 *)r, &tp1p1);
+ ge25519_dbl_p1p1(&tp1p1,(ge25519_p2 *)r);
+ ge25519_p1p1_to_p3(r, &tp1p1);
+ choose_t(&t, (unsigned long long) 0, (signed long long) b[0], ge25519_base_multiples_niels);
+ fe25519_mul(&t.t2d, &t.t2d, &ecd);
+ ge25519_nielsadd2(r, &t);
+ for(i=2;i<64;i+=2)
+ {
+ choose_t(&t, (unsigned long long) i/2, (signed long long) b[i], ge25519_base_multiples_niels);
+ ge25519_nielsadd2(r, &t);
+ }
+#else
+ choose_t((ge25519_niels *)r, 0, (signed long long) b[0], ge25519_base_multiples_niels);
+ fe25519_sub(&d, &r->y, &r->x);
+ fe25519_add(&r->y, &r->y, &r->x);
+ r->x = d;
+ r->t = r->z;
+ fe25519_setint(&r->z,2);
+ for(i=1;i<64;i++)
+ {
+ choose_t(&t, (unsigned long long) i, (signed long long) b[i], ge25519_base_multiples_niels);
+ ge25519_nielsadd2(r, &t);
+ }
+#endif
+}
diff --git a/ext/ed25519-amd64-asm/ge25519_unpackneg.c b/ext/ed25519-amd64-asm/ge25519_unpackneg.c
new file mode 100644
index 00000000..ff16fd20
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ge25519_unpackneg.c
@@ -0,0 +1,60 @@
+#include "fe25519.h"
+#include "ge25519.h"
+
+/* d */
+static const fe25519 ecd = {{0x75EB4DCA135978A3, 0x00700A4D4141D8AB, 0x8CC740797779E898, 0x52036CEE2B6FFE73}};
+/* sqrt(-1) */
+static const fe25519 sqrtm1 = {{0xC4EE1B274A0EA0B0, 0x2F431806AD2FE478, 0x2B4D00993DFBD7A7, 0x2B8324804FC1DF0B}};
+
+/* return 0 on success, -1 otherwise */
+int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32])
+{
+ fe25519 t, chk, num, den, den2, den4, den6;
+ unsigned char par = p[31] >> 7;
+
+ fe25519_setint(&r->z,1);
+ fe25519_unpack(&r->y, p);
+ fe25519_square(&num, &r->y); /* x = y^2 */
+ fe25519_mul(&den, &num, &ecd); /* den = dy^2 */
+ fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */
+ fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */
+
+ /* Computation of sqrt(num/den)
+ 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8)
+ */
+ fe25519_square(&den2, &den);
+ fe25519_square(&den4, &den2);
+ fe25519_mul(&den6, &den4, &den2);
+ fe25519_mul(&t, &den6, &num);
+ fe25519_mul(&t, &t, &den);
+
+ fe25519_pow2523(&t, &t);
+ /* 2. computation of r->x = t * num * den^3
+ */
+ fe25519_mul(&t, &t, &num);
+ fe25519_mul(&t, &t, &den);
+ fe25519_mul(&t, &t, &den);
+ fe25519_mul(&r->x, &t, &den);
+
+ /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not:
+ */
+ fe25519_square(&chk, &r->x);
+ fe25519_mul(&chk, &chk, &den);
+ if (!fe25519_iseq_vartime(&chk, &num))
+ fe25519_mul(&r->x, &r->x, &sqrtm1);
+
+ /* 4. Now we have one of the two square roots, except if input was not a square
+ */
+ fe25519_square(&chk, &r->x);
+ fe25519_mul(&chk, &chk, &den);
+ if (!fe25519_iseq_vartime(&chk, &num))
+ return -1;
+
+ /* 5. Choose the desired square root according to parity:
+ */
+ if(fe25519_getparity(&r->x) != (1-par))
+ fe25519_neg(&r->x, &r->x);
+
+ fe25519_mul(&r->t, &r->x, &r->y);
+ return 0;
+}
diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced.s b/ext/ed25519-amd64-asm/heap_rootreplaced.s
new file mode 100644
index 00000000..8fe385b4
--- /dev/null
+++ b/ext/ed25519-amd64-asm/heap_rootreplaced.s
@@ -0,0 +1,476 @@
+
+# qhasm: int64 hp
+
+# qhasm: int64 hlen
+
+# qhasm: int64 sp
+
+# qhasm: int64 pp
+
+# qhasm: input hp
+
+# qhasm: input hlen
+
+# qhasm: input sp
+
+# qhasm: int64 prc
+
+# qhasm: int64 plc
+
+# qhasm: int64 pc
+
+# qhasm: int64 d
+
+# qhasm: int64 spp
+
+# qhasm: int64 sprc
+
+# qhasm: int64 spc
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 p0
+
+# qhasm: int64 p1
+
+# qhasm: int64 p2
+
+# qhasm: int64 p3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced
+.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced
+_crypto_sign_ed25519_amd64_64_heap_rootreplaced:
+crypto_sign_ed25519_amd64_64_heap_rootreplaced:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: pp = 0
+# asm 1: mov $0,>pp=int64#4
+# asm 2: mov $0,>pp=%rcx
+mov $0,%rcx
+
+# qhasm: siftdownloop:
+._siftdownloop:
+
+# qhasm: prc = pp
+# asm 1: mov <pp=int64#4,>prc=int64#5
+# asm 2: mov <pp=%rcx,>prc=%r8
+mov %rcx,%r8
+
+# qhasm: prc *= 2
+# asm 1: imulq $2,<prc=int64#5,>prc=int64#5
+# asm 2: imulq $2,<prc=%r8,>prc=%r8
+imulq $2,%r8,%r8
+
+# qhasm: pc = prc
+# asm 1: mov <prc=int64#5,>pc=int64#6
+# asm 2: mov <prc=%r8,>pc=%r9
+mov %r8,%r9
+
+# qhasm: prc += 2
+# asm 1: add $2,<prc=int64#5
+# asm 2: add $2,<prc=%r8
+add $2,%r8
+
+# qhasm: pc += 1
+# asm 1: add $1,<pc=int64#6
+# asm 2: add $1,<pc=%r9
+add $1,%r9
+
+# qhasm: unsigned>? hlen - prc
+# asm 1: cmp <prc=int64#5,<hlen=int64#2
+# asm 2: cmp <prc=%r8,<hlen=%rsi
+cmp %r8,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop if !unsigned>
+jbe ._siftuploop
+
+# qhasm: sprc = *(uint64 *)(hp + prc * 8)
+# asm 1: movq (<hp=int64#1,<prc=int64#5,8),>sprc=int64#7
+# asm 2: movq (<hp=%rdi,<prc=%r8,8),>sprc=%rax
+movq (%rdi,%r8,8),%rax
+
+# qhasm: sprc <<= 5
+# asm 1: shl $5,<sprc=int64#7
+# asm 2: shl $5,<sprc=%rax
+shl $5,%rax
+
+# qhasm: sprc += sp
+# asm 1: add <sp=int64#3,<sprc=int64#7
+# asm 2: add <sp=%rdx,<sprc=%rax
+add %rdx,%rax
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#6,8),>spc=int64#8
+# asm 2: movq (<hp=%rdi,<pc=%r9,8),>spc=%r10
+movq (%rdi,%r9,8),%r10
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#8
+# asm 2: shl $5,<spc=%r10
+shl $5,%r10
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#8
+# asm 2: add <sp=%rdx,<spc=%r10
+add %rdx,%r10
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#8),>c0=int64#9
+# asm 2: movq 0(<spc=%r10),>c0=%r11
+movq 0(%r10),%r11
+
+# qhasm: c1 = *(uint64 *)(spc + 8)
+# asm 1: movq 8(<spc=int64#8),>c1=int64#10
+# asm 2: movq 8(<spc=%r10),>c1=%r12
+movq 8(%r10),%r12
+
+# qhasm: c2 = *(uint64 *)(spc + 16)
+# asm 1: movq 16(<spc=int64#8),>c2=int64#11
+# asm 2: movq 16(<spc=%r10),>c2=%r13
+movq 16(%r10),%r13
+
+# qhasm: c3 = *(uint64 *)(spc + 24)
+# asm 1: movq 24(<spc=int64#8),>c3=int64#12
+# asm 2: movq 24(<spc=%r10),>c3=%r14
+movq 24(%r10),%r14
+
+# qhasm: carry? c0 -= *(uint64 *)(sprc + 0)
+# asm 1: subq 0(<sprc=int64#7),<c0=int64#9
+# asm 2: subq 0(<sprc=%rax),<c0=%r11
+subq 0(%rax),%r11
+
+# qhasm: carry? c1 -= *(uint64 *)(sprc + 8) - carry
+# asm 1: sbbq 8(<sprc=int64#7),<c1=int64#10
+# asm 2: sbbq 8(<sprc=%rax),<c1=%r12
+sbbq 8(%rax),%r12
+
+# qhasm: carry? c2 -= *(uint64 *)(sprc + 16) - carry
+# asm 1: sbbq 16(<sprc=int64#7),<c2=int64#11
+# asm 2: sbbq 16(<sprc=%rax),<c2=%r13
+sbbq 16(%rax),%r13
+
+# qhasm: carry? c3 -= *(uint64 *)(sprc + 24) - carry
+# asm 1: sbbq 24(<sprc=int64#7),<c3=int64#12
+# asm 2: sbbq 24(<sprc=%rax),<c3=%r14
+sbbq 24(%rax),%r14
+
+# qhasm: pc = prc if carry
+# asm 1: cmovc <prc=int64#5,<pc=int64#6
+# asm 2: cmovc <prc=%r8,<pc=%r9
+cmovc %r8,%r9
+
+# qhasm: spc = sprc if carry
+# asm 1: cmovc <sprc=int64#7,<spc=int64#8
+# asm 2: cmovc <sprc=%rax,<spc=%r10
+cmovc %rax,%r10
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#8
+# asm 2: sub <sp=%rdx,<spc=%r10
+sub %rdx,%r10
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#8
+# asm 2: shr $5,<spc=%r10
+shr $5,%r10
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#8,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r10,(<hp=%rdi,<pp=%rcx,8)
+movq %r10,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#6,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%r9,8)
+movq %r8,(%rdi,%r9,8)
+
+# qhasm: pp = pc
+# asm 1: mov <pc=int64#6,>pp=int64#4
+# asm 2: mov <pc=%r9,>pp=%rcx
+mov %r9,%rcx
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftdownloop
+jmp ._siftdownloop
+
+# qhasm: siftuploop:
+._siftuploop:
+
+# qhasm: pc = pp
+# asm 1: mov <pp=int64#4,>pc=int64#2
+# asm 2: mov <pp=%rcx,>pc=%rsi
+mov %rcx,%rsi
+
+# qhasm: pp -= 1
+# asm 1: sub $1,<pp=int64#4
+# asm 2: sub $1,<pp=%rcx
+sub $1,%rcx
+
+# qhasm: (uint64) pp >>= 1
+# asm 1: shr $1,<pp=int64#4
+# asm 2: shr $1,<pp=%rcx
+shr $1,%rcx
+
+# qhasm: unsigned>? pc - 0
+# asm 1: cmp $0,<pc=int64#2
+# asm 2: cmp $0,<pc=%rsi
+cmp $0,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if !unsigned>
+jbe ._end
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#2,8),>spc=int64#6
+# asm 2: movq (<hp=%rdi,<pc=%rsi,8),>spc=%r9
+movq (%rdi,%rsi,8),%r9
+
+# qhasm: spp <<= 5
+# asm 1: shl $5,<spp=int64#5
+# asm 2: shl $5,<spp=%r8
+shl $5,%r8
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#6
+# asm 2: shl $5,<spc=%r9
+shl $5,%r9
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#6
+# asm 2: add <sp=%rdx,<spc=%r9
+add %rdx,%r9
+
+# qhasm: spp += sp
+# asm 1: add <sp=int64#3,<spp=int64#5
+# asm 2: add <sp=%rdx,<spp=%r8
+add %rdx,%r8
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#6),>c0=int64#7
+# asm 2: movq 0(<spc=%r9),>c0=%rax
+movq 0(%r9),%rax
+
+# qhasm: c1 = *(uint64 *)(spc + 8)
+# asm 1: movq 8(<spc=int64#6),>c1=int64#8
+# asm 2: movq 8(<spc=%r9),>c1=%r10
+movq 8(%r9),%r10
+
+# qhasm: c2 = *(uint64 *)(spc + 16)
+# asm 1: movq 16(<spc=int64#6),>c2=int64#9
+# asm 2: movq 16(<spc=%r9),>c2=%r11
+movq 16(%r9),%r11
+
+# qhasm: c3 = *(uint64 *)(spc + 24)
+# asm 1: movq 24(<spc=int64#6),>c3=int64#10
+# asm 2: movq 24(<spc=%r9),>c3=%r12
+movq 24(%r9),%r12
+
+# qhasm: carry? c0 -= *(uint64 *)(spp + 0)
+# asm 1: subq 0(<spp=int64#5),<c0=int64#7
+# asm 2: subq 0(<spp=%r8),<c0=%rax
+subq 0(%r8),%rax
+
+# qhasm: carry? c1 -= *(uint64 *)(spp + 8) - carry
+# asm 1: sbbq 8(<spp=int64#5),<c1=int64#8
+# asm 2: sbbq 8(<spp=%r8),<c1=%r10
+sbbq 8(%r8),%r10
+
+# qhasm: carry? c2 -= *(uint64 *)(spp + 16) - carry
+# asm 1: sbbq 16(<spp=int64#5),<c2=int64#9
+# asm 2: sbbq 16(<spp=%r8),<c2=%r11
+sbbq 16(%r8),%r11
+
+# qhasm: carry? c3 -= *(uint64 *)(spp + 24) - carry
+# asm 1: sbbq 24(<spp=int64#5),<c3=int64#10
+# asm 2: sbbq 24(<spp=%r8),<c3=%r12
+sbbq 24(%r8),%r12
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if carry
+jc ._end
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#6
+# asm 2: sub <sp=%rdx,<spc=%r9
+sub %rdx,%r9
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#6
+# asm 2: shr $5,<spc=%r9
+shr $5,%r9
+
+# qhasm: spp -= sp
+# asm 1: sub <sp=int64#3,<spp=int64#5
+# asm 2: sub <sp=%rdx,<spp=%r8
+sub %rdx,%r8
+
+# qhasm: (uint64) spp >>= 5
+# asm 1: shr $5,<spp=int64#5
+# asm 2: shr $5,<spp=%r8
+shr $5,%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#6,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r9,(<hp=%rdi,<pp=%rcx,8)
+movq %r9,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#2,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%rsi,8)
+movq %r8,(%rdi,%rsi,8)
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop
+jmp ._siftuploop
+
+# qhasm: end:
+._end:
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s b/ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s
new file mode 100644
index 00000000..488e9c52
--- /dev/null
+++ b/ext/ed25519-amd64-asm/heap_rootreplaced_1limb.s
@@ -0,0 +1,416 @@
+
+# qhasm: int64 hp
+
+# qhasm: int64 hlen
+
+# qhasm: int64 sp
+
+# qhasm: int64 pp
+
+# qhasm: input hp
+
+# qhasm: input hlen
+
+# qhasm: input sp
+
+# qhasm: int64 prc
+
+# qhasm: int64 plc
+
+# qhasm: int64 pc
+
+# qhasm: int64 d
+
+# qhasm: int64 spp
+
+# qhasm: int64 sprc
+
+# qhasm: int64 spc
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 p0
+
+# qhasm: int64 p1
+
+# qhasm: int64 p2
+
+# qhasm: int64 p3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb
+.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb
+_crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb:
+crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: pp = 0
+# asm 1: mov $0,>pp=int64#4
+# asm 2: mov $0,>pp=%rcx
+mov $0,%rcx
+
+# qhasm: siftdownloop:
+._siftdownloop:
+
+# qhasm: prc = pp
+# asm 1: mov <pp=int64#4,>prc=int64#5
+# asm 2: mov <pp=%rcx,>prc=%r8
+mov %rcx,%r8
+
+# qhasm: prc *= 2
+# asm 1: imulq $2,<prc=int64#5,>prc=int64#5
+# asm 2: imulq $2,<prc=%r8,>prc=%r8
+imulq $2,%r8,%r8
+
+# qhasm: pc = prc
+# asm 1: mov <prc=int64#5,>pc=int64#6
+# asm 2: mov <prc=%r8,>pc=%r9
+mov %r8,%r9
+
+# qhasm: prc += 2
+# asm 1: add $2,<prc=int64#5
+# asm 2: add $2,<prc=%r8
+add $2,%r8
+
+# qhasm: pc += 1
+# asm 1: add $1,<pc=int64#6
+# asm 2: add $1,<pc=%r9
+add $1,%r9
+
+# qhasm: unsigned>? hlen - prc
+# asm 1: cmp <prc=int64#5,<hlen=int64#2
+# asm 2: cmp <prc=%r8,<hlen=%rsi
+cmp %r8,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop if !unsigned>
+jbe ._siftuploop
+
+# qhasm: sprc = *(uint64 *)(hp + prc * 8)
+# asm 1: movq (<hp=int64#1,<prc=int64#5,8),>sprc=int64#7
+# asm 2: movq (<hp=%rdi,<prc=%r8,8),>sprc=%rax
+movq (%rdi,%r8,8),%rax
+
+# qhasm: sprc <<= 5
+# asm 1: shl $5,<sprc=int64#7
+# asm 2: shl $5,<sprc=%rax
+shl $5,%rax
+
+# qhasm: sprc += sp
+# asm 1: add <sp=int64#3,<sprc=int64#7
+# asm 2: add <sp=%rdx,<sprc=%rax
+add %rdx,%rax
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#6,8),>spc=int64#8
+# asm 2: movq (<hp=%rdi,<pc=%r9,8),>spc=%r10
+movq (%rdi,%r9,8),%r10
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#8
+# asm 2: shl $5,<spc=%r10
+shl $5,%r10
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#8
+# asm 2: add <sp=%rdx,<spc=%r10
+add %rdx,%r10
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#8),>c0=int64#9
+# asm 2: movq 0(<spc=%r10),>c0=%r11
+movq 0(%r10),%r11
+
+# qhasm: carry? c0 -= *(uint64 *)(sprc + 0)
+# asm 1: subq 0(<sprc=int64#7),<c0=int64#9
+# asm 2: subq 0(<sprc=%rax),<c0=%r11
+subq 0(%rax),%r11
+
+# qhasm: pc = prc if carry
+# asm 1: cmovc <prc=int64#5,<pc=int64#6
+# asm 2: cmovc <prc=%r8,<pc=%r9
+cmovc %r8,%r9
+
+# qhasm: spc = sprc if carry
+# asm 1: cmovc <sprc=int64#7,<spc=int64#8
+# asm 2: cmovc <sprc=%rax,<spc=%r10
+cmovc %rax,%r10
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#8
+# asm 2: sub <sp=%rdx,<spc=%r10
+sub %rdx,%r10
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#8
+# asm 2: shr $5,<spc=%r10
+shr $5,%r10
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#8,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r10,(<hp=%rdi,<pp=%rcx,8)
+movq %r10,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#6,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%r9,8)
+movq %r8,(%rdi,%r9,8)
+
+# qhasm: pp = pc
+# asm 1: mov <pc=int64#6,>pp=int64#4
+# asm 2: mov <pc=%r9,>pp=%rcx
+mov %r9,%rcx
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftdownloop
+jmp ._siftdownloop
+
+# qhasm: siftuploop:
+._siftuploop:
+
+# qhasm: pc = pp
+# asm 1: mov <pp=int64#4,>pc=int64#2
+# asm 2: mov <pp=%rcx,>pc=%rsi
+mov %rcx,%rsi
+
+# qhasm: pp -= 1
+# asm 1: sub $1,<pp=int64#4
+# asm 2: sub $1,<pp=%rcx
+sub $1,%rcx
+
+# qhasm: (uint64) pp >>= 1
+# asm 1: shr $1,<pp=int64#4
+# asm 2: shr $1,<pp=%rcx
+shr $1,%rcx
+
+# qhasm: unsigned>? pc - 0
+# asm 1: cmp $0,<pc=int64#2
+# asm 2: cmp $0,<pc=%rsi
+cmp $0,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if !unsigned>
+jbe ._end
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#2,8),>spc=int64#6
+# asm 2: movq (<hp=%rdi,<pc=%rsi,8),>spc=%r9
+movq (%rdi,%rsi,8),%r9
+
+# qhasm: spp <<= 5
+# asm 1: shl $5,<spp=int64#5
+# asm 2: shl $5,<spp=%r8
+shl $5,%r8
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#6
+# asm 2: shl $5,<spc=%r9
+shl $5,%r9
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#6
+# asm 2: add <sp=%rdx,<spc=%r9
+add %rdx,%r9
+
+# qhasm: spp += sp
+# asm 1: add <sp=int64#3,<spp=int64#5
+# asm 2: add <sp=%rdx,<spp=%r8
+add %rdx,%r8
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#6),>c0=int64#7
+# asm 2: movq 0(<spc=%r9),>c0=%rax
+movq 0(%r9),%rax
+
+# qhasm: carry? c0 -= *(uint64 *)(spp + 0)
+# asm 1: subq 0(<spp=int64#5),<c0=int64#7
+# asm 2: subq 0(<spp=%r8),<c0=%rax
+subq 0(%r8),%rax
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if carry
+jc ._end
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#6
+# asm 2: sub <sp=%rdx,<spc=%r9
+sub %rdx,%r9
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#6
+# asm 2: shr $5,<spc=%r9
+shr $5,%r9
+
+# qhasm: spp -= sp
+# asm 1: sub <sp=int64#3,<spp=int64#5
+# asm 2: sub <sp=%rdx,<spp=%r8
+sub %rdx,%r8
+
+# qhasm: (uint64) spp >>= 5
+# asm 1: shr $5,<spp=int64#5
+# asm 2: shr $5,<spp=%r8
+shr $5,%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#6,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r9,(<hp=%rdi,<pp=%rcx,8)
+movq %r9,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#2,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%rsi,8)
+movq %r8,(%rdi,%rsi,8)
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop
+jmp ._siftuploop
+
+# qhasm: end:
+._end:
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s b/ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s
new file mode 100644
index 00000000..f9259184
--- /dev/null
+++ b/ext/ed25519-amd64-asm/heap_rootreplaced_2limbs.s
@@ -0,0 +1,436 @@
+
+# qhasm: int64 hp
+
+# qhasm: int64 hlen
+
+# qhasm: int64 sp
+
+# qhasm: int64 pp
+
+# qhasm: input hp
+
+# qhasm: input hlen
+
+# qhasm: input sp
+
+# qhasm: int64 prc
+
+# qhasm: int64 plc
+
+# qhasm: int64 pc
+
+# qhasm: int64 d
+
+# qhasm: int64 spp
+
+# qhasm: int64 sprc
+
+# qhasm: int64 spc
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 p0
+
+# qhasm: int64 p1
+
+# qhasm: int64 p2
+
+# qhasm: int64 p3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs
+.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs
+_crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs:
+crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: pp = 0
+# asm 1: mov $0,>pp=int64#4
+# asm 2: mov $0,>pp=%rcx
+mov $0,%rcx
+
+# qhasm: siftdownloop:
+._siftdownloop:
+
+# qhasm: prc = pp
+# asm 1: mov <pp=int64#4,>prc=int64#5
+# asm 2: mov <pp=%rcx,>prc=%r8
+mov %rcx,%r8
+
+# qhasm: prc *= 2
+# asm 1: imulq $2,<prc=int64#5,>prc=int64#5
+# asm 2: imulq $2,<prc=%r8,>prc=%r8
+imulq $2,%r8,%r8
+
+# qhasm: pc = prc
+# asm 1: mov <prc=int64#5,>pc=int64#6
+# asm 2: mov <prc=%r8,>pc=%r9
+mov %r8,%r9
+
+# qhasm: prc += 2
+# asm 1: add $2,<prc=int64#5
+# asm 2: add $2,<prc=%r8
+add $2,%r8
+
+# qhasm: pc += 1
+# asm 1: add $1,<pc=int64#6
+# asm 2: add $1,<pc=%r9
+add $1,%r9
+
+# qhasm: unsigned>? hlen - prc
+# asm 1: cmp <prc=int64#5,<hlen=int64#2
+# asm 2: cmp <prc=%r8,<hlen=%rsi
+cmp %r8,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop if !unsigned>
+jbe ._siftuploop
+
+# qhasm: sprc = *(uint64 *)(hp + prc * 8)
+# asm 1: movq (<hp=int64#1,<prc=int64#5,8),>sprc=int64#7
+# asm 2: movq (<hp=%rdi,<prc=%r8,8),>sprc=%rax
+movq (%rdi,%r8,8),%rax
+
+# qhasm: sprc <<= 5
+# asm 1: shl $5,<sprc=int64#7
+# asm 2: shl $5,<sprc=%rax
+shl $5,%rax
+
+# qhasm: sprc += sp
+# asm 1: add <sp=int64#3,<sprc=int64#7
+# asm 2: add <sp=%rdx,<sprc=%rax
+add %rdx,%rax
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#6,8),>spc=int64#8
+# asm 2: movq (<hp=%rdi,<pc=%r9,8),>spc=%r10
+movq (%rdi,%r9,8),%r10
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#8
+# asm 2: shl $5,<spc=%r10
+shl $5,%r10
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#8
+# asm 2: add <sp=%rdx,<spc=%r10
+add %rdx,%r10
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#8),>c0=int64#9
+# asm 2: movq 0(<spc=%r10),>c0=%r11
+movq 0(%r10),%r11
+
+# qhasm: c1 = *(uint64 *)(spc + 8)
+# asm 1: movq 8(<spc=int64#8),>c1=int64#10
+# asm 2: movq 8(<spc=%r10),>c1=%r12
+movq 8(%r10),%r12
+
+# qhasm: carry? c0 -= *(uint64 *)(sprc + 0)
+# asm 1: subq 0(<sprc=int64#7),<c0=int64#9
+# asm 2: subq 0(<sprc=%rax),<c0=%r11
+subq 0(%rax),%r11
+
+# qhasm: carry? c1 -= *(uint64 *)(sprc + 8) - carry
+# asm 1: sbbq 8(<sprc=int64#7),<c1=int64#10
+# asm 2: sbbq 8(<sprc=%rax),<c1=%r12
+sbbq 8(%rax),%r12
+
+# qhasm: pc = prc if carry
+# asm 1: cmovc <prc=int64#5,<pc=int64#6
+# asm 2: cmovc <prc=%r8,<pc=%r9
+cmovc %r8,%r9
+
+# qhasm: spc = sprc if carry
+# asm 1: cmovc <sprc=int64#7,<spc=int64#8
+# asm 2: cmovc <sprc=%rax,<spc=%r10
+cmovc %rax,%r10
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#8
+# asm 2: sub <sp=%rdx,<spc=%r10
+sub %rdx,%r10
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#8
+# asm 2: shr $5,<spc=%r10
+shr $5,%r10
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#8,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r10,(<hp=%rdi,<pp=%rcx,8)
+movq %r10,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#6,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%r9,8)
+movq %r8,(%rdi,%r9,8)
+
+# qhasm: pp = pc
+# asm 1: mov <pc=int64#6,>pp=int64#4
+# asm 2: mov <pc=%r9,>pp=%rcx
+mov %r9,%rcx
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftdownloop
+jmp ._siftdownloop
+
+# qhasm: siftuploop:
+._siftuploop:
+
+# qhasm: pc = pp
+# asm 1: mov <pp=int64#4,>pc=int64#2
+# asm 2: mov <pp=%rcx,>pc=%rsi
+mov %rcx,%rsi
+
+# qhasm: pp -= 1
+# asm 1: sub $1,<pp=int64#4
+# asm 2: sub $1,<pp=%rcx
+sub $1,%rcx
+
+# qhasm: (uint64) pp >>= 1
+# asm 1: shr $1,<pp=int64#4
+# asm 2: shr $1,<pp=%rcx
+shr $1,%rcx
+
+# qhasm: unsigned>? pc - 0
+# asm 1: cmp $0,<pc=int64#2
+# asm 2: cmp $0,<pc=%rsi
+cmp $0,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if !unsigned>
+jbe ._end
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#2,8),>spc=int64#6
+# asm 2: movq (<hp=%rdi,<pc=%rsi,8),>spc=%r9
+movq (%rdi,%rsi,8),%r9
+
+# qhasm: spp <<= 5
+# asm 1: shl $5,<spp=int64#5
+# asm 2: shl $5,<spp=%r8
+shl $5,%r8
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#6
+# asm 2: shl $5,<spc=%r9
+shl $5,%r9
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#6
+# asm 2: add <sp=%rdx,<spc=%r9
+add %rdx,%r9
+
+# qhasm: spp += sp
+# asm 1: add <sp=int64#3,<spp=int64#5
+# asm 2: add <sp=%rdx,<spp=%r8
+add %rdx,%r8
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#6),>c0=int64#7
+# asm 2: movq 0(<spc=%r9),>c0=%rax
+movq 0(%r9),%rax
+
+# qhasm: c1 = *(uint64 *)(spc + 8)
+# asm 1: movq 8(<spc=int64#6),>c1=int64#8
+# asm 2: movq 8(<spc=%r9),>c1=%r10
+movq 8(%r9),%r10
+
+# qhasm: carry? c0 -= *(uint64 *)(spp + 0)
+# asm 1: subq 0(<spp=int64#5),<c0=int64#7
+# asm 2: subq 0(<spp=%r8),<c0=%rax
+subq 0(%r8),%rax
+
+# qhasm: carry? c1 -= *(uint64 *)(spp + 8) - carry
+# asm 1: sbbq 8(<spp=int64#5),<c1=int64#8
+# asm 2: sbbq 8(<spp=%r8),<c1=%r10
+sbbq 8(%r8),%r10
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if carry
+jc ._end
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#6
+# asm 2: sub <sp=%rdx,<spc=%r9
+sub %rdx,%r9
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#6
+# asm 2: shr $5,<spc=%r9
+shr $5,%r9
+
+# qhasm: spp -= sp
+# asm 1: sub <sp=int64#3,<spp=int64#5
+# asm 2: sub <sp=%rdx,<spp=%r8
+sub %rdx,%r8
+
+# qhasm: (uint64) spp >>= 5
+# asm 1: shr $5,<spp=int64#5
+# asm 2: shr $5,<spp=%r8
+shr $5,%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#6,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r9,(<hp=%rdi,<pp=%rcx,8)
+movq %r9,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#2,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%rsi,8)
+movq %r8,(%rdi,%rsi,8)
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop
+jmp ._siftuploop
+
+# qhasm: end:
+._end:
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s b/ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s
new file mode 100644
index 00000000..dcf890ea
--- /dev/null
+++ b/ext/ed25519-amd64-asm/heap_rootreplaced_3limbs.s
@@ -0,0 +1,456 @@
+
+# qhasm: int64 hp
+
+# qhasm: int64 hlen
+
+# qhasm: int64 sp
+
+# qhasm: int64 pp
+
+# qhasm: input hp
+
+# qhasm: input hlen
+
+# qhasm: input sp
+
+# qhasm: int64 prc
+
+# qhasm: int64 plc
+
+# qhasm: int64 pc
+
+# qhasm: int64 d
+
+# qhasm: int64 spp
+
+# qhasm: int64 sprc
+
+# qhasm: int64 spc
+
+# qhasm: int64 c0
+
+# qhasm: int64 c1
+
+# qhasm: int64 c2
+
+# qhasm: int64 c3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 p0
+
+# qhasm: int64 p1
+
+# qhasm: int64 p2
+
+# qhasm: int64 p3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs
+.globl crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs
+_crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs:
+crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: pp = 0
+# asm 1: mov $0,>pp=int64#4
+# asm 2: mov $0,>pp=%rcx
+mov $0,%rcx
+
+# qhasm: siftdownloop:
+._siftdownloop:
+
+# qhasm: prc = pp
+# asm 1: mov <pp=int64#4,>prc=int64#5
+# asm 2: mov <pp=%rcx,>prc=%r8
+mov %rcx,%r8
+
+# qhasm: prc *= 2
+# asm 1: imulq $2,<prc=int64#5,>prc=int64#5
+# asm 2: imulq $2,<prc=%r8,>prc=%r8
+imulq $2,%r8,%r8
+
+# qhasm: pc = prc
+# asm 1: mov <prc=int64#5,>pc=int64#6
+# asm 2: mov <prc=%r8,>pc=%r9
+mov %r8,%r9
+
+# qhasm: prc += 2
+# asm 1: add $2,<prc=int64#5
+# asm 2: add $2,<prc=%r8
+add $2,%r8
+
+# qhasm: pc += 1
+# asm 1: add $1,<pc=int64#6
+# asm 2: add $1,<pc=%r9
+add $1,%r9
+
+# qhasm: unsigned>? hlen - prc
+# asm 1: cmp <prc=int64#5,<hlen=int64#2
+# asm 2: cmp <prc=%r8,<hlen=%rsi
+cmp %r8,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop if !unsigned>
+jbe ._siftuploop
+
+# qhasm: sprc = *(uint64 *)(hp + prc * 8)
+# asm 1: movq (<hp=int64#1,<prc=int64#5,8),>sprc=int64#7
+# asm 2: movq (<hp=%rdi,<prc=%r8,8),>sprc=%rax
+movq (%rdi,%r8,8),%rax
+
+# qhasm: sprc <<= 5
+# asm 1: shl $5,<sprc=int64#7
+# asm 2: shl $5,<sprc=%rax
+shl $5,%rax
+
+# qhasm: sprc += sp
+# asm 1: add <sp=int64#3,<sprc=int64#7
+# asm 2: add <sp=%rdx,<sprc=%rax
+add %rdx,%rax
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#6,8),>spc=int64#8
+# asm 2: movq (<hp=%rdi,<pc=%r9,8),>spc=%r10
+movq (%rdi,%r9,8),%r10
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#8
+# asm 2: shl $5,<spc=%r10
+shl $5,%r10
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#8
+# asm 2: add <sp=%rdx,<spc=%r10
+add %rdx,%r10
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#8),>c0=int64#9
+# asm 2: movq 0(<spc=%r10),>c0=%r11
+movq 0(%r10),%r11
+
+# qhasm: c1 = *(uint64 *)(spc + 8)
+# asm 1: movq 8(<spc=int64#8),>c1=int64#10
+# asm 2: movq 8(<spc=%r10),>c1=%r12
+movq 8(%r10),%r12
+
+# qhasm: c2 = *(uint64 *)(spc + 16)
+# asm 1: movq 16(<spc=int64#8),>c2=int64#11
+# asm 2: movq 16(<spc=%r10),>c2=%r13
+movq 16(%r10),%r13
+
+# qhasm: carry? c0 -= *(uint64 *)(sprc + 0)
+# asm 1: subq 0(<sprc=int64#7),<c0=int64#9
+# asm 2: subq 0(<sprc=%rax),<c0=%r11
+subq 0(%rax),%r11
+
+# qhasm: carry? c1 -= *(uint64 *)(sprc + 8) - carry
+# asm 1: sbbq 8(<sprc=int64#7),<c1=int64#10
+# asm 2: sbbq 8(<sprc=%rax),<c1=%r12
+sbbq 8(%rax),%r12
+
+# qhasm: carry? c2 -= *(uint64 *)(sprc + 16) - carry
+# asm 1: sbbq 16(<sprc=int64#7),<c2=int64#11
+# asm 2: sbbq 16(<sprc=%rax),<c2=%r13
+sbbq 16(%rax),%r13
+
+# qhasm: pc = prc if carry
+# asm 1: cmovc <prc=int64#5,<pc=int64#6
+# asm 2: cmovc <prc=%r8,<pc=%r9
+cmovc %r8,%r9
+
+# qhasm: spc = sprc if carry
+# asm 1: cmovc <sprc=int64#7,<spc=int64#8
+# asm 2: cmovc <sprc=%rax,<spc=%r10
+cmovc %rax,%r10
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#8
+# asm 2: sub <sp=%rdx,<spc=%r10
+sub %rdx,%r10
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#8
+# asm 2: shr $5,<spc=%r10
+shr $5,%r10
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#8,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r10,(<hp=%rdi,<pp=%rcx,8)
+movq %r10,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#6,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%r9,8)
+movq %r8,(%rdi,%r9,8)
+
+# qhasm: pp = pc
+# asm 1: mov <pc=int64#6,>pp=int64#4
+# asm 2: mov <pc=%r9,>pp=%rcx
+mov %r9,%rcx
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftdownloop
+jmp ._siftdownloop
+
+# qhasm: siftuploop:
+._siftuploop:
+
+# qhasm: pc = pp
+# asm 1: mov <pp=int64#4,>pc=int64#2
+# asm 2: mov <pp=%rcx,>pc=%rsi
+mov %rcx,%rsi
+
+# qhasm: pp -= 1
+# asm 1: sub $1,<pp=int64#4
+# asm 2: sub $1,<pp=%rcx
+sub $1,%rcx
+
+# qhasm: (uint64) pp >>= 1
+# asm 1: shr $1,<pp=int64#4
+# asm 2: shr $1,<pp=%rcx
+shr $1,%rcx
+
+# qhasm: unsigned>? pc - 0
+# asm 1: cmp $0,<pc=int64#2
+# asm 2: cmp $0,<pc=%rsi
+cmp $0,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if !unsigned>
+jbe ._end
+
+# qhasm: spp = *(uint64 *)(hp + pp * 8)
+# asm 1: movq (<hp=int64#1,<pp=int64#4,8),>spp=int64#5
+# asm 2: movq (<hp=%rdi,<pp=%rcx,8),>spp=%r8
+movq (%rdi,%rcx,8),%r8
+
+# qhasm: spc = *(uint64 *)(hp + pc * 8)
+# asm 1: movq (<hp=int64#1,<pc=int64#2,8),>spc=int64#6
+# asm 2: movq (<hp=%rdi,<pc=%rsi,8),>spc=%r9
+movq (%rdi,%rsi,8),%r9
+
+# qhasm: spp <<= 5
+# asm 1: shl $5,<spp=int64#5
+# asm 2: shl $5,<spp=%r8
+shl $5,%r8
+
+# qhasm: spc <<= 5
+# asm 1: shl $5,<spc=int64#6
+# asm 2: shl $5,<spc=%r9
+shl $5,%r9
+
+# qhasm: spc += sp
+# asm 1: add <sp=int64#3,<spc=int64#6
+# asm 2: add <sp=%rdx,<spc=%r9
+add %rdx,%r9
+
+# qhasm: spp += sp
+# asm 1: add <sp=int64#3,<spp=int64#5
+# asm 2: add <sp=%rdx,<spp=%r8
+add %rdx,%r8
+
+# qhasm: c0 = *(uint64 *)(spc + 0)
+# asm 1: movq 0(<spc=int64#6),>c0=int64#7
+# asm 2: movq 0(<spc=%r9),>c0=%rax
+movq 0(%r9),%rax
+
+# qhasm: c1 = *(uint64 *)(spc + 8)
+# asm 1: movq 8(<spc=int64#6),>c1=int64#8
+# asm 2: movq 8(<spc=%r9),>c1=%r10
+movq 8(%r9),%r10
+
+# qhasm: c2 = *(uint64 *)(spc + 16)
+# asm 1: movq 16(<spc=int64#6),>c2=int64#9
+# asm 2: movq 16(<spc=%r9),>c2=%r11
+movq 16(%r9),%r11
+
+# qhasm: carry? c0 -= *(uint64 *)(spp + 0)
+# asm 1: subq 0(<spp=int64#5),<c0=int64#7
+# asm 2: subq 0(<spp=%r8),<c0=%rax
+subq 0(%r8),%rax
+
+# qhasm: carry? c1 -= *(uint64 *)(spp + 8) - carry
+# asm 1: sbbq 8(<spp=int64#5),<c1=int64#8
+# asm 2: sbbq 8(<spp=%r8),<c1=%r10
+sbbq 8(%r8),%r10
+
+# qhasm: carry? c2 -= *(uint64 *)(spp + 16) - carry
+# asm 1: sbbq 16(<spp=int64#5),<c2=int64#9
+# asm 2: sbbq 16(<spp=%r8),<c2=%r11
+sbbq 16(%r8),%r11
+# comment:fp stack unchanged by jump
+
+# qhasm: goto end if carry
+jc ._end
+
+# qhasm: spc -= sp
+# asm 1: sub <sp=int64#3,<spc=int64#6
+# asm 2: sub <sp=%rdx,<spc=%r9
+sub %rdx,%r9
+
+# qhasm: (uint64) spc >>= 5
+# asm 1: shr $5,<spc=int64#6
+# asm 2: shr $5,<spc=%r9
+shr $5,%r9
+
+# qhasm: spp -= sp
+# asm 1: sub <sp=int64#3,<spp=int64#5
+# asm 2: sub <sp=%rdx,<spp=%r8
+sub %rdx,%r8
+
+# qhasm: (uint64) spp >>= 5
+# asm 1: shr $5,<spp=int64#5
+# asm 2: shr $5,<spp=%r8
+shr $5,%r8
+
+# qhasm: *(uint64 *)(hp + pp * 8) = spc
+# asm 1: movq <spc=int64#6,(<hp=int64#1,<pp=int64#4,8)
+# asm 2: movq <spc=%r9,(<hp=%rdi,<pp=%rcx,8)
+movq %r9,(%rdi,%rcx,8)
+
+# qhasm: *(uint64 *)(hp + pc * 8) = spp
+# asm 1: movq <spp=int64#5,(<hp=int64#1,<pc=int64#2,8)
+# asm 2: movq <spp=%r8,(<hp=%rdi,<pc=%rsi,8)
+movq %r8,(%rdi,%rsi,8)
+# comment:fp stack unchanged by jump
+
+# qhasm: goto siftuploop
+jmp ._siftuploop
+
+# qhasm: end:
+._end:
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/hram.c b/ext/ed25519-amd64-asm/hram.c
new file mode 100644
index 00000000..6f99fc62
--- /dev/null
+++ b/ext/ed25519-amd64-asm/hram.c
@@ -0,0 +1,16 @@
+/*#include "crypto_hash_sha512.h"*/
+#include "hram.h"
+
+extern void ZT_sha512internal(void *digest,const void *data,unsigned int len);
+
+void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
+{
+ unsigned long long i;
+
+ for (i = 0;i < 32;++i) playground[i] = sm[i];
+ for (i = 32;i < 64;++i) playground[i] = pk[i-32];
+ for (i = 64;i < smlen;++i) playground[i] = sm[i];
+
+ /*crypto_hash_sha512(hram,playground,smlen);*/
+ ZT_sha512internal(hram,playground,smlen);
+}
diff --git a/ext/ed25519-amd64-asm/hram.h b/ext/ed25519-amd64-asm/hram.h
new file mode 100644
index 00000000..1740c78a
--- /dev/null
+++ b/ext/ed25519-amd64-asm/hram.h
@@ -0,0 +1,8 @@
+#ifndef HRAM_H
+#define HRAM_H
+
+#define get_hram crypto_sign_ed25519_amd64_64_get_hram
+
+extern void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen);
+
+#endif
diff --git a/ext/ed25519-amd64-asm/implementors b/ext/ed25519-amd64-asm/implementors
new file mode 100644
index 00000000..9b5399a3
--- /dev/null
+++ b/ext/ed25519-amd64-asm/implementors
@@ -0,0 +1,5 @@
+Daniel J. Bernstein
+Niels Duif
+Tanja Lange
+lead: Peter Schwabe
+Bo-Yin Yang
diff --git a/ext/ed25519-amd64-asm/index_heap.c b/ext/ed25519-amd64-asm/index_heap.c
new file mode 100644
index 00000000..f29f7a28
--- /dev/null
+++ b/ext/ed25519-amd64-asm/index_heap.c
@@ -0,0 +1,58 @@
+#include "sc25519.h"
+#include "index_heap.h"
+
+/* caller's responsibility to ensure hlen>=3 */
+void heap_init(unsigned long long *h, unsigned long long hlen, sc25519 *scalars)
+{
+ h[0] = 0;
+ unsigned long long i=1;
+ while(i<hlen)
+ heap_push(h, &i, i, scalars);
+}
+
+void heap_extend(unsigned long long *h, unsigned long long oldlen, unsigned long long newlen, sc25519 *scalars)
+{
+ unsigned long long i=oldlen;
+ while(i<newlen)
+ heap_push(h, &i, i, scalars);
+}
+
+
+void heap_push(unsigned long long *h, unsigned long long *hlen, unsigned long long elem, sc25519 *scalars)
+{
+ /* Move up towards the root */
+ /* XXX: Check size of hlen, whether cast to signed value is ok */
+ signed long long pos = *hlen;
+ signed long long ppos = (pos-1)/2;
+ unsigned long long t;
+ h[*hlen] = elem;
+ while(pos > 0)
+ {
+ /* if(sc25519_lt_vartime(&scalars[h[ppos]], &scalars[h[pos]])) */
+ if(sc25519_lt(&scalars[h[ppos]], &scalars[h[pos]]))
+ {
+ t = h[ppos];
+ h[ppos] = h[pos];
+ h[pos] = t;
+ pos = ppos;
+ ppos = (pos-1)/2;
+ }
+ else break;
+ }
+ (*hlen)++;
+}
+
+/* Put the largest value in the heap in max1, the second largest in max2 */
+void heap_get2max(unsigned long long *h, unsigned long long *max1, unsigned long long *max2, sc25519 *scalars)
+{
+ *max1 = h[0];
+ *max2 = h[1];
+ if(sc25519_lt(&scalars[h[1]],&scalars[h[2]]))
+ *max2 = h[2];
+}
+
+/* After the root has been replaced, restore heap property */
+/* extern void heap_rootreplaced(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+*/
+/* extern void heap_rootreplaced_shortscalars(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+*/
diff --git a/ext/ed25519-amd64-asm/index_heap.h b/ext/ed25519-amd64-asm/index_heap.h
new file mode 100644
index 00000000..7dee9161
--- /dev/null
+++ b/ext/ed25519-amd64-asm/index_heap.h
@@ -0,0 +1,31 @@
+#ifndef INDEX_HEAP_H
+#define INDEX_HEAP_H
+
+#include "sc25519.h"
+
+#define heap_init crypto_sign_ed25519_amd64_64_heap_init
+#define heap_extend crypto_sign_ed25519_amd64_64_heap_extend
+#define heap_pop crypto_sign_ed25519_amd64_64_heap_pop
+#define heap_push crypto_sign_ed25519_amd64_64_heap_push
+#define heap_get2max crypto_sign_ed25519_amd64_64_heap_get2max
+#define heap_rootreplaced crypto_sign_ed25519_amd64_64_heap_rootreplaced
+#define heap_rootreplaced_3limbs crypto_sign_ed25519_amd64_64_heap_rootreplaced_3limbs
+#define heap_rootreplaced_2limbs crypto_sign_ed25519_amd64_64_heap_rootreplaced_2limbs
+#define heap_rootreplaced_1limb crypto_sign_ed25519_amd64_64_heap_rootreplaced_1limb
+
+void heap_init(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+
+void heap_extend(unsigned long long *h, unsigned long long oldlen, unsigned long long newlen, sc25519 *scalars);
+
+unsigned long long heap_pop(unsigned long long *h, unsigned long long *hlen, sc25519 *scalars);
+
+void heap_push(unsigned long long *h, unsigned long long *hlen, unsigned long long elem, sc25519 *scalars);
+
+void heap_get2max(unsigned long long *h, unsigned long long *max1, unsigned long long *max2, sc25519 *scalars);
+
+void heap_rootreplaced(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+void heap_rootreplaced_3limbs(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+void heap_rootreplaced_2limbs(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+void heap_rootreplaced_1limb(unsigned long long *h, unsigned long long hlen, sc25519 *scalars);
+
+#endif
diff --git a/ext/ed25519-amd64-asm/keypair.c b/ext/ed25519-amd64-asm/keypair.c
new file mode 100644
index 00000000..7e094710
--- /dev/null
+++ b/ext/ed25519-amd64-asm/keypair.c
@@ -0,0 +1,25 @@
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "randombytes.h"
+#include "ge25519.h"
+
+int crypto_sign_keypair(unsigned char *pk,unsigned char *sk)
+{
+ unsigned char az[64];
+ sc25519 scsk;
+ ge25519 gepk;
+
+ randombytes(sk,32);
+ crypto_hash_sha512(az,sk,32);
+ az[0] &= 248;
+ az[31] &= 127;
+ az[31] |= 64;
+
+ sc25519_from32bytes(&scsk,az);
+
+ ge25519_scalarmult_base(&gepk, &scsk);
+ ge25519_pack(pk, &gepk);
+ memmove(sk + 32,pk,32);
+ return 0;
+}
diff --git a/ext/ed25519-amd64-asm/open.c b/ext/ed25519-amd64-asm/open.c
new file mode 100644
index 00000000..104d48dc
--- /dev/null
+++ b/ext/ed25519-amd64-asm/open.c
@@ -0,0 +1,49 @@
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_verify_32.h"
+#include "crypto_hash_sha512.h"
+#include "ge25519.h"
+
+int crypto_sign_open(
+ unsigned char *m,unsigned long long *mlen,
+ const unsigned char *sm,unsigned long long smlen,
+ const unsigned char *pk
+ )
+{
+ unsigned char pkcopy[32];
+ unsigned char rcopy[32];
+ unsigned char hram[64];
+ unsigned char rcheck[32];
+ ge25519 get1, get2;
+ sc25519 schram, scs;
+
+ if (smlen < 64) goto badsig;
+ if (sm[63] & 224) goto badsig;
+ if (ge25519_unpackneg_vartime(&get1,pk)) goto badsig;
+
+ memmove(pkcopy,pk,32);
+ memmove(rcopy,sm,32);
+
+ sc25519_from32bytes(&scs, sm+32);
+
+ memmove(m,sm,smlen);
+ memmove(m + 32,pkcopy,32);
+ crypto_hash_sha512(hram,m,smlen);
+
+ sc25519_from64bytes(&schram, hram);
+
+ ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &scs);
+ ge25519_pack(rcheck, &get2);
+
+ if (crypto_verify_32(rcopy,rcheck) == 0) {
+ memmove(m,m + 64,smlen - 64);
+ memset(m + smlen - 64,0,64);
+ *mlen = smlen - 64;
+ return 0;
+ }
+
+badsig:
+ *mlen = (unsigned long long) -1;
+ memset(m,0,smlen);
+ return -1;
+}
diff --git a/ext/ed25519-amd64-asm/sc25519.h b/ext/ed25519-amd64-asm/sc25519.h
new file mode 100644
index 00000000..8ff1b1ca
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519.h
@@ -0,0 +1,66 @@
+#ifndef SC25519_H
+#define SC25519_H
+
+#define sc25519 crypto_sign_ed25519_amd64_64_sc25519
+#define shortsc25519 crypto_sign_ed25519_amd64_64_shortsc25519
+#define sc25519_from32bytes crypto_sign_ed25519_amd64_64_sc25519_from32bytes
+#define shortsc25519_from16bytes crypto_sign_ed25519_amd64_64_shortsc25519_from16bytes
+#define sc25519_from64bytes crypto_sign_ed25519_amd64_64_sc25519_from64bytes
+#define sc25519_from_shortsc crypto_sign_ed25519_amd64_64_sc25519_from_shortsc
+#define sc25519_to32bytes crypto_sign_ed25519_amd64_64_sc25519_to32bytes
+#define sc25519_iszero_vartime crypto_sign_ed25519_amd64_64_sc25519_iszero_vartime
+#define sc25519_isshort_vartime crypto_sign_ed25519_amd64_64_sc25519_isshort_vartime
+#define sc25519_lt crypto_sign_ed25519_amd64_64_sc25519_lt
+#define sc25519_add crypto_sign_ed25519_amd64_64_sc25519_add
+#define sc25519_sub_nored crypto_sign_ed25519_amd64_64_sc25519_sub_nored
+#define sc25519_mul crypto_sign_ed25519_amd64_64_sc25519_mul
+#define sc25519_mul_shortsc crypto_sign_ed25519_amd64_64_sc25519_mul_shortsc
+#define sc25519_window4 crypto_sign_ed25519_amd64_64_sc25519_window4
+#define sc25519_slide crypto_sign_ed25519_amd64_64_sc25519_slide
+#define sc25519_2interleave2 crypto_sign_ed25519_amd64_64_sc25519_2interleave2
+#define sc25519_barrett crypto_sign_ed25519_amd64_64_sc25519_barrett
+
+typedef struct
+{
+ unsigned long long v[4];
+}
+sc25519;
+
+typedef struct
+{
+ unsigned long long v[2];
+}
+shortsc25519;
+
+void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]);
+
+void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]);
+
+void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x);
+
+void sc25519_to32bytes(unsigned char r[32], const sc25519 *x);
+
+int sc25519_iszero_vartime(const sc25519 *x);
+
+int sc25519_lt(const sc25519 *x, const sc25519 *y);
+
+void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y);
+
+void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y);
+
+void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y);
+
+void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y);
+
+/* Convert s into a representation of the form \sum_{i=0}^{63}r[i]2^(4*i)
+ * with r[i] in {-8,...,7}
+ */
+void sc25519_window4(signed char r[85], const sc25519 *s);
+
+void sc25519_slide(signed char r[256], const sc25519 *s, int swindowsize);
+
+void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2);
+
+void sc25519_barrett(sc25519 *r, unsigned long long x[8]);
+
+#endif
diff --git a/ext/ed25519-amd64-asm/sc25519_add.s b/ext/ed25519-amd64-asm/sc25519_add.s
new file mode 100644
index 00000000..d5b941cd
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_add.s
@@ -0,0 +1,232 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_add
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_sc25519_add
+.globl crypto_sign_ed25519_amd64_64_sc25519_add
+_crypto_sign_ed25519_amd64_64_sc25519_add:
+crypto_sign_ed25519_amd64_64_sc25519_add:
+mov %rsp,%r11
+and $31,%r11
+add $32,%r11
+sub %r11,%rsp
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#1
+# asm 2: movq <caller4=%r14,>caller4_stack=0(%rsp)
+movq %r14,0(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#2
+# asm 2: movq <caller5=%r15,>caller5_stack=8(%rsp)
+movq %r15,8(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#3
+# asm 2: movq <caller6=%rbx,>caller6_stack=16(%rsp)
+movq %rbx,16(%rsp)
+
+# qhasm: r0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>r0=int64#4
+# asm 2: movq 0(<xp=%rsi),>r0=%rcx
+movq 0(%rsi),%rcx
+
+# qhasm: r1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>r1=int64#5
+# asm 2: movq 8(<xp=%rsi),>r1=%r8
+movq 8(%rsi),%r8
+
+# qhasm: r2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>r2=int64#6
+# asm 2: movq 16(<xp=%rsi),>r2=%r9
+movq 16(%rsi),%r9
+
+# qhasm: r3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>r3=int64#2
+# asm 2: movq 24(<xp=%rsi),>r3=%rsi
+movq 24(%rsi),%rsi
+
+# qhasm: carry? r0 += *(uint64 *)(yp + 0)
+# asm 1: addq 0(<yp=int64#3),<r0=int64#4
+# asm 2: addq 0(<yp=%rdx),<r0=%rcx
+addq 0(%rdx),%rcx
+
+# qhasm: carry? r1 += *(uint64 *)(yp + 8) + carry
+# asm 1: adcq 8(<yp=int64#3),<r1=int64#5
+# asm 2: adcq 8(<yp=%rdx),<r1=%r8
+adcq 8(%rdx),%r8
+
+# qhasm: carry? r2 += *(uint64 *)(yp + 16) + carry
+# asm 1: adcq 16(<yp=int64#3),<r2=int64#6
+# asm 2: adcq 16(<yp=%rdx),<r2=%r9
+adcq 16(%rdx),%r9
+
+# qhasm: r3 += *(uint64 *)(yp + 24) + carry
+# asm 1: adcq 24(<yp=int64#3),<r3=int64#2
+# asm 2: adcq 24(<yp=%rdx),<r3=%rsi
+adcq 24(%rdx),%rsi
+
+# qhasm: t0 = r0
+# asm 1: mov <r0=int64#4,>t0=int64#3
+# asm 2: mov <r0=%rcx,>t0=%rdx
+mov %rcx,%rdx
+
+# qhasm: t1 = r1
+# asm 1: mov <r1=int64#5,>t1=int64#7
+# asm 2: mov <r1=%r8,>t1=%rax
+mov %r8,%rax
+
+# qhasm: t2 = r2
+# asm 1: mov <r2=int64#6,>t2=int64#8
+# asm 2: mov <r2=%r9,>t2=%r10
+mov %r9,%r10
+
+# qhasm: t3 = r3
+# asm 1: mov <r3=int64#2,>t3=int64#12
+# asm 2: mov <r3=%rsi,>t3=%r14
+mov %rsi,%r14
+
+# qhasm: carry? t0 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+# asm 1: sub crypto_sign_ed25519_amd64_64_ORDER0,<t0=int64#3
+# asm 2: sub crypto_sign_ed25519_amd64_64_ORDER0,<t0=%rdx
+sub crypto_sign_ed25519_amd64_64_ORDER0(%rip),%rdx
+
+# qhasm: carry? t1 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER1,<t1=int64#7
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER1,<t1=%rax
+sbb crypto_sign_ed25519_amd64_64_ORDER1(%rip),%rax
+
+# qhasm: carry? t2 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER2,<t2=int64#8
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER2,<t2=%r10
+sbb crypto_sign_ed25519_amd64_64_ORDER2(%rip),%r10
+
+# qhasm: unsigned<? t3 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER3 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER3,<t3=int64#12
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER3,<t3=%r14
+sbb crypto_sign_ed25519_amd64_64_ORDER3(%rip),%r14
+
+# qhasm: r0 = t0 if !unsigned<
+# asm 1: cmovae <t0=int64#3,<r0=int64#4
+# asm 2: cmovae <t0=%rdx,<r0=%rcx
+cmovae %rdx,%rcx
+
+# qhasm: r1 = t1 if !unsigned<
+# asm 1: cmovae <t1=int64#7,<r1=int64#5
+# asm 2: cmovae <t1=%rax,<r1=%r8
+cmovae %rax,%r8
+
+# qhasm: r2 = t2 if !unsigned<
+# asm 1: cmovae <t2=int64#8,<r2=int64#6
+# asm 2: cmovae <t2=%r10,<r2=%r9
+cmovae %r10,%r9
+
+# qhasm: r3 = t3 if !unsigned<
+# asm 1: cmovae <t3=int64#12,<r3=int64#2
+# asm 2: cmovae <t3=%r14,<r3=%rsi
+cmovae %r14,%rsi
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#4,0(<rp=int64#1)
+# asm 2: movq <r0=%rcx,0(<rp=%rdi)
+movq %rcx,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#5,8(<rp=int64#1)
+# asm 2: movq <r1=%r8,8(<rp=%rdi)
+movq %r8,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#6,16(<rp=int64#1)
+# asm 2: movq <r2=%r9,16(<rp=%rdi)
+movq %r9,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#2,24(<rp=int64#1)
+# asm 2: movq <r3=%rsi,24(<rp=%rdi)
+movq %rsi,24(%rdi)
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#1,>caller4=int64#12
+# asm 2: movq <caller4_stack=0(%rsp),>caller4=%r14
+movq 0(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#2,>caller5=int64#13
+# asm 2: movq <caller5_stack=8(%rsp),>caller5=%r15
+movq 8(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#3,>caller6=int64#14
+# asm 2: movq <caller6_stack=16(%rsp),>caller6=%rbx
+movq 16(%rsp),%rbx
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/sc25519_barrett.s b/ext/ed25519-amd64-asm/sc25519_barrett.s
new file mode 100644
index 00000000..7eb56fad
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_barrett.s
@@ -0,0 +1,1188 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: int64 q23
+
+# qhasm: int64 q24
+
+# qhasm: int64 q30
+
+# qhasm: int64 q31
+
+# qhasm: int64 q32
+
+# qhasm: int64 q33
+
+# qhasm: int64 r20
+
+# qhasm: int64 r21
+
+# qhasm: int64 r22
+
+# qhasm: int64 r23
+
+# qhasm: int64 r24
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 rax
+
+# qhasm: int64 rdx
+
+# qhasm: int64 c
+
+# qhasm: int64 zero
+
+# qhasm: int64 mask
+
+# qhasm: int64 nmask
+
+# qhasm: stack64 q30_stack
+
+# qhasm: stack64 q31_stack
+
+# qhasm: stack64 q32_stack
+
+# qhasm: stack64 q33_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_barrett
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_sc25519_barrett
+.globl crypto_sign_ed25519_amd64_64_sc25519_barrett
+_crypto_sign_ed25519_amd64_64_sc25519_barrett:
+crypto_sign_ed25519_amd64_64_sc25519_barrett:
+mov %rsp,%r11
+and $31,%r11
+add $96,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: zero ^= zero
+# asm 1: xor <zero=int64#4,<zero=int64#4
+# asm 2: xor <zero=%rcx,<zero=%rcx
+xor %rcx,%rcx
+
+# qhasm: q30 ^= q30
+# asm 1: xor <q30=int64#5,<q30=int64#5
+# asm 2: xor <q30=%r8,<q30=%r8
+xor %r8,%r8
+
+# qhasm: q31 ^= q31
+# asm 1: xor <q31=int64#6,<q31=int64#6
+# asm 2: xor <q31=%r9,<q31=%r9
+xor %r9,%r9
+
+# qhasm: q32 ^= q32
+# asm 1: xor <q32=int64#8,<q32=int64#8
+# asm 2: xor <q32=%r10,<q32=%r10
+xor %r10,%r10
+
+# qhasm: q33 ^= q33
+# asm 1: xor <q33=int64#9,<q33=int64#9
+# asm 2: xor <q33=%r11,<q33=%r11
+xor %r11,%r11
+
+# qhasm: rax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>rax=int64#7
+# asm 2: movq 24(<xp=%rsi),>rax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3
+mulq crypto_sign_ed25519_amd64_64_MU3(%rip)
+
+# qhasm: q23 = rax
+# asm 1: mov <rax=int64#7,>q23=int64#10
+# asm 2: mov <rax=%rax,>q23=%r12
+mov %rax,%r12
+
+# qhasm: c = rdx
+# asm 1: mov <rdx=int64#3,>c=int64#11
+# asm 2: mov <rdx=%rdx,>c=%r13
+mov %rdx,%r13
+
+# qhasm: rax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>rax=int64#7
+# asm 2: movq 24(<xp=%rsi),>rax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4
+mulq crypto_sign_ed25519_amd64_64_MU4(%rip)
+
+# qhasm: q24 = rax
+# asm 1: mov <rax=int64#7,>q24=int64#12
+# asm 2: mov <rax=%rax,>q24=%r14
+mov %rax,%r14
+
+# qhasm: carry? q24 += c
+# asm 1: add <c=int64#11,<q24=int64#12
+# asm 2: add <c=%r13,<q24=%r14
+add %r13,%r14
+
+# qhasm: q30 += rdx + carry
+# asm 1: adc <rdx=int64#3,<q30=int64#5
+# asm 2: adc <rdx=%rdx,<q30=%r8
+adc %rdx,%r8
+
+# qhasm: rax = *(uint64 *)(xp + 32)
+# asm 1: movq 32(<xp=int64#2),>rax=int64#7
+# asm 2: movq 32(<xp=%rsi),>rax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2
+mulq crypto_sign_ed25519_amd64_64_MU2(%rip)
+
+# qhasm: carry? q23 += rax
+# asm 1: add <rax=int64#7,<q23=int64#10
+# asm 2: add <rax=%rax,<q23=%r12
+add %rax,%r12
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#11
+# asm 2: mov $0,>c=%r13
+mov $0,%r13
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#11
+# asm 2: adc <rdx=%rdx,<c=%r13
+adc %rdx,%r13
+
+# qhasm: rax = *(uint64 *)(xp + 32)
+# asm 1: movq 32(<xp=int64#2),>rax=int64#7
+# asm 2: movq 32(<xp=%rsi),>rax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3
+mulq crypto_sign_ed25519_amd64_64_MU3(%rip)
+
+# qhasm: carry? q24 += rax
+# asm 1: add <rax=int64#7,<q24=int64#12
+# asm 2: add <rax=%rax,<q24=%r14
+add %rax,%r14
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q24 += c
+# asm 1: add <c=int64#11,<q24=int64#12
+# asm 2: add <c=%r13,<q24=%r14
+add %r13,%r14
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#11
+# asm 2: mov $0,>c=%r13
+mov $0,%r13
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#11
+# asm 2: adc <rdx=%rdx,<c=%r13
+adc %rdx,%r13
+
+# qhasm: rax = *(uint64 *)(xp + 32)
+# asm 1: movq 32(<xp=int64#2),>rax=int64#7
+# asm 2: movq 32(<xp=%rsi),>rax=%rax
+movq 32(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4
+mulq crypto_sign_ed25519_amd64_64_MU4(%rip)
+
+# qhasm: carry? q30 += rax
+# asm 1: add <rax=int64#7,<q30=int64#5
+# asm 2: add <rax=%rax,<q30=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q30 += c
+# asm 1: add <c=int64#11,<q30=int64#5
+# asm 2: add <c=%r13,<q30=%r8
+add %r13,%r8
+
+# qhasm: q31 += rdx + carry
+# asm 1: adc <rdx=int64#3,<q31=int64#6
+# asm 2: adc <rdx=%rdx,<q31=%r9
+adc %rdx,%r9
+
+# qhasm: rax = *(uint64 *)(xp + 40)
+# asm 1: movq 40(<xp=int64#2),>rax=int64#7
+# asm 2: movq 40(<xp=%rsi),>rax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU1
+mulq crypto_sign_ed25519_amd64_64_MU1(%rip)
+
+# qhasm: carry? q23 += rax
+# asm 1: add <rax=int64#7,<q23=int64#10
+# asm 2: add <rax=%rax,<q23=%r12
+add %rax,%r12
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#11
+# asm 2: mov $0,>c=%r13
+mov $0,%r13
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#11
+# asm 2: adc <rdx=%rdx,<c=%r13
+adc %rdx,%r13
+
+# qhasm: rax = *(uint64 *)(xp + 40)
+# asm 1: movq 40(<xp=int64#2),>rax=int64#7
+# asm 2: movq 40(<xp=%rsi),>rax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2
+mulq crypto_sign_ed25519_amd64_64_MU2(%rip)
+
+# qhasm: carry? q24 += rax
+# asm 1: add <rax=int64#7,<q24=int64#12
+# asm 2: add <rax=%rax,<q24=%r14
+add %rax,%r14
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q24 += c
+# asm 1: add <c=int64#11,<q24=int64#12
+# asm 2: add <c=%r13,<q24=%r14
+add %r13,%r14
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#11
+# asm 2: mov $0,>c=%r13
+mov $0,%r13
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#11
+# asm 2: adc <rdx=%rdx,<c=%r13
+adc %rdx,%r13
+
+# qhasm: rax = *(uint64 *)(xp + 40)
+# asm 1: movq 40(<xp=int64#2),>rax=int64#7
+# asm 2: movq 40(<xp=%rsi),>rax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3
+mulq crypto_sign_ed25519_amd64_64_MU3(%rip)
+
+# qhasm: carry? q30 += rax
+# asm 1: add <rax=int64#7,<q30=int64#5
+# asm 2: add <rax=%rax,<q30=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q30 += c
+# asm 1: add <c=int64#11,<q30=int64#5
+# asm 2: add <c=%r13,<q30=%r8
+add %r13,%r8
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#11
+# asm 2: mov $0,>c=%r13
+mov $0,%r13
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#11
+# asm 2: adc <rdx=%rdx,<c=%r13
+adc %rdx,%r13
+
+# qhasm: rax = *(uint64 *)(xp + 40)
+# asm 1: movq 40(<xp=int64#2),>rax=int64#7
+# asm 2: movq 40(<xp=%rsi),>rax=%rax
+movq 40(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4
+mulq crypto_sign_ed25519_amd64_64_MU4(%rip)
+
+# qhasm: carry? q31 += rax
+# asm 1: add <rax=int64#7,<q31=int64#6
+# asm 2: add <rax=%rax,<q31=%r9
+add %rax,%r9
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q31 += c
+# asm 1: add <c=int64#11,<q31=int64#6
+# asm 2: add <c=%r13,<q31=%r9
+add %r13,%r9
+
+# qhasm: q32 += rdx + carry
+# asm 1: adc <rdx=int64#3,<q32=int64#8
+# asm 2: adc <rdx=%rdx,<q32=%r10
+adc %rdx,%r10
+
+# qhasm: rax = *(uint64 *)(xp + 48)
+# asm 1: movq 48(<xp=int64#2),>rax=int64#7
+# asm 2: movq 48(<xp=%rsi),>rax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU0
+mulq crypto_sign_ed25519_amd64_64_MU0(%rip)
+
+# qhasm: carry? q23 += rax
+# asm 1: add <rax=int64#7,<q23=int64#10
+# asm 2: add <rax=%rax,<q23=%r12
+add %rax,%r12
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#10
+# asm 2: mov $0,>c=%r12
+mov $0,%r12
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#10
+# asm 2: adc <rdx=%rdx,<c=%r12
+adc %rdx,%r12
+
+# qhasm: rax = *(uint64 *)(xp + 48)
+# asm 1: movq 48(<xp=int64#2),>rax=int64#7
+# asm 2: movq 48(<xp=%rsi),>rax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU1
+mulq crypto_sign_ed25519_amd64_64_MU1(%rip)
+
+# qhasm: carry? q24 += rax
+# asm 1: add <rax=int64#7,<q24=int64#12
+# asm 2: add <rax=%rax,<q24=%r14
+add %rax,%r14
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q24 += c
+# asm 1: add <c=int64#10,<q24=int64#12
+# asm 2: add <c=%r12,<q24=%r14
+add %r12,%r14
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#10
+# asm 2: mov $0,>c=%r12
+mov $0,%r12
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#10
+# asm 2: adc <rdx=%rdx,<c=%r12
+adc %rdx,%r12
+
+# qhasm: rax = *(uint64 *)(xp + 48)
+# asm 1: movq 48(<xp=int64#2),>rax=int64#7
+# asm 2: movq 48(<xp=%rsi),>rax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2
+mulq crypto_sign_ed25519_amd64_64_MU2(%rip)
+
+# qhasm: carry? q30 += rax
+# asm 1: add <rax=int64#7,<q30=int64#5
+# asm 2: add <rax=%rax,<q30=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q30 += c
+# asm 1: add <c=int64#10,<q30=int64#5
+# asm 2: add <c=%r12,<q30=%r8
+add %r12,%r8
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#10
+# asm 2: mov $0,>c=%r12
+mov $0,%r12
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#10
+# asm 2: adc <rdx=%rdx,<c=%r12
+adc %rdx,%r12
+
+# qhasm: rax = *(uint64 *)(xp + 48)
+# asm 1: movq 48(<xp=int64#2),>rax=int64#7
+# asm 2: movq 48(<xp=%rsi),>rax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3
+mulq crypto_sign_ed25519_amd64_64_MU3(%rip)
+
+# qhasm: carry? q31 += rax
+# asm 1: add <rax=int64#7,<q31=int64#6
+# asm 2: add <rax=%rax,<q31=%r9
+add %rax,%r9
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q31 += c
+# asm 1: add <c=int64#10,<q31=int64#6
+# asm 2: add <c=%r12,<q31=%r9
+add %r12,%r9
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#10
+# asm 2: mov $0,>c=%r12
+mov $0,%r12
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#10
+# asm 2: adc <rdx=%rdx,<c=%r12
+adc %rdx,%r12
+
+# qhasm: rax = *(uint64 *)(xp + 48)
+# asm 1: movq 48(<xp=int64#2),>rax=int64#7
+# asm 2: movq 48(<xp=%rsi),>rax=%rax
+movq 48(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4
+mulq crypto_sign_ed25519_amd64_64_MU4(%rip)
+
+# qhasm: carry? q32 += rax
+# asm 1: add <rax=int64#7,<q32=int64#8
+# asm 2: add <rax=%rax,<q32=%r10
+add %rax,%r10
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q32 += c
+# asm 1: add <c=int64#10,<q32=int64#8
+# asm 2: add <c=%r12,<q32=%r10
+add %r12,%r10
+
+# qhasm: q33 += rdx + carry
+# asm 1: adc <rdx=int64#3,<q33=int64#9
+# asm 2: adc <rdx=%rdx,<q33=%r11
+adc %rdx,%r11
+
+# qhasm: rax = *(uint64 *)(xp + 56)
+# asm 1: movq 56(<xp=int64#2),>rax=int64#7
+# asm 2: movq 56(<xp=%rsi),>rax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU0
+mulq crypto_sign_ed25519_amd64_64_MU0(%rip)
+
+# qhasm: carry? q24 += rax
+# asm 1: add <rax=int64#7,<q24=int64#12
+# asm 2: add <rax=%rax,<q24=%r14
+add %rax,%r14
+
+# qhasm: free q24
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#10
+# asm 2: mov $0,>c=%r12
+mov $0,%r12
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#10
+# asm 2: adc <rdx=%rdx,<c=%r12
+adc %rdx,%r12
+
+# qhasm: rax = *(uint64 *)(xp + 56)
+# asm 1: movq 56(<xp=int64#2),>rax=int64#7
+# asm 2: movq 56(<xp=%rsi),>rax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU1
+mulq crypto_sign_ed25519_amd64_64_MU1(%rip)
+
+# qhasm: carry? q30 += rax
+# asm 1: add <rax=int64#7,<q30=int64#5
+# asm 2: add <rax=%rax,<q30=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q30 += c
+# asm 1: add <c=int64#10,<q30=int64#5
+# asm 2: add <c=%r12,<q30=%r8
+add %r12,%r8
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#10
+# asm 2: mov $0,>c=%r12
+mov $0,%r12
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#10
+# asm 2: adc <rdx=%rdx,<c=%r12
+adc %rdx,%r12
+
+# qhasm: q30_stack = q30
+# asm 1: movq <q30=int64#5,>q30_stack=stack64#8
+# asm 2: movq <q30=%r8,>q30_stack=56(%rsp)
+movq %r8,56(%rsp)
+
+# qhasm: rax = *(uint64 *)(xp + 56)
+# asm 1: movq 56(<xp=int64#2),>rax=int64#7
+# asm 2: movq 56(<xp=%rsi),>rax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU2
+mulq crypto_sign_ed25519_amd64_64_MU2(%rip)
+
+# qhasm: carry? q31 += rax
+# asm 1: add <rax=int64#7,<q31=int64#6
+# asm 2: add <rax=%rax,<q31=%r9
+add %rax,%r9
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q31 += c
+# asm 1: add <c=int64#10,<q31=int64#6
+# asm 2: add <c=%r12,<q31=%r9
+add %r12,%r9
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#5
+# asm 2: mov $0,>c=%r8
+mov $0,%r8
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#5
+# asm 2: adc <rdx=%rdx,<c=%r8
+adc %rdx,%r8
+
+# qhasm: q31_stack = q31
+# asm 1: movq <q31=int64#6,>q31_stack=stack64#9
+# asm 2: movq <q31=%r9,>q31_stack=64(%rsp)
+movq %r9,64(%rsp)
+
+# qhasm: rax = *(uint64 *)(xp + 56)
+# asm 1: movq 56(<xp=int64#2),>rax=int64#7
+# asm 2: movq 56(<xp=%rsi),>rax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU3
+mulq crypto_sign_ed25519_amd64_64_MU3(%rip)
+
+# qhasm: carry? q32 += rax
+# asm 1: add <rax=int64#7,<q32=int64#8
+# asm 2: add <rax=%rax,<q32=%r10
+add %rax,%r10
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? q32 += c
+# asm 1: add <c=int64#5,<q32=int64#8
+# asm 2: add <c=%r8,<q32=%r10
+add %r8,%r10
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#5
+# asm 2: mov $0,>c=%r8
+mov $0,%r8
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#5
+# asm 2: adc <rdx=%rdx,<c=%r8
+adc %rdx,%r8
+
+# qhasm: q32_stack = q32
+# asm 1: movq <q32=int64#8,>q32_stack=stack64#10
+# asm 2: movq <q32=%r10,>q32_stack=72(%rsp)
+movq %r10,72(%rsp)
+
+# qhasm: rax = *(uint64 *)(xp + 56)
+# asm 1: movq 56(<xp=int64#2),>rax=int64#7
+# asm 2: movq 56(<xp=%rsi),>rax=%rax
+movq 56(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_MU4
+mulq crypto_sign_ed25519_amd64_64_MU4(%rip)
+
+# qhasm: carry? q33 += rax
+# asm 1: add <rax=int64#7,<q33=int64#9
+# asm 2: add <rax=%rax,<q33=%r11
+add %rax,%r11
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: q33 += c
+# asm 1: add <c=int64#5,<q33=int64#9
+# asm 2: add <c=%r8,<q33=%r11
+add %r8,%r11
+
+# qhasm: q33_stack = q33
+# asm 1: movq <q33=int64#9,>q33_stack=stack64#11
+# asm 2: movq <q33=%r11,>q33_stack=80(%rsp)
+movq %r11,80(%rsp)
+
+# qhasm: rax = q30_stack
+# asm 1: movq <q30_stack=stack64#8,>rax=int64#7
+# asm 2: movq <q30_stack=56(%rsp),>rax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip)
+
+# qhasm: r20 = rax
+# asm 1: mov <rax=int64#7,>r20=int64#5
+# asm 2: mov <rax=%rax,>r20=%r8
+mov %rax,%r8
+
+# qhasm: c = rdx
+# asm 1: mov <rdx=int64#3,>c=int64#6
+# asm 2: mov <rdx=%rdx,>c=%r9
+mov %rdx,%r9
+
+# qhasm: rax = q30_stack
+# asm 1: movq <q30_stack=stack64#8,>rax=int64#7
+# asm 2: movq <q30_stack=56(%rsp),>rax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1
+mulq crypto_sign_ed25519_amd64_64_ORDER1(%rip)
+
+# qhasm: r21 = rax
+# asm 1: mov <rax=int64#7,>r21=int64#8
+# asm 2: mov <rax=%rax,>r21=%r10
+mov %rax,%r10
+
+# qhasm: carry? r21 += c
+# asm 1: add <c=int64#6,<r21=int64#8
+# asm 2: add <c=%r9,<r21=%r10
+add %r9,%r10
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#6
+# asm 2: mov $0,>c=%r9
+mov $0,%r9
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#6
+# asm 2: adc <rdx=%rdx,<c=%r9
+adc %rdx,%r9
+
+# qhasm: rax = q30_stack
+# asm 1: movq <q30_stack=stack64#8,>rax=int64#7
+# asm 2: movq <q30_stack=56(%rsp),>rax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2
+mulq crypto_sign_ed25519_amd64_64_ORDER2(%rip)
+
+# qhasm: r22 = rax
+# asm 1: mov <rax=int64#7,>r22=int64#9
+# asm 2: mov <rax=%rax,>r22=%r11
+mov %rax,%r11
+
+# qhasm: carry? r22 += c
+# asm 1: add <c=int64#6,<r22=int64#9
+# asm 2: add <c=%r9,<r22=%r11
+add %r9,%r11
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#6
+# asm 2: mov $0,>c=%r9
+mov $0,%r9
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#6
+# asm 2: adc <rdx=%rdx,<c=%r9
+adc %rdx,%r9
+
+# qhasm: rax = q30_stack
+# asm 1: movq <q30_stack=stack64#8,>rax=int64#7
+# asm 2: movq <q30_stack=56(%rsp),>rax=%rax
+movq 56(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER3
+mulq crypto_sign_ed25519_amd64_64_ORDER3(%rip)
+
+# qhasm: free rdx
+
+# qhasm: r23 = rax
+# asm 1: mov <rax=int64#7,>r23=int64#10
+# asm 2: mov <rax=%rax,>r23=%r12
+mov %rax,%r12
+
+# qhasm: r23 += c
+# asm 1: add <c=int64#6,<r23=int64#10
+# asm 2: add <c=%r9,<r23=%r12
+add %r9,%r12
+
+# qhasm: rax = q31_stack
+# asm 1: movq <q31_stack=stack64#9,>rax=int64#7
+# asm 2: movq <q31_stack=64(%rsp),>rax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip)
+
+# qhasm: carry? r21 += rax
+# asm 1: add <rax=int64#7,<r21=int64#8
+# asm 2: add <rax=%rax,<r21=%r10
+add %rax,%r10
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#6
+# asm 2: mov $0,>c=%r9
+mov $0,%r9
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#6
+# asm 2: adc <rdx=%rdx,<c=%r9
+adc %rdx,%r9
+
+# qhasm: rax = q31_stack
+# asm 1: movq <q31_stack=stack64#9,>rax=int64#7
+# asm 2: movq <q31_stack=64(%rsp),>rax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1
+mulq crypto_sign_ed25519_amd64_64_ORDER1(%rip)
+
+# qhasm: carry? r22 += rax
+# asm 1: add <rax=int64#7,<r22=int64#9
+# asm 2: add <rax=%rax,<r22=%r11
+add %rax,%r11
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#4,<rdx=int64#3
+# asm 2: adc <zero=%rcx,<rdx=%rdx
+adc %rcx,%rdx
+
+# qhasm: carry? r22 += c
+# asm 1: add <c=int64#6,<r22=int64#9
+# asm 2: add <c=%r9,<r22=%r11
+add %r9,%r11
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#4
+# asm 2: mov $0,>c=%rcx
+mov $0,%rcx
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#4
+# asm 2: adc <rdx=%rdx,<c=%rcx
+adc %rdx,%rcx
+
+# qhasm: rax = q31_stack
+# asm 1: movq <q31_stack=stack64#9,>rax=int64#7
+# asm 2: movq <q31_stack=64(%rsp),>rax=%rax
+movq 64(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2
+mulq crypto_sign_ed25519_amd64_64_ORDER2(%rip)
+
+# qhasm: free rdx
+
+# qhasm: r23 += rax
+# asm 1: add <rax=int64#7,<r23=int64#10
+# asm 2: add <rax=%rax,<r23=%r12
+add %rax,%r12
+
+# qhasm: r23 += c
+# asm 1: add <c=int64#4,<r23=int64#10
+# asm 2: add <c=%rcx,<r23=%r12
+add %rcx,%r12
+
+# qhasm: rax = q32_stack
+# asm 1: movq <q32_stack=stack64#10,>rax=int64#7
+# asm 2: movq <q32_stack=72(%rsp),>rax=%rax
+movq 72(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip)
+
+# qhasm: carry? r22 += rax
+# asm 1: add <rax=int64#7,<r22=int64#9
+# asm 2: add <rax=%rax,<r22=%r11
+add %rax,%r11
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#4
+# asm 2: mov $0,>c=%rcx
+mov $0,%rcx
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#4
+# asm 2: adc <rdx=%rdx,<c=%rcx
+adc %rdx,%rcx
+
+# qhasm: rax = q32_stack
+# asm 1: movq <q32_stack=stack64#10,>rax=int64#7
+# asm 2: movq <q32_stack=72(%rsp),>rax=%rax
+movq 72(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1
+mulq crypto_sign_ed25519_amd64_64_ORDER1(%rip)
+
+# qhasm: free rdx
+
+# qhasm: r23 += rax
+# asm 1: add <rax=int64#7,<r23=int64#10
+# asm 2: add <rax=%rax,<r23=%r12
+add %rax,%r12
+
+# qhasm: r23 += c
+# asm 1: add <c=int64#4,<r23=int64#10
+# asm 2: add <c=%rcx,<r23=%r12
+add %rcx,%r12
+
+# qhasm: rax = q33_stack
+# asm 1: movq <q33_stack=stack64#11,>rax=int64#7
+# asm 2: movq <q33_stack=80(%rsp),>rax=%rax
+movq 80(%rsp),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+mulq crypto_sign_ed25519_amd64_64_ORDER0(%rip)
+
+# qhasm: free rdx
+
+# qhasm: r23 += rax
+# asm 1: add <rax=int64#7,<r23=int64#10
+# asm 2: add <rax=%rax,<r23=%r12
+add %rax,%r12
+
+# qhasm: r0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>r0=int64#3
+# asm 2: movq 0(<xp=%rsi),>r0=%rdx
+movq 0(%rsi),%rdx
+
+# qhasm: carry? r0 -= r20
+# asm 1: sub <r20=int64#5,<r0=int64#3
+# asm 2: sub <r20=%r8,<r0=%rdx
+sub %r8,%rdx
+
+# qhasm: t0 = r0
+# asm 1: mov <r0=int64#3,>t0=int64#4
+# asm 2: mov <r0=%rdx,>t0=%rcx
+mov %rdx,%rcx
+
+# qhasm: r1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>r1=int64#5
+# asm 2: movq 8(<xp=%rsi),>r1=%r8
+movq 8(%rsi),%r8
+
+# qhasm: carry? r1 -= r21 - carry
+# asm 1: sbb <r21=int64#8,<r1=int64#5
+# asm 2: sbb <r21=%r10,<r1=%r8
+sbb %r10,%r8
+
+# qhasm: t1 = r1
+# asm 1: mov <r1=int64#5,>t1=int64#6
+# asm 2: mov <r1=%r8,>t1=%r9
+mov %r8,%r9
+
+# qhasm: r2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>r2=int64#7
+# asm 2: movq 16(<xp=%rsi),>r2=%rax
+movq 16(%rsi),%rax
+
+# qhasm: carry? r2 -= r22 - carry
+# asm 1: sbb <r22=int64#9,<r2=int64#7
+# asm 2: sbb <r22=%r11,<r2=%rax
+sbb %r11,%rax
+
+# qhasm: t2 = r2
+# asm 1: mov <r2=int64#7,>t2=int64#8
+# asm 2: mov <r2=%rax,>t2=%r10
+mov %rax,%r10
+
+# qhasm: r3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>r3=int64#2
+# asm 2: movq 24(<xp=%rsi),>r3=%rsi
+movq 24(%rsi),%rsi
+
+# qhasm: r3 -= r23 - carry
+# asm 1: sbb <r23=int64#10,<r3=int64#2
+# asm 2: sbb <r23=%r12,<r3=%rsi
+sbb %r12,%rsi
+
+# qhasm: t3 = r3
+# asm 1: mov <r3=int64#2,>t3=int64#9
+# asm 2: mov <r3=%rsi,>t3=%r11
+mov %rsi,%r11
+
+# qhasm: carry? t0 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+# asm 1: sub crypto_sign_ed25519_amd64_64_ORDER0,<t0=int64#4
+# asm 2: sub crypto_sign_ed25519_amd64_64_ORDER0,<t0=%rcx
+sub crypto_sign_ed25519_amd64_64_ORDER0(%rip),%rcx
+
+# qhasm: carry? t1 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER1,<t1=int64#6
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER1,<t1=%r9
+sbb crypto_sign_ed25519_amd64_64_ORDER1(%rip),%r9
+
+# qhasm: carry? t2 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER2,<t2=int64#8
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER2,<t2=%r10
+sbb crypto_sign_ed25519_amd64_64_ORDER2(%rip),%r10
+
+# qhasm: unsigned<? t3 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER3 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER3,<t3=int64#9
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER3,<t3=%r11
+sbb crypto_sign_ed25519_amd64_64_ORDER3(%rip),%r11
+
+# qhasm: r0 = t0 if !unsigned<
+# asm 1: cmovae <t0=int64#4,<r0=int64#3
+# asm 2: cmovae <t0=%rcx,<r0=%rdx
+cmovae %rcx,%rdx
+
+# qhasm: t0 = r0
+# asm 1: mov <r0=int64#3,>t0=int64#4
+# asm 2: mov <r0=%rdx,>t0=%rcx
+mov %rdx,%rcx
+
+# qhasm: r1 = t1 if !unsigned<
+# asm 1: cmovae <t1=int64#6,<r1=int64#5
+# asm 2: cmovae <t1=%r9,<r1=%r8
+cmovae %r9,%r8
+
+# qhasm: t1 = r1
+# asm 1: mov <r1=int64#5,>t1=int64#6
+# asm 2: mov <r1=%r8,>t1=%r9
+mov %r8,%r9
+
+# qhasm: r2 = t2 if !unsigned<
+# asm 1: cmovae <t2=int64#8,<r2=int64#7
+# asm 2: cmovae <t2=%r10,<r2=%rax
+cmovae %r10,%rax
+
+# qhasm: t2 = r2
+# asm 1: mov <r2=int64#7,>t2=int64#8
+# asm 2: mov <r2=%rax,>t2=%r10
+mov %rax,%r10
+
+# qhasm: r3 = t3 if !unsigned<
+# asm 1: cmovae <t3=int64#9,<r3=int64#2
+# asm 2: cmovae <t3=%r11,<r3=%rsi
+cmovae %r11,%rsi
+
+# qhasm: t3 = r3
+# asm 1: mov <r3=int64#2,>t3=int64#9
+# asm 2: mov <r3=%rsi,>t3=%r11
+mov %rsi,%r11
+
+# qhasm: carry? t0 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER0
+# asm 1: sub crypto_sign_ed25519_amd64_64_ORDER0,<t0=int64#4
+# asm 2: sub crypto_sign_ed25519_amd64_64_ORDER0,<t0=%rcx
+sub crypto_sign_ed25519_amd64_64_ORDER0(%rip),%rcx
+
+# qhasm: carry? t1 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER1 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER1,<t1=int64#6
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER1,<t1=%r9
+sbb crypto_sign_ed25519_amd64_64_ORDER1(%rip),%r9
+
+# qhasm: carry? t2 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER2 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER2,<t2=int64#8
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER2,<t2=%r10
+sbb crypto_sign_ed25519_amd64_64_ORDER2(%rip),%r10
+
+# qhasm: unsigned<? t3 -= *(uint64 *) &crypto_sign_ed25519_amd64_64_ORDER3 - carry
+# asm 1: sbb crypto_sign_ed25519_amd64_64_ORDER3,<t3=int64#9
+# asm 2: sbb crypto_sign_ed25519_amd64_64_ORDER3,<t3=%r11
+sbb crypto_sign_ed25519_amd64_64_ORDER3(%rip),%r11
+
+# qhasm: r0 = t0 if !unsigned<
+# asm 1: cmovae <t0=int64#4,<r0=int64#3
+# asm 2: cmovae <t0=%rcx,<r0=%rdx
+cmovae %rcx,%rdx
+
+# qhasm: r1 = t1 if !unsigned<
+# asm 1: cmovae <t1=int64#6,<r1=int64#5
+# asm 2: cmovae <t1=%r9,<r1=%r8
+cmovae %r9,%r8
+
+# qhasm: r2 = t2 if !unsigned<
+# asm 1: cmovae <t2=int64#8,<r2=int64#7
+# asm 2: cmovae <t2=%r10,<r2=%rax
+cmovae %r10,%rax
+
+# qhasm: r3 = t3 if !unsigned<
+# asm 1: cmovae <t3=int64#9,<r3=int64#2
+# asm 2: cmovae <t3=%r11,<r3=%rsi
+cmovae %r11,%rsi
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#3,0(<rp=int64#1)
+# asm 2: movq <r0=%rdx,0(<rp=%rdi)
+movq %rdx,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#5,8(<rp=int64#1)
+# asm 2: movq <r1=%r8,8(<rp=%rdi)
+movq %r8,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#7,16(<rp=int64#1)
+# asm 2: movq <r2=%rax,16(<rp=%rdi)
+movq %rax,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#2,24(<rp=int64#1)
+# asm 2: movq <r3=%rsi,24(<rp=%rdi)
+movq %rsi,24(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/sc25519_from32bytes.c b/ext/ed25519-amd64-asm/sc25519_from32bytes.c
new file mode 100644
index 00000000..7f21e686
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_from32bytes.c
@@ -0,0 +1,55 @@
+#include "sc25519.h"
+
+/*Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493
+ * = 7237005577332262213973186563042994240857116359379907606001950938285454250989
+ */
+
+/* Contains order, 2*order, 4*order, 8*order, each represented in 4 consecutive unsigned long long */
+static const unsigned long long order[16] = {0x5812631A5CF5D3EDULL, 0x14DEF9DEA2F79CD6ULL,
+ 0x0000000000000000ULL, 0x1000000000000000ULL,
+ 0xB024C634B9EBA7DAULL, 0x29BDF3BD45EF39ACULL,
+ 0x0000000000000000ULL, 0x2000000000000000ULL,
+ 0x60498C6973D74FB4ULL, 0x537BE77A8BDE7359ULL,
+ 0x0000000000000000ULL, 0x4000000000000000ULL,
+ 0xC09318D2E7AE9F68ULL, 0xA6F7CEF517BCE6B2ULL,
+ 0x0000000000000000ULL, 0x8000000000000000ULL};
+
+static unsigned long long smaller(unsigned long long a,unsigned long long b)
+{
+ unsigned long long atop = a >> 32;
+ unsigned long long abot = a & 4294967295;
+ unsigned long long btop = b >> 32;
+ unsigned long long bbot = b & 4294967295;
+ unsigned long long atopbelowbtop = (atop - btop) >> 63;
+ unsigned long long atopeqbtop = ((atop ^ btop) - 1) >> 63;
+ unsigned long long abotbelowbbot = (abot - bbot) >> 63;
+ return atopbelowbtop | (atopeqbtop & abotbelowbbot);
+}
+
+void sc25519_from32bytes(sc25519 *r, const unsigned char x[32])
+{
+ unsigned long long t[4];
+ unsigned long long b;
+ unsigned long long mask;
+ int i, j;
+
+ /* assuming little-endian */
+ r->v[0] = *(unsigned long long *)x;
+ r->v[1] = *(((unsigned long long *)x)+1);
+ r->v[2] = *(((unsigned long long *)x)+2);
+ r->v[3] = *(((unsigned long long *)x)+3);
+
+ for(j=3;j>=0;j--)
+ {
+ b=0;
+ for(i=0;i<4;i++)
+ {
+ b += order[4*j+i]; /* no overflow for this particular order */
+ t[i] = r->v[i] - b;
+ b = smaller(r->v[i],b);
+ }
+ mask = b - 1;
+ for(i=0;i<4;i++)
+ r->v[i] ^= mask & (r->v[i] ^ t[i]);
+ }
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_from64bytes.c b/ext/ed25519-amd64-asm/sc25519_from64bytes.c
new file mode 100644
index 00000000..8e76a1b3
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_from64bytes.c
@@ -0,0 +1,7 @@
+#include "sc25519.h"
+
+void sc25519_from64bytes(sc25519 *r, const unsigned char x[64])
+{
+ /* assuming little-endian representation of unsigned long long */
+ sc25519_barrett(r, (unsigned long long *)x);
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_from_shortsc.c b/ext/ed25519-amd64-asm/sc25519_from_shortsc.c
new file mode 100644
index 00000000..3b8ff2fb
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_from_shortsc.c
@@ -0,0 +1,9 @@
+#include "sc25519.h"
+
+void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x)
+{
+ r->v[0] = x->v[0];
+ r->v[1] = x->v[1];
+ r->v[2] = 0;
+ r->v[3] = 0;
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_iszero.c b/ext/ed25519-amd64-asm/sc25519_iszero.c
new file mode 100644
index 00000000..21f593d7
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_iszero.c
@@ -0,0 +1,10 @@
+#include "sc25519.h"
+
+int sc25519_iszero_vartime(const sc25519 *x)
+{
+ if(x->v[0] != 0) return 0;
+ if(x->v[1] != 0) return 0;
+ if(x->v[2] != 0) return 0;
+ if(x->v[3] != 0) return 0;
+ return 1;
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_lt.s b/ext/ed25519-amd64-asm/sc25519_lt.s
new file mode 100644
index 00000000..3ba43178
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_lt.s
@@ -0,0 +1,131 @@
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: int64 ret
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: output ret
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 doof
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_lt
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_sc25519_lt
+.globl crypto_sign_ed25519_amd64_64_sc25519_lt
+_crypto_sign_ed25519_amd64_64_sc25519_lt:
+crypto_sign_ed25519_amd64_64_sc25519_lt:
+mov %rsp,%r11
+and $31,%r11
+add $0,%r11
+sub %r11,%rsp
+
+# qhasm: t0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#1),>t0=int64#3
+# asm 2: movq 0(<xp=%rdi),>t0=%rdx
+movq 0(%rdi),%rdx
+
+# qhasm: t1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#1),>t1=int64#4
+# asm 2: movq 8(<xp=%rdi),>t1=%rcx
+movq 8(%rdi),%rcx
+
+# qhasm: t2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#1),>t2=int64#5
+# asm 2: movq 16(<xp=%rdi),>t2=%r8
+movq 16(%rdi),%r8
+
+# qhasm: t3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#1),>t3=int64#1
+# asm 2: movq 24(<xp=%rdi),>t3=%rdi
+movq 24(%rdi),%rdi
+
+# qhasm: carry? t0 -= *(uint64 *)(yp + 0)
+# asm 1: subq 0(<yp=int64#2),<t0=int64#3
+# asm 2: subq 0(<yp=%rsi),<t0=%rdx
+subq 0(%rsi),%rdx
+
+# qhasm: carry? t1 -= *(uint64 *)(yp + 8) - carry
+# asm 1: sbbq 8(<yp=int64#2),<t1=int64#4
+# asm 2: sbbq 8(<yp=%rsi),<t1=%rcx
+sbbq 8(%rsi),%rcx
+
+# qhasm: carry? t2 -= *(uint64 *)(yp + 16) - carry
+# asm 1: sbbq 16(<yp=int64#2),<t2=int64#5
+# asm 2: sbbq 16(<yp=%rsi),<t2=%r8
+sbbq 16(%rsi),%r8
+
+# qhasm: carry? t3 -= *(uint64 *)(yp + 24) - carry
+# asm 1: sbbq 24(<yp=int64#2),<t3=int64#1
+# asm 2: sbbq 24(<yp=%rsi),<t3=%rdi
+sbbq 24(%rsi),%rdi
+
+# qhasm: ret = 0
+# asm 1: mov $0,>ret=int64#1
+# asm 2: mov $0,>ret=%rdi
+mov $0,%rdi
+
+# qhasm: doof = 1
+# asm 1: mov $1,>doof=int64#2
+# asm 2: mov $1,>doof=%rsi
+mov $1,%rsi
+
+# qhasm: ret = doof if carry
+# asm 1: cmovc <doof=int64#2,<ret=int64#1
+# asm 2: cmovc <doof=%rsi,<ret=%rdi
+cmovc %rsi,%rdi
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/sc25519_mul.c b/ext/ed25519-amd64-asm/sc25519_mul.c
new file mode 100644
index 00000000..ca4d5baa
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_mul.c
@@ -0,0 +1,12 @@
+#include "sc25519.h"
+
+#define ull4_mul crypto_sign_ed25519_amd64_64_ull4_mul
+
+extern void ull4_mul(unsigned long long r[8], const unsigned long long x[4], const unsigned long long y[4]);
+
+void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y)
+{
+ unsigned long long t[8];
+ ull4_mul(t, x->v, y->v);
+ sc25519_barrett(r, t);
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_mul_shortsc.c b/ext/ed25519-amd64-asm/sc25519_mul_shortsc.c
new file mode 100644
index 00000000..0c67250d
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_mul_shortsc.c
@@ -0,0 +1,9 @@
+#include "sc25519.h"
+
+void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y)
+{
+ /* XXX: This wants to be faster */
+ sc25519 t;
+ sc25519_from_shortsc(&t, y);
+ sc25519_mul(r, x, &t);
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_slide.c b/ext/ed25519-amd64-asm/sc25519_slide.c
new file mode 100644
index 00000000..4e52010d
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_slide.c
@@ -0,0 +1,49 @@
+#include "sc25519.h"
+
+void sc25519_slide(signed char r[256], const sc25519 *s, int swindowsize)
+{
+ int i,j,k,b,m=(1<<(swindowsize-1))-1, soplen=256;
+ unsigned long long sv0 = s->v[0];
+ unsigned long long sv1 = s->v[1];
+ unsigned long long sv2 = s->v[2];
+ unsigned long long sv3 = s->v[3];
+
+ /* first put the binary expansion into r */
+ for(i=0;i<64;i++) {
+ r[i] = sv0 & 1;
+ r[i+64] = sv1 & 1;
+ r[i+128] = sv2 & 1;
+ r[i+192] = sv3 & 1;
+ sv0 >>= 1;
+ sv1 >>= 1;
+ sv2 >>= 1;
+ sv3 >>= 1;
+ }
+
+ /* Making it sliding window */
+ for (j = 0;j < soplen;++j)
+ {
+ if (r[j]) {
+ for (b = 1;b < soplen - j && b <= 6;++b) {
+ if (r[j] + (r[j + b] << b) <= m)
+ {
+ r[j] += r[j + b] << b; r[j + b] = 0;
+ }
+ else if (r[j] - (r[j + b] << b) >= -m)
+ {
+ r[j] -= r[j + b] << b;
+ for (k = j + b;k < soplen;++k)
+ {
+ if (!r[k]) {
+ r[k] = 1;
+ break;
+ }
+ r[k] = 0;
+ }
+ }
+ else if (r[j + b])
+ break;
+ }
+ }
+ }
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_sub_nored.s b/ext/ed25519-amd64-asm/sc25519_sub_nored.s
new file mode 100644
index 00000000..a347e7d4
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_sub_nored.s
@@ -0,0 +1,142 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 t0
+
+# qhasm: int64 t1
+
+# qhasm: int64 t2
+
+# qhasm: int64 t3
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_sc25519_sub_nored
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_sc25519_sub_nored
+.globl crypto_sign_ed25519_amd64_64_sc25519_sub_nored
+_crypto_sign_ed25519_amd64_64_sc25519_sub_nored:
+crypto_sign_ed25519_amd64_64_sc25519_sub_nored:
+mov %rsp,%r11
+and $31,%r11
+add $0,%r11
+sub %r11,%rsp
+
+# qhasm: r0 = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>r0=int64#4
+# asm 2: movq 0(<xp=%rsi),>r0=%rcx
+movq 0(%rsi),%rcx
+
+# qhasm: r1 = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>r1=int64#5
+# asm 2: movq 8(<xp=%rsi),>r1=%r8
+movq 8(%rsi),%r8
+
+# qhasm: r2 = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>r2=int64#6
+# asm 2: movq 16(<xp=%rsi),>r2=%r9
+movq 16(%rsi),%r9
+
+# qhasm: r3 = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>r3=int64#2
+# asm 2: movq 24(<xp=%rsi),>r3=%rsi
+movq 24(%rsi),%rsi
+
+# qhasm: carry? r0 -= *(uint64 *)(yp + 0)
+# asm 1: subq 0(<yp=int64#3),<r0=int64#4
+# asm 2: subq 0(<yp=%rdx),<r0=%rcx
+subq 0(%rdx),%rcx
+
+# qhasm: carry? r1 -= *(uint64 *)(yp + 8) - carry
+# asm 1: sbbq 8(<yp=int64#3),<r1=int64#5
+# asm 2: sbbq 8(<yp=%rdx),<r1=%r8
+sbbq 8(%rdx),%r8
+
+# qhasm: carry? r2 -= *(uint64 *)(yp + 16) - carry
+# asm 1: sbbq 16(<yp=int64#3),<r2=int64#6
+# asm 2: sbbq 16(<yp=%rdx),<r2=%r9
+sbbq 16(%rdx),%r9
+
+# qhasm: r3 -= *(uint64 *)(yp + 24) - carry
+# asm 1: sbbq 24(<yp=int64#3),<r3=int64#2
+# asm 2: sbbq 24(<yp=%rdx),<r3=%rsi
+sbbq 24(%rdx),%rsi
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#4,0(<rp=int64#1)
+# asm 2: movq <r0=%rcx,0(<rp=%rdi)
+movq %rcx,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#5,8(<rp=int64#1)
+# asm 2: movq <r1=%r8,8(<rp=%rdi)
+movq %r8,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#6,16(<rp=int64#1)
+# asm 2: movq <r2=%r9,16(<rp=%rdi)
+movq %r9,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#2,24(<rp=int64#1)
+# asm 2: movq <r3=%rsi,24(<rp=%rdi)
+movq %rsi,24(%rdi)
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/ed25519-amd64-asm/sc25519_to32bytes.c b/ext/ed25519-amd64-asm/sc25519_to32bytes.c
new file mode 100644
index 00000000..eddb235d
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_to32bytes.c
@@ -0,0 +1,8 @@
+#include "sc25519.h"
+
+void sc25519_to32bytes(unsigned char r[32], const sc25519 *x)
+{
+ /* assuming little-endian */
+ int i;
+ for(i=0;i<32;i++) r[i] = i[(unsigned char *)x->v];
+}
diff --git a/ext/ed25519-amd64-asm/sc25519_window4.c b/ext/ed25519-amd64-asm/sc25519_window4.c
new file mode 100644
index 00000000..683a1d4b
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sc25519_window4.c
@@ -0,0 +1,27 @@
+#include "sc25519.h"
+
+void sc25519_window4(signed char r[64], const sc25519 *s)
+{
+ char carry;
+ int i;
+ for(i=0;i<16;i++)
+ r[i] = (s->v[0] >> (4*i)) & 15;
+ for(i=0;i<16;i++)
+ r[i+16] = (s->v[1] >> (4*i)) & 15;
+ for(i=0;i<16;i++)
+ r[i+32] = (s->v[2] >> (4*i)) & 15;
+ for(i=0;i<16;i++)
+ r[i+48] = (s->v[3] >> (4*i)) & 15;
+
+ /* Making it signed */
+ carry = 0;
+ for(i=0;i<63;i++)
+ {
+ r[i] += carry;
+ r[i+1] += r[i] >> 4;
+ r[i] &= 15;
+ carry = r[i] >> 3;
+ r[i] -= carry << 4;
+ }
+ r[63] += carry;
+}
diff --git a/ext/ed25519-amd64-asm/sign.c b/ext/ed25519-amd64-asm/sign.c
new file mode 100644
index 00000000..958e4a14
--- /dev/null
+++ b/ext/ed25519-amd64-asm/sign.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <string.h>
+/*#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"*/
+#include "ge25519.h"
+
+/* Original */
+#if 0
+int crypto_sign(
+ unsigned char *sm,unsigned long long *smlen,
+ const unsigned char *m,unsigned long long mlen,
+ const unsigned char *sk
+ )
+{
+ unsigned char pk[32];
+ unsigned char az[64];
+ unsigned char nonce[64];
+ unsigned char hram[64];
+ sc25519 sck, scs, scsk;
+ ge25519 ger;
+
+ memmove(pk,sk + 32,32);
+ /* pk: 32-byte public key A */
+
+ crypto_hash_sha512(az,sk,32);
+ az[0] &= 248;
+ az[31] &= 127;
+ az[31] |= 64;
+ /* az: 32-byte scalar a, 32-byte randomizer z */
+
+ *smlen = mlen + 64;
+ memmove(sm + 64,m,mlen);
+ memmove(sm + 32,az + 32,32);
+ /* sm: 32-byte uninit, 32-byte z, mlen-byte m */
+
+ crypto_hash_sha512(nonce, sm+32, mlen+32);
+ /* nonce: 64-byte H(z,m) */
+
+ sc25519_from64bytes(&sck, nonce);
+ ge25519_scalarmult_base(&ger, &sck);
+ ge25519_pack(sm, &ger);
+ /* sm: 32-byte R, 32-byte z, mlen-byte m */
+
+ memmove(sm + 32,pk,32);
+ /* sm: 32-byte R, 32-byte A, mlen-byte m */
+
+ crypto_hash_sha512(hram,sm,mlen + 64);
+ /* hram: 64-byte H(R,A,m) */
+
+ sc25519_from64bytes(&scs, hram);
+ sc25519_from32bytes(&scsk, az);
+ sc25519_mul(&scs, &scs, &scsk);
+ sc25519_add(&scs, &scs, &sck);
+ /* scs: S = nonce + H(R,A,m)a */
+
+ sc25519_to32bytes(sm + 32,&scs);
+ /* sm: 32-byte R, 32-byte S, mlen-byte m */
+
+ return 0;
+}
+#endif
+
+#if 0
+void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPublic,const void *msg,unsigned int len,void *signature)
+{
+ sc25519 sck, scs, scsk;
+ ge25519 ger;
+ unsigned char r[32];
+ unsigned char s[32];
+ unsigned char extsk[64];
+ unsigned char hmg[crypto_hash_sha512_BYTES];
+ unsigned char hram[crypto_hash_sha512_BYTES];
+ unsigned char *sig = (unsigned char *)signature;
+ unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg)
+
+ SHA512::hash(digest,msg,len);
+
+ SHA512::hash(extsk,myPrivate.data + 32,32);
+ extsk[0] &= 248;
+ extsk[31] &= 127;
+ extsk[31] |= 64;
+
+ for(unsigned int i=0;i<32;i++)
+ sig[32 + i] = extsk[32 + i];
+ for(unsigned int i=0;i<32;i++)
+ sig[64 + i] = digest[i];
+
+ SHA512::hash(hmg,sig + 32,64);
+
+ /* Computation of R */
+ sc25519_from64bytes(&sck, hmg);
+ ge25519_scalarmult_base(&ger, &sck);
+ ge25519_pack(r, &ger);
+
+ /* Computation of s */
+ for(unsigned int i=0;i<32;i++)
+ sig[i] = r[i];
+
+ get_hram(hram,sig,myPublic.data + 32,sig,96);
+
+ sc25519_from64bytes(&scs, hram);
+ sc25519_from32bytes(&scsk, extsk);
+ sc25519_mul(&scs, &scs, &scsk);
+
+ sc25519_add(&scs, &scs, &sck);
+
+ sc25519_to32bytes(s,&scs); /* cat s */
+ for(unsigned int i=0;i<32;i++)
+ sig[32 + i] = s[i];
+}
+
+void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
+{
+ unsigned long long i;
+
+ for (i = 0;i < 32;++i) playground[i] = sm[i];
+ for (i = 32;i < 64;++i) playground[i] = pk[i-32];
+ for (i = 64;i < smlen;++i) playground[i] = sm[i];
+
+ //crypto_hash_sha512(hram,playground,smlen);
+ ZeroTier::SHA512::hash(hram,playground,(unsigned int)smlen);
+}
+#endif
+
+extern void ZT_sha512internal(void *digest,const void *data,unsigned int len);
+
+extern void ed25519_amd64_asm_sign(const unsigned char *sk,const unsigned char *pk,const unsigned char *m,const unsigned int mlen,unsigned char *sig)
+{
+ unsigned char az[64];
+ unsigned char nonce[64];
+ unsigned char hram[64];
+ sc25519 sck, scs, scsk;
+ ge25519 ger;
+ unsigned char digest[64];
+ unsigned int i;
+
+ ZT_sha512internal(digest,m,mlen);
+
+ ZT_sha512internal(az,sk,32);
+ az[0] &= 248;
+ az[31] &= 127;
+ az[31] |= 64;
+
+ for(i=0;i<32;i++)
+ sig[32 + i] = az[32 + i];
+ for(i=0;i<32;i++)
+ sig[64 + i] = digest[i];
+
+ ZT_sha512internal(nonce,sig + 32,64);
+
+ sc25519_from64bytes(&sck, nonce);
+ ge25519_scalarmult_base(&ger, &sck);
+ ge25519_pack(sig, &ger);
+
+ memmove(sig + 32,pk,32);
+
+ ZT_sha512internal(hram,sig,96);
+
+ sc25519_from64bytes(&scs, hram);
+ sc25519_from32bytes(&scsk, az);
+ sc25519_mul(&scs, &scs, &scsk);
+ sc25519_add(&scs, &scs, &sck);
+
+ sc25519_to32bytes(sig + 32,&scs);
+}
diff --git a/ext/ed25519-amd64-asm/ull4_mul.s b/ext/ed25519-amd64-asm/ull4_mul.s
new file mode 100644
index 00000000..9f7b4fa2
--- /dev/null
+++ b/ext/ed25519-amd64-asm/ull4_mul.s
@@ -0,0 +1,716 @@
+
+# qhasm: int64 rp
+
+# qhasm: int64 xp
+
+# qhasm: int64 yp
+
+# qhasm: input rp
+
+# qhasm: input xp
+
+# qhasm: input yp
+
+# qhasm: int64 r0
+
+# qhasm: int64 r1
+
+# qhasm: int64 r2
+
+# qhasm: int64 r3
+
+# qhasm: int64 r4
+
+# qhasm: int64 r5
+
+# qhasm: int64 r6
+
+# qhasm: int64 r7
+
+# qhasm: int64 c
+
+# qhasm: int64 zero
+
+# qhasm: int64 rax
+
+# qhasm: int64 rdx
+
+# qhasm: int64 caller1
+
+# qhasm: int64 caller2
+
+# qhasm: int64 caller3
+
+# qhasm: int64 caller4
+
+# qhasm: int64 caller5
+
+# qhasm: int64 caller6
+
+# qhasm: int64 caller7
+
+# qhasm: caller caller1
+
+# qhasm: caller caller2
+
+# qhasm: caller caller3
+
+# qhasm: caller caller4
+
+# qhasm: caller caller5
+
+# qhasm: caller caller6
+
+# qhasm: caller caller7
+
+# qhasm: stack64 caller1_stack
+
+# qhasm: stack64 caller2_stack
+
+# qhasm: stack64 caller3_stack
+
+# qhasm: stack64 caller4_stack
+
+# qhasm: stack64 caller5_stack
+
+# qhasm: stack64 caller6_stack
+
+# qhasm: stack64 caller7_stack
+
+# qhasm: enter crypto_sign_ed25519_amd64_64_ull4_mul
+.text
+.p2align 5
+.globl _crypto_sign_ed25519_amd64_64_ull4_mul
+.globl crypto_sign_ed25519_amd64_64_ull4_mul
+_crypto_sign_ed25519_amd64_64_ull4_mul:
+crypto_sign_ed25519_amd64_64_ull4_mul:
+mov %rsp,%r11
+and $31,%r11
+add $64,%r11
+sub %r11,%rsp
+
+# qhasm: caller1_stack = caller1
+# asm 1: movq <caller1=int64#9,>caller1_stack=stack64#1
+# asm 2: movq <caller1=%r11,>caller1_stack=0(%rsp)
+movq %r11,0(%rsp)
+
+# qhasm: caller2_stack = caller2
+# asm 1: movq <caller2=int64#10,>caller2_stack=stack64#2
+# asm 2: movq <caller2=%r12,>caller2_stack=8(%rsp)
+movq %r12,8(%rsp)
+
+# qhasm: caller3_stack = caller3
+# asm 1: movq <caller3=int64#11,>caller3_stack=stack64#3
+# asm 2: movq <caller3=%r13,>caller3_stack=16(%rsp)
+movq %r13,16(%rsp)
+
+# qhasm: caller4_stack = caller4
+# asm 1: movq <caller4=int64#12,>caller4_stack=stack64#4
+# asm 2: movq <caller4=%r14,>caller4_stack=24(%rsp)
+movq %r14,24(%rsp)
+
+# qhasm: caller5_stack = caller5
+# asm 1: movq <caller5=int64#13,>caller5_stack=stack64#5
+# asm 2: movq <caller5=%r15,>caller5_stack=32(%rsp)
+movq %r15,32(%rsp)
+
+# qhasm: caller6_stack = caller6
+# asm 1: movq <caller6=int64#14,>caller6_stack=stack64#6
+# asm 2: movq <caller6=%rbx,>caller6_stack=40(%rsp)
+movq %rbx,40(%rsp)
+
+# qhasm: caller7_stack = caller7
+# asm 1: movq <caller7=int64#15,>caller7_stack=stack64#7
+# asm 2: movq <caller7=%rbp,>caller7_stack=48(%rsp)
+movq %rbp,48(%rsp)
+
+# qhasm: yp = yp
+# asm 1: mov <yp=int64#3,>yp=int64#4
+# asm 2: mov <yp=%rdx,>yp=%rcx
+mov %rdx,%rcx
+
+# qhasm: r4 = 0
+# asm 1: mov $0,>r4=int64#5
+# asm 2: mov $0,>r4=%r8
+mov $0,%r8
+
+# qhasm: r5 = 0
+# asm 1: mov $0,>r5=int64#6
+# asm 2: mov $0,>r5=%r9
+mov $0,%r9
+
+# qhasm: r6 = 0
+# asm 1: mov $0,>r6=int64#8
+# asm 2: mov $0,>r6=%r10
+mov $0,%r10
+
+# qhasm: r7 = 0
+# asm 1: mov $0,>r7=int64#9
+# asm 2: mov $0,>r7=%r11
+mov $0,%r11
+
+# qhasm: zero = 0
+# asm 1: mov $0,>zero=int64#10
+# asm 2: mov $0,>zero=%r12
+mov $0,%r12
+
+# qhasm: rax = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>rax=int64#7
+# asm 2: movq 0(<xp=%rsi),>rax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0)
+# asm 1: mulq 0(<yp=int64#4)
+# asm 2: mulq 0(<yp=%rcx)
+mulq 0(%rcx)
+
+# qhasm: r0 = rax
+# asm 1: mov <rax=int64#7,>r0=int64#11
+# asm 2: mov <rax=%rax,>r0=%r13
+mov %rax,%r13
+
+# qhasm: c = rdx
+# asm 1: mov <rdx=int64#3,>c=int64#12
+# asm 2: mov <rdx=%rdx,>c=%r14
+mov %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>rax=int64#7
+# asm 2: movq 0(<xp=%rsi),>rax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8)
+# asm 1: mulq 8(<yp=int64#4)
+# asm 2: mulq 8(<yp=%rcx)
+mulq 8(%rcx)
+
+# qhasm: r1 = rax
+# asm 1: mov <rax=int64#7,>r1=int64#13
+# asm 2: mov <rax=%rax,>r1=%r15
+mov %rax,%r15
+
+# qhasm: carry? r1 += c
+# asm 1: add <c=int64#12,<r1=int64#13
+# asm 2: add <c=%r14,<r1=%r15
+add %r14,%r15
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>rax=int64#7
+# asm 2: movq 0(<xp=%rsi),>rax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16)
+# asm 1: mulq 16(<yp=int64#4)
+# asm 2: mulq 16(<yp=%rcx)
+mulq 16(%rcx)
+
+# qhasm: r2 = rax
+# asm 1: mov <rax=int64#7,>r2=int64#14
+# asm 2: mov <rax=%rax,>r2=%rbx
+mov %rax,%rbx
+
+# qhasm: carry? r2 += c
+# asm 1: add <c=int64#12,<r2=int64#14
+# asm 2: add <c=%r14,<r2=%rbx
+add %r14,%rbx
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 0)
+# asm 1: movq 0(<xp=int64#2),>rax=int64#7
+# asm 2: movq 0(<xp=%rsi),>rax=%rax
+movq 0(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24)
+# asm 1: mulq 24(<yp=int64#4)
+# asm 2: mulq 24(<yp=%rcx)
+mulq 24(%rcx)
+
+# qhasm: r3 = rax
+# asm 1: mov <rax=int64#7,>r3=int64#15
+# asm 2: mov <rax=%rax,>r3=%rbp
+mov %rax,%rbp
+
+# qhasm: carry? r3 += c
+# asm 1: add <c=int64#12,<r3=int64#15
+# asm 2: add <c=%r14,<r3=%rbp
+add %r14,%rbp
+
+# qhasm: r4 += rdx + carry
+# asm 1: adc <rdx=int64#3,<r4=int64#5
+# asm 2: adc <rdx=%rdx,<r4=%r8
+adc %rdx,%r8
+
+# qhasm: rax = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>rax=int64#7
+# asm 2: movq 8(<xp=%rsi),>rax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0)
+# asm 1: mulq 0(<yp=int64#4)
+# asm 2: mulq 0(<yp=%rcx)
+mulq 0(%rcx)
+
+# qhasm: carry? r1 += rax
+# asm 1: add <rax=int64#7,<r1=int64#13
+# asm 2: add <rax=%rax,<r1=%r15
+add %rax,%r15
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>rax=int64#7
+# asm 2: movq 8(<xp=%rsi),>rax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8)
+# asm 1: mulq 8(<yp=int64#4)
+# asm 2: mulq 8(<yp=%rcx)
+mulq 8(%rcx)
+
+# qhasm: carry? r2 += rax
+# asm 1: add <rax=int64#7,<r2=int64#14
+# asm 2: add <rax=%rax,<r2=%rbx
+add %rax,%rbx
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r2 += c
+# asm 1: add <c=int64#12,<r2=int64#14
+# asm 2: add <c=%r14,<r2=%rbx
+add %r14,%rbx
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>rax=int64#7
+# asm 2: movq 8(<xp=%rsi),>rax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16)
+# asm 1: mulq 16(<yp=int64#4)
+# asm 2: mulq 16(<yp=%rcx)
+mulq 16(%rcx)
+
+# qhasm: carry? r3 += rax
+# asm 1: add <rax=int64#7,<r3=int64#15
+# asm 2: add <rax=%rax,<r3=%rbp
+add %rax,%rbp
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r3 += c
+# asm 1: add <c=int64#12,<r3=int64#15
+# asm 2: add <c=%r14,<r3=%rbp
+add %r14,%rbp
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 8)
+# asm 1: movq 8(<xp=int64#2),>rax=int64#7
+# asm 2: movq 8(<xp=%rsi),>rax=%rax
+movq 8(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24)
+# asm 1: mulq 24(<yp=int64#4)
+# asm 2: mulq 24(<yp=%rcx)
+mulq 24(%rcx)
+
+# qhasm: carry? r4 += rax
+# asm 1: add <rax=int64#7,<r4=int64#5
+# asm 2: add <rax=%rax,<r4=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r4 += c
+# asm 1: add <c=int64#12,<r4=int64#5
+# asm 2: add <c=%r14,<r4=%r8
+add %r14,%r8
+
+# qhasm: r5 += rdx + carry
+# asm 1: adc <rdx=int64#3,<r5=int64#6
+# asm 2: adc <rdx=%rdx,<r5=%r9
+adc %rdx,%r9
+
+# qhasm: rax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>rax=int64#7
+# asm 2: movq 16(<xp=%rsi),>rax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0)
+# asm 1: mulq 0(<yp=int64#4)
+# asm 2: mulq 0(<yp=%rcx)
+mulq 0(%rcx)
+
+# qhasm: carry? r2 += rax
+# asm 1: add <rax=int64#7,<r2=int64#14
+# asm 2: add <rax=%rax,<r2=%rbx
+add %rax,%rbx
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>rax=int64#7
+# asm 2: movq 16(<xp=%rsi),>rax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8)
+# asm 1: mulq 8(<yp=int64#4)
+# asm 2: mulq 8(<yp=%rcx)
+mulq 8(%rcx)
+
+# qhasm: carry? r3 += rax
+# asm 1: add <rax=int64#7,<r3=int64#15
+# asm 2: add <rax=%rax,<r3=%rbp
+add %rax,%rbp
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r3 += c
+# asm 1: add <c=int64#12,<r3=int64#15
+# asm 2: add <c=%r14,<r3=%rbp
+add %r14,%rbp
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>rax=int64#7
+# asm 2: movq 16(<xp=%rsi),>rax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16)
+# asm 1: mulq 16(<yp=int64#4)
+# asm 2: mulq 16(<yp=%rcx)
+mulq 16(%rcx)
+
+# qhasm: carry? r4 += rax
+# asm 1: add <rax=int64#7,<r4=int64#5
+# asm 2: add <rax=%rax,<r4=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r4 += c
+# asm 1: add <c=int64#12,<r4=int64#5
+# asm 2: add <c=%r14,<r4=%r8
+add %r14,%r8
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 16)
+# asm 1: movq 16(<xp=int64#2),>rax=int64#7
+# asm 2: movq 16(<xp=%rsi),>rax=%rax
+movq 16(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24)
+# asm 1: mulq 24(<yp=int64#4)
+# asm 2: mulq 24(<yp=%rcx)
+mulq 24(%rcx)
+
+# qhasm: carry? r5 += rax
+# asm 1: add <rax=int64#7,<r5=int64#6
+# asm 2: add <rax=%rax,<r5=%r9
+add %rax,%r9
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r5 += c
+# asm 1: add <c=int64#12,<r5=int64#6
+# asm 2: add <c=%r14,<r5=%r9
+add %r14,%r9
+
+# qhasm: r6 += rdx + carry
+# asm 1: adc <rdx=int64#3,<r6=int64#8
+# asm 2: adc <rdx=%rdx,<r6=%r10
+adc %rdx,%r10
+
+# qhasm: rax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>rax=int64#7
+# asm 2: movq 24(<xp=%rsi),>rax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 0)
+# asm 1: mulq 0(<yp=int64#4)
+# asm 2: mulq 0(<yp=%rcx)
+mulq 0(%rcx)
+
+# qhasm: carry? r3 += rax
+# asm 1: add <rax=int64#7,<r3=int64#15
+# asm 2: add <rax=%rax,<r3=%rbp
+add %rax,%rbp
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>rax=int64#7
+# asm 2: movq 24(<xp=%rsi),>rax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 8)
+# asm 1: mulq 8(<yp=int64#4)
+# asm 2: mulq 8(<yp=%rcx)
+mulq 8(%rcx)
+
+# qhasm: carry? r4 += rax
+# asm 1: add <rax=int64#7,<r4=int64#5
+# asm 2: add <rax=%rax,<r4=%r8
+add %rax,%r8
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r4 += c
+# asm 1: add <c=int64#12,<r4=int64#5
+# asm 2: add <c=%r14,<r4=%r8
+add %r14,%r8
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>rax=int64#7
+# asm 2: movq 24(<xp=%rsi),>rax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 16)
+# asm 1: mulq 16(<yp=int64#4)
+# asm 2: mulq 16(<yp=%rcx)
+mulq 16(%rcx)
+
+# qhasm: carry? r5 += rax
+# asm 1: add <rax=int64#7,<r5=int64#6
+# asm 2: add <rax=%rax,<r5=%r9
+add %rax,%r9
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r5 += c
+# asm 1: add <c=int64#12,<r5=int64#6
+# asm 2: add <c=%r14,<r5=%r9
+add %r14,%r9
+
+# qhasm: c = 0
+# asm 1: mov $0,>c=int64#12
+# asm 2: mov $0,>c=%r14
+mov $0,%r14
+
+# qhasm: c += rdx + carry
+# asm 1: adc <rdx=int64#3,<c=int64#12
+# asm 2: adc <rdx=%rdx,<c=%r14
+adc %rdx,%r14
+
+# qhasm: rax = *(uint64 *)(xp + 24)
+# asm 1: movq 24(<xp=int64#2),>rax=int64#7
+# asm 2: movq 24(<xp=%rsi),>rax=%rax
+movq 24(%rsi),%rax
+
+# qhasm: (uint128) rdx rax = rax * *(uint64 *)(yp + 24)
+# asm 1: mulq 24(<yp=int64#4)
+# asm 2: mulq 24(<yp=%rcx)
+mulq 24(%rcx)
+
+# qhasm: carry? r6 += rax
+# asm 1: add <rax=int64#7,<r6=int64#8
+# asm 2: add <rax=%rax,<r6=%r10
+add %rax,%r10
+
+# qhasm: rdx += zero + carry
+# asm 1: adc <zero=int64#10,<rdx=int64#3
+# asm 2: adc <zero=%r12,<rdx=%rdx
+adc %r12,%rdx
+
+# qhasm: carry? r6 += c
+# asm 1: add <c=int64#12,<r6=int64#8
+# asm 2: add <c=%r14,<r6=%r10
+add %r14,%r10
+
+# qhasm: r7 += rdx + carry
+# asm 1: adc <rdx=int64#3,<r7=int64#9
+# asm 2: adc <rdx=%rdx,<r7=%r11
+adc %rdx,%r11
+
+# qhasm: *(uint64 *)(rp + 0) = r0
+# asm 1: movq <r0=int64#11,0(<rp=int64#1)
+# asm 2: movq <r0=%r13,0(<rp=%rdi)
+movq %r13,0(%rdi)
+
+# qhasm: *(uint64 *)(rp + 8) = r1
+# asm 1: movq <r1=int64#13,8(<rp=int64#1)
+# asm 2: movq <r1=%r15,8(<rp=%rdi)
+movq %r15,8(%rdi)
+
+# qhasm: *(uint64 *)(rp + 16) = r2
+# asm 1: movq <r2=int64#14,16(<rp=int64#1)
+# asm 2: movq <r2=%rbx,16(<rp=%rdi)
+movq %rbx,16(%rdi)
+
+# qhasm: *(uint64 *)(rp + 24) = r3
+# asm 1: movq <r3=int64#15,24(<rp=int64#1)
+# asm 2: movq <r3=%rbp,24(<rp=%rdi)
+movq %rbp,24(%rdi)
+
+# qhasm: *(uint64 *)(rp + 32) = r4
+# asm 1: movq <r4=int64#5,32(<rp=int64#1)
+# asm 2: movq <r4=%r8,32(<rp=%rdi)
+movq %r8,32(%rdi)
+
+# qhasm: *(uint64 *)(rp + 40) = r5
+# asm 1: movq <r5=int64#6,40(<rp=int64#1)
+# asm 2: movq <r5=%r9,40(<rp=%rdi)
+movq %r9,40(%rdi)
+
+# qhasm: *(uint64 *)(rp + 48) = r6
+# asm 1: movq <r6=int64#8,48(<rp=int64#1)
+# asm 2: movq <r6=%r10,48(<rp=%rdi)
+movq %r10,48(%rdi)
+
+# qhasm: *(uint64 *)(rp + 56) = r7
+# asm 1: movq <r7=int64#9,56(<rp=int64#1)
+# asm 2: movq <r7=%r11,56(<rp=%rdi)
+movq %r11,56(%rdi)
+
+# qhasm: caller1 = caller1_stack
+# asm 1: movq <caller1_stack=stack64#1,>caller1=int64#9
+# asm 2: movq <caller1_stack=0(%rsp),>caller1=%r11
+movq 0(%rsp),%r11
+
+# qhasm: caller2 = caller2_stack
+# asm 1: movq <caller2_stack=stack64#2,>caller2=int64#10
+# asm 2: movq <caller2_stack=8(%rsp),>caller2=%r12
+movq 8(%rsp),%r12
+
+# qhasm: caller3 = caller3_stack
+# asm 1: movq <caller3_stack=stack64#3,>caller3=int64#11
+# asm 2: movq <caller3_stack=16(%rsp),>caller3=%r13
+movq 16(%rsp),%r13
+
+# qhasm: caller4 = caller4_stack
+# asm 1: movq <caller4_stack=stack64#4,>caller4=int64#12
+# asm 2: movq <caller4_stack=24(%rsp),>caller4=%r14
+movq 24(%rsp),%r14
+
+# qhasm: caller5 = caller5_stack
+# asm 1: movq <caller5_stack=stack64#5,>caller5=int64#13
+# asm 2: movq <caller5_stack=32(%rsp),>caller5=%r15
+movq 32(%rsp),%r15
+
+# qhasm: caller6 = caller6_stack
+# asm 1: movq <caller6_stack=stack64#6,>caller6=int64#14
+# asm 2: movq <caller6_stack=40(%rsp),>caller6=%rbx
+movq 40(%rsp),%rbx
+
+# qhasm: caller7 = caller7_stack
+# asm 1: movq <caller7_stack=stack64#7,>caller7=int64#15
+# asm 2: movq <caller7_stack=48(%rsp),>caller7=%rbp
+movq 48(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+mov %rdi,%rax
+mov %rsi,%rdx
+ret
diff --git a/ext/http-parser/http_parser.c b/ext/http-parser/http_parser.c
index 3c896ffa..895bf0c7 100644
--- a/ext/http-parser/http_parser.c
+++ b/ext/http-parser/http_parser.c
@@ -1366,12 +1366,7 @@ reexecute:
|| c != CONTENT_LENGTH[parser->index]) {
parser->header_state = h_general;
} else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
- if (parser->flags & F_CONTENTLENGTH) {
- SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
- goto error;
- }
parser->header_state = h_content_length;
- parser->flags |= F_CONTENTLENGTH;
}
break;
@@ -1474,6 +1469,12 @@ reexecute:
goto error;
}
+ if (parser->flags & F_CONTENTLENGTH) {
+ SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
+ goto error;
+ }
+
+ parser->flags |= F_CONTENTLENGTH;
parser->content_length = ch - '0';
break;
diff --git a/ext/http-parser/http_parser.h b/ext/http-parser/http_parser.h
index 105ae510..45c72a07 100644
--- a/ext/http-parser/http_parser.h
+++ b/ext/http-parser/http_parser.h
@@ -27,7 +27,7 @@ extern "C" {
/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 7
-#define HTTP_PARSER_VERSION_PATCH 0
+#define HTTP_PARSER_VERSION_PATCH 1
#include <sys/types.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
@@ -90,6 +90,76 @@ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
typedef int (*http_cb) (http_parser*);
+/* Status Codes */
+#define HTTP_STATUS_MAP(XX) \
+ XX(100, CONTINUE, Continue) \
+ XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
+ XX(102, PROCESSING, Processing) \
+ XX(200, OK, OK) \
+ XX(201, CREATED, Created) \
+ XX(202, ACCEPTED, Accepted) \
+ XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
+ XX(204, NO_CONTENT, No Content) \
+ XX(205, RESET_CONTENT, Reset Content) \
+ XX(206, PARTIAL_CONTENT, Partial Content) \
+ XX(207, MULTI_STATUS, Multi-Status) \
+ XX(208, ALREADY_REPORTED, Already Reported) \
+ XX(226, IM_USED, IM Used) \
+ XX(300, MULTIPLE_CHOICES, Multiple Choices) \
+ XX(301, MOVED_PERMANENTLY, Moved Permanently) \
+ XX(302, FOUND, Found) \
+ XX(303, SEE_OTHER, See Other) \
+ XX(304, NOT_MODIFIED, Not Modified) \
+ XX(305, USE_PROXY, Use Proxy) \
+ XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
+ XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
+ XX(400, BAD_REQUEST, Bad Request) \
+ XX(401, UNAUTHORIZED, Unauthorized) \
+ XX(402, PAYMENT_REQUIRED, Payment Required) \
+ XX(403, FORBIDDEN, Forbidden) \
+ XX(404, NOT_FOUND, Not Found) \
+ XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
+ XX(406, NOT_ACCEPTABLE, Not Acceptable) \
+ XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
+ XX(408, REQUEST_TIMEOUT, Request Timeout) \
+ XX(409, CONFLICT, Conflict) \
+ XX(410, GONE, Gone) \
+ XX(411, LENGTH_REQUIRED, Length Required) \
+ XX(412, PRECONDITION_FAILED, Precondition Failed) \
+ XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
+ XX(414, URI_TOO_LONG, URI Too Long) \
+ XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
+ XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
+ XX(417, EXPECTATION_FAILED, Expectation Failed) \
+ XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
+ XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
+ XX(423, LOCKED, Locked) \
+ XX(424, FAILED_DEPENDENCY, Failed Dependency) \
+ XX(426, UPGRADE_REQUIRED, Upgrade Required) \
+ XX(428, PRECONDITION_REQUIRED, Precondition Required) \
+ XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
+ XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
+ XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
+ XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
+ XX(501, NOT_IMPLEMENTED, Not Implemented) \
+ XX(502, BAD_GATEWAY, Bad Gateway) \
+ XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
+ XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
+ XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
+ XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
+ XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
+ XX(508, LOOP_DETECTED, Loop Detected) \
+ XX(510, NOT_EXTENDED, Not Extended) \
+ XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
+
+enum http_status
+ {
+#define XX(num, name, string) HTTP_STATUS_##name = num,
+ HTTP_STATUS_MAP(XX)
+#undef XX
+ };
+
+
/* Request Methods */
#define HTTP_METHOD_MAP(XX) \
XX(0, DELETE, DELETE) \
diff --git a/ext/installfiles/linux/zerotier-containerized/Dockerfile b/ext/installfiles/linux/zerotier-containerized/Dockerfile
new file mode 100644
index 00000000..85faace0
--- /dev/null
+++ b/ext/installfiles/linux/zerotier-containerized/Dockerfile
@@ -0,0 +1,20 @@
+FROM alpine:latest
+MAINTAINER Adam Ierymenko <adam.ierymenko@zerotier.com>
+
+LABEL version="1.2.4"
+LABEL description="Containerized ZeroTier One for use on CoreOS or other Docker-only Linux hosts."
+
+# Uncomment to build in container
+#RUN apk add --update alpine-sdk linux-headers
+
+RUN apk add --update libgcc libstdc++
+
+ADD zerotier-one /
+RUN chmod 0755 /zerotier-one
+RUN ln -sf /zerotier-one /zerotier-cli
+RUN mkdir -p /var/lib/zerotier-one
+
+ADD main.sh /
+RUN chmod 0755 /main.sh
+
+ENTRYPOINT /main.sh
diff --git a/ext/installfiles/linux/zerotier-containerized/main.sh b/ext/installfiles/linux/zerotier-containerized/main.sh
new file mode 100755
index 00000000..685a6891
--- /dev/null
+++ b/ext/installfiles/linux/zerotier-containerized/main.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin
+
+if [ ! -e /dev/net/tun ]; then
+ echo 'FATAL: cannot start ZeroTier One in container: /dev/net/tun not present.'
+ exit 1
+fi
+
+exec /zerotier-one
diff --git a/ext/installfiles/mac-update/updater.tmpl.sh b/ext/installfiles/mac-update/updater.tmpl.sh
new file mode 100644
index 00000000..0b07f6d9
--- /dev/null
+++ b/ext/installfiles/mac-update/updater.tmpl.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+export PATH=/bin:/usr/bin:/sbin:/usr/sbin
+shopt -s expand_aliases
+
+if [ "$UID" -ne 0 ]; then
+ echo '*** Auto-updater must be run as root.'
+ exit 1
+fi
+
+scriptPath="`dirname "$0"`/`basename "$0"`"
+if [ ! -s "$scriptPath" ]; then
+ scriptPath="$0"
+ if [ ! -s "$scriptPath" ]; then
+ echo "*** Auto-updater cannot determine its own path; $scriptPath is not readable."
+ exit 2
+ fi
+fi
+
+endMarkerIndex=`grep -a -b -E '^################' "$scriptPath" | head -c 16 | cut -d : -f 1`
+if [ "$endMarkerIndex" -le 100 ]; then
+ echo 'Internal error: unable to find end of script / start of binary data marker.'
+ exit 2
+fi
+blobStart=`expr $endMarkerIndex + 17`
+if [ "$blobStart" -le "$endMarkerIndex" ]; then
+ echo 'Internal error: unable to find end of script / start of binary data marker.'
+ exit 2
+fi
+
+rm -f /tmp/ZeroTierOne-update.pkg
+tail -c +$blobStart "$scriptPath" >/tmp/ZeroTierOne-update.pkg
+chmod 0600 /tmp/ZeroTierOne-update.pkg
+
+if [ -s /tmp/ZeroTierOne-update.pkg ]; then
+ rm -f '/Library/Application Support/ZeroTier/One/latest-update.exe' '/Library/Application Support/ZeroTier/One/latest-update.json' /tmp/ZeroTierOne-update.log
+ installer -verbose -pkg /tmp/ZeroTierOne-update.pkg -target / >/tmp/ZeroTierOne-update.log 2>&1
+ rm -f /tmp/ZeroTierOne-update.pkg
+ exit 0
+else
+ echo '*** Error self-unpacking update!'
+ exit 3
+fi
+
+# Do not remove the last line or add a carriage return to it! The installer
+# looks for an unterminated line beginning with 16 #'s in itself to find
+# the binary blob data, which is appended after it.
+
+################ \ No newline at end of file
diff --git a/ext/installfiles/mac/ZeroTier One.pkgproj b/ext/installfiles/mac/ZeroTier One.pkgproj
index d9730527..59c22dde 100755
--- a/ext/installfiles/mac/ZeroTier One.pkgproj
+++ b/ext/installfiles/mac/ZeroTier One.pkgproj
@@ -37,7 +37,7 @@
<key>GID</key>
<integer>80</integer>
<key>PATH</key>
- <string>mac-ui-macgap1-wrapper/bin/ZeroTier One.app</string>
+ <string>../../../macui/build/Release/ZeroTier One.app</string>
<key>PATH_TYPE</key>
<integer>1</integer>
<key>PERMISSIONS</key>
@@ -123,119 +123,6 @@
</dict>
<dict>
<key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui/index.html</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui/main.js</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui/react.min.js</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui/simpleajax.min.js</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui/zerotier.css</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui/ztui.min.js</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>ui</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>2</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
<array/>
<key>GID</key>
<integer>0</integer>
@@ -726,6 +613,12 @@
</dict>
<key>PAYLOAD_TYPE</key>
<integer>0</integer>
+ <key>SHOW_INVISIBLE</key>
+ <false/>
+ <key>SPLIT_FORKS</key>
+ <true/>
+ <key>TREAT_MISSING_FILES_AS_WARNING</key>
+ <false/>
<key>VERSION</key>
<integer>3</integer>
</dict>
@@ -754,12 +647,24 @@
<integer>1</integer>
<key>CONCLUSION_ACTION</key>
<integer>0</integer>
+ <key>FOLLOW_SYMBOLIC_LINKS</key>
+ <false/>
<key>IDENTIFIER</key>
<string>com.zerotier.pkg.ZeroTierOne</string>
+ <key>LOCATION</key>
+ <integer>0</integer>
+ <key>NAME</key>
+ <string></string>
<key>OVERWRITE_PERMISSIONS</key>
<false/>
+ <key>PAYLOAD_SIZE</key>
+ <integer>-1</integer>
+ <key>RELOCATABLE</key>
+ <false/>
+ <key>USE_HFS+_COMPRESSION</key>
+ <false/>
<key>VERSION</key>
- <string>1.1.14</string>
+ <string>1.2.6</string>
</dict>
<key>PROJECT_COMMENTS</key>
<dict>
@@ -773,7 +678,7 @@
ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
- b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE0MDQuNDciPgo8c3R5bGUg
+ b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE1MDQuNzYiPgo8c3R5bGUg
dHlwZT0idGV4dC9jc3MiPgpwLnAxIHttYXJnaW46IDAuMHB4IDAu
MHB4IDAuMHB4IDAuMHB4OyBsaW5lLWhlaWdodDogMTQuMHB4OyBm
b250OiAxMi4wcHggSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsg
@@ -782,7 +687,7 @@
b2R5Pgo8cCBjbGFzcz0icDEiPjxzcGFuIGNsYXNzPSJzMSI+WmVy
b1RpZXIgT25lIC0gTmV0d29yayBWaXJ0dWFsaXphdGlvbiBFdmVy
eXdoZXJlPC9zcGFuPjwvcD4KPHAgY2xhc3M9InAxIj48c3BhbiBj
- bGFzcz0iczEiPihjKTIwMTEtMjAxNiBaZXJvVGllciwgSW5jLjwv
+ bGFzcz0iczEiPihjKTIwMTEtMjAxNyBaZXJvVGllciwgSW5jLjwv
c3Bhbj48L3A+CjxwIGNsYXNzPSJwMSI+PHNwYW4gY2xhc3M9InMx
Ij5jb250YWN0QHplcm90aWVyLmNvbTwvc3Bhbj48L3A+CjxwIGNs
YXNzPSJwMSI+PHNwYW4gY2xhc3M9InMxIj48YnI+Cjwvc3Bhbj48
@@ -975,6 +880,8 @@
</array>
<key>NAME</key>
<string>ZeroTier One</string>
+ <key>PAYLOAD_ONLY</key>
+ <false/>
</dict>
</dict>
<key>TYPE</key>
diff --git a/ext/installfiles/mac/launch.sh b/ext/installfiles/mac/launch.sh
index 41c4b9c8..b02a6670 100755
--- a/ext/installfiles/mac/launch.sh
+++ b/ext/installfiles/mac/launch.sh
@@ -1,7 +1,3 @@
#!/bin/bash
-
-zthome="/Library/Application Support/ZeroTier/One"
-export PATH="$zthome:/bin:/usr/bin:/sbin:/usr/sbin"
-
-# Launch ZeroTier One (not as daemon... launchd monitors it)
+export PATH="/Library/Application Support/ZeroTier/One:/bin:/usr/bin:/sbin:/usr/sbin"
exec zerotier-one
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist
deleted file mode 100644
index c67923c7..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Info.plist
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>BuildMachineOSBuild</key>
- <string>15B42</string>
- <key>CFBundleDevelopmentRegion</key>
- <string>en</string>
- <key>CFBundleExecutable</key>
- <string>ZeroTier One</string>
- <key>CFBundleIconFile</key>
- <string>ZeroTierIcon</string>
- <key>CFBundleIdentifier</key>
- <string>com.zerotier.ZeroTier-One</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>ZeroTier One</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.0</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleSupportedPlatforms</key>
- <array>
- <string>MacOSX</string>
- </array>
- <key>CFBundleVersion</key>
- <string>1</string>
- <key>DTCompiler</key>
- <string>com.apple.compilers.llvm.clang.1_0</string>
- <key>DTPlatformBuild</key>
- <string>7B1005</string>
- <key>DTPlatformVersion</key>
- <string>GM</string>
- <key>DTSDKBuild</key>
- <string>15A278</string>
- <key>DTSDKName</key>
- <string>macosx10.11</string>
- <key>DTXcode</key>
- <string>0711</string>
- <key>DTXcodeBuild</key>
- <string>7B1005</string>
- <key>LSApplicationCategoryType</key>
- <string>public.app-category.utilities</string>
- <key>LSMinimumSystemVersion</key>
- <string>10.7</string>
- <key>NSAppTransportSecurity</key>
- <dict>
- <key>NSAllowsArbitraryLoads</key>
- <true/>
- </dict>
- <key>NSMainNibFile</key>
- <string>MainMenu</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
-</dict>
-</plist>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One
deleted file mode 100755
index 8e38b861..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/MacOS/ZeroTier One
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo
deleted file mode 100644
index bd04210f..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/PkgInfo
+++ /dev/null
@@ -1 +0,0 @@
-APPL???? \ No newline at end of file
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icns b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icns
deleted file mode 100644
index 17e60d58..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/ZeroTierIcon.icns
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf
deleted file mode 100644
index 6f388f66..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Credits.rtf
+++ /dev/null
@@ -1,13 +0,0 @@
-{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\vieww9600\viewh8400\viewkind0
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\b\fs24 \cf0 (c)2011-2015 ZeroTier, Inc.\
-Licensed under the GNU GPLv3\
-\
-UI Wrapper MacGap (c) Twitter, Inc.\
-Licensed under the MIT License\
-http://macgap.com/\
-} \ No newline at end of file
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.strings b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.strings
deleted file mode 100644
index 5e45963c..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/InfoPlist.strings
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib
deleted file mode 100644
index bac7faa7..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/MainMenu.nib
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib
deleted file mode 100644
index e7b174a1..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/Resources/en.lproj/Window.nib
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources b/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources
deleted file mode 100644
index 5e334db0..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/bin/ZeroTier One.app/Contents/_CodeSignature/CodeResources
+++ /dev/null
@@ -1,187 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>files</key>
- <dict>
- <key>Resources/ZeroTierIcon.icns</key>
- <data>
- 430Gd+4+jnim7WxXEEugp6G+Tgk=
- </data>
- <key>Resources/en.lproj/Credits.rtf</key>
- <dict>
- <key>hash</key>
- <data>
- ePttkAH2X1GJ6OL0UhDBAktxB3Y=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- <key>Resources/en.lproj/InfoPlist.strings</key>
- <dict>
- <key>hash</key>
- <data>
- MiLKDDnrUKr4EmuvhS5VQwxHGK8=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- <key>Resources/en.lproj/MainMenu.nib</key>
- <dict>
- <key>hash</key>
- <data>
- 8JZXf4/3df3LD+o74Y8WM0dV8io=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- <key>Resources/en.lproj/Window.nib</key>
- <dict>
- <key>hash</key>
- <data>
- aP0mIANPPnnTMmxYlELioz9ZO1I=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- </dict>
- <key>files2</key>
- <dict>
- <key>Resources/ZeroTierIcon.icns</key>
- <data>
- 430Gd+4+jnim7WxXEEugp6G+Tgk=
- </data>
- <key>Resources/en.lproj/Credits.rtf</key>
- <dict>
- <key>hash</key>
- <data>
- ePttkAH2X1GJ6OL0UhDBAktxB3Y=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- <key>Resources/en.lproj/InfoPlist.strings</key>
- <dict>
- <key>hash</key>
- <data>
- MiLKDDnrUKr4EmuvhS5VQwxHGK8=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- <key>Resources/en.lproj/MainMenu.nib</key>
- <dict>
- <key>hash</key>
- <data>
- 8JZXf4/3df3LD+o74Y8WM0dV8io=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- <key>Resources/en.lproj/Window.nib</key>
- <dict>
- <key>hash</key>
- <data>
- aP0mIANPPnnTMmxYlELioz9ZO1I=
- </data>
- <key>optional</key>
- <true/>
- </dict>
- </dict>
- <key>rules</key>
- <dict>
- <key>^Resources/</key>
- <true/>
- <key>^Resources/.*\.lproj/</key>
- <dict>
- <key>optional</key>
- <true/>
- <key>weight</key>
- <real>1000</real>
- </dict>
- <key>^Resources/.*\.lproj/locversion.plist$</key>
- <dict>
- <key>omit</key>
- <true/>
- <key>weight</key>
- <real>1100</real>
- </dict>
- <key>^version.plist$</key>
- <true/>
- </dict>
- <key>rules2</key>
- <dict>
- <key>.*\.dSYM($|/)</key>
- <dict>
- <key>weight</key>
- <real>11</real>
- </dict>
- <key>^(.*/)?\.DS_Store$</key>
- <dict>
- <key>omit</key>
- <true/>
- <key>weight</key>
- <real>2000</real>
- </dict>
- <key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
- <dict>
- <key>nested</key>
- <true/>
- <key>weight</key>
- <real>10</real>
- </dict>
- <key>^.*</key>
- <true/>
- <key>^Info\.plist$</key>
- <dict>
- <key>omit</key>
- <true/>
- <key>weight</key>
- <real>20</real>
- </dict>
- <key>^PkgInfo$</key>
- <dict>
- <key>omit</key>
- <true/>
- <key>weight</key>
- <real>20</real>
- </dict>
- <key>^Resources/</key>
- <dict>
- <key>weight</key>
- <real>20</real>
- </dict>
- <key>^Resources/.*\.lproj/</key>
- <dict>
- <key>optional</key>
- <true/>
- <key>weight</key>
- <real>1000</real>
- </dict>
- <key>^Resources/.*\.lproj/locversion.plist$</key>
- <dict>
- <key>omit</key>
- <true/>
- <key>weight</key>
- <real>1100</real>
- </dict>
- <key>^[^/]+$</key>
- <dict>
- <key>nested</key>
- <true/>
- <key>weight</key>
- <real>10</real>
- </dict>
- <key>^embedded\.provisionprofile$</key>
- <dict>
- <key>weight</key>
- <real>20</real>
- </dict>
- <key>^version\.plist$</key>
- <dict>
- <key>weight</key>
- <real>20</real>
- </dict>
- </dict>
-</dict>
-</plist>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/LICENSE b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/LICENSE
deleted file mode 100644
index c7fd4a4a..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-MacGap was ported from phonegap-mac, and is under the same license (MIT)
-
-The MIT License
-*****************
-
-Copyright (c) <2012> <Nitobi Software Inc., et. al., >
-
- 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.
-
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj
deleted file mode 100644
index 775c5964..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,489 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */ = {isa = PBXBuildFile; fileRef = 1495814E15C15CCC00E1CFE5 /* Notice.m */; };
- 6F169DA718CC332E005EDDF3 /* Command.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA618CC332E005EDDF3 /* Command.m */; };
- 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */; };
- 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */; };
- 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */; };
- 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DB018CD906F005EDDF3 /* MenuProxy.m */; };
- 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD672B518FE618E00C0DAAD /* UserDefaults.m */; };
- 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */; };
- 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 88746BED14CCA435001E160E /* JSEventHelper.m */; };
- 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0645F14BDE10A00E4BCE2 /* Window.m */; };
- 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88C0646414BDEC5800E4BCE2 /* Window.xib */; };
- 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0646C14BDF6A600E4BCE2 /* WindowController.m */; };
- C14EFCA71B0986AF00894B5F /* ZeroTierIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = C14EFCA61B0986AF00894B5F /* ZeroTierIcon.icns */; };
- C1C2B9911AFB0CF10060D7C2 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1C2B9901AFB0CF10060D7C2 /* Security.framework */; };
- F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = F2B80015179E0FC100B069A8 /* Clipboard.m */; };
- FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA32509C14BA813600BF0781 /* WebKit.framework */; };
- FA3250C314BA85E700BF0781 /* ContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BC14BA85E700BF0781 /* ContentView.m */; };
- FA3250C514BA85E700BF0781 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BE14BA85E700BF0781 /* Utils.m */; };
- FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C014BA85E700BF0781 /* WebViewDelegate.m */; };
- FA3250D314BA860800BF0781 /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C914BA860800BF0781 /* App.m */; };
- FA3250D514BA860800BF0781 /* Dock.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CB14BA860800BF0781 /* Dock.m */; };
- FA3250D914BA860800BF0781 /* Path.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CF14BA860800BF0781 /* Path.m */; };
- FA3250DB14BA860800BF0781 /* Sound.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250D114BA860800BF0781 /* Sound.m */; };
- FA3F7742168F70790027B324 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA3F7741168F70780027B324 /* Cocoa.framework */; };
- FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAE451C714BA79C600190544 /* InfoPlist.strings */; };
- FAE451CB14BA79C600190544 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451CA14BA79C600190544 /* main.m */; };
- FAE451CF14BA79C600190544 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = FAE451CD14BA79C600190544 /* Credits.rtf */; };
- FAE451D214BA79C600190544 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451D114BA79C600190544 /* AppDelegate.m */; };
- FAE451D514BA79C600190544 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAE451D314BA79C600190544 /* MainMenu.xib */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- FA3250DD14BA876F00BF0781 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
- 1495814D15C15CCC00E1CFE5 /* Notice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Notice.h; path = Classes/Commands/Notice.h; sourceTree = "<group>"; };
- 1495814E15C15CCC00E1CFE5 /* Notice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Notice.m; path = Classes/Commands/Notice.m; sourceTree = "<group>"; };
- 6F169DA518CC332E005EDDF3 /* Command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Command.h; path = Classes/Commands/Command.h; sourceTree = "<group>"; };
- 6F169DA618CC332E005EDDF3 /* Command.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Command.m; path = Classes/Commands/Command.m; sourceTree = "<group>"; };
- 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallbackDelegate.h; path = Classes/CallbackDelegate.h; sourceTree = "<group>"; };
- 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CallbackDelegate.m; path = Classes/CallbackDelegate.m; sourceTree = "<group>"; };
- 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
- 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuItemProxy.h; path = Classes/Commands/MenuItemProxy.h; sourceTree = "<group>"; };
- 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuItemProxy.m; path = Classes/Commands/MenuItemProxy.m; sourceTree = "<group>"; };
- 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuProxy.h; path = Classes/Commands/MenuProxy.h; sourceTree = "<group>"; };
- 6F169DB018CD906F005EDDF3 /* MenuProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuProxy.m; path = Classes/Commands/MenuProxy.m; sourceTree = "<group>"; };
- 6FD672B418FE618E00C0DAAD /* UserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserDefaults.h; path = Classes/Commands/UserDefaults.h; sourceTree = "<group>"; };
- 6FD672B518FE618E00C0DAAD /* UserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UserDefaults.m; path = Classes/Commands/UserDefaults.m; sourceTree = "<group>"; };
- 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fonts.h; path = Classes/Commands/fonts.h; sourceTree = "<group>"; };
- 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = fonts.m; path = Classes/Commands/fonts.m; sourceTree = "<group>"; };
- 88746BEC14CCA435001E160E /* JSEventHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSEventHelper.h; path = Classes/JSEventHelper.h; sourceTree = "<group>"; };
- 88746BED14CCA435001E160E /* JSEventHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSEventHelper.m; path = Classes/JSEventHelper.m; sourceTree = "<group>"; };
- 88C0645E14BDE10A00E4BCE2 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Window.h; path = Classes/Window.h; sourceTree = "<group>"; };
- 88C0645F14BDE10A00E4BCE2 /* Window.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Window.m; path = Classes/Window.m; sourceTree = "<group>"; };
- 88C0646514BDEC5800E4BCE2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Window.xib; sourceTree = "<group>"; };
- 88C0646B14BDF6A600E4BCE2 /* WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowController.h; sourceTree = "<group>"; };
- 88C0646C14BDF6A600E4BCE2 /* WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WindowController.m; sourceTree = "<group>"; };
- C14EFCA61B0986AF00894B5F /* ZeroTierIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ZeroTierIcon.icns; path = ../../../../artwork/ZeroTierIcon.icns; sourceTree = "<group>"; };
- C1C2B9901AFB0CF10060D7C2 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
- F2B80014179E0FC100B069A8 /* Clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clipboard.h; sourceTree = "<group>"; };
- F2B80015179E0FC100B069A8 /* Clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Clipboard.m; sourceTree = "<group>"; };
- FA32509C14BA813600BF0781 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
- FA3250BA14BA85E700BF0781 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = Classes/Constants.h; sourceTree = "<group>"; };
- FA3250BB14BA85E700BF0781 /* ContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ContentView.h; path = Classes/ContentView.h; sourceTree = "<group>"; };
- FA3250BC14BA85E700BF0781 /* ContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ContentView.m; path = Classes/ContentView.m; sourceTree = "<group>"; };
- FA3250BD14BA85E700BF0781 /* Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = Classes/Utils.h; sourceTree = "<group>"; };
- FA3250BE14BA85E700BF0781 /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = Classes/Utils.m; sourceTree = "<group>"; };
- FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebViewDelegate.h; path = Classes/WebViewDelegate.h; sourceTree = "<group>"; };
- FA3250C014BA85E700BF0781 /* WebViewDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WebViewDelegate.m; path = Classes/WebViewDelegate.m; sourceTree = "<group>"; };
- FA3250C814BA860800BF0781 /* App.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = App.h; path = Classes/Commands/App.h; sourceTree = "<group>"; };
- FA3250C914BA860800BF0781 /* App.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = App.m; path = Classes/Commands/App.m; sourceTree = "<group>"; };
- FA3250CA14BA860800BF0781 /* Dock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dock.h; path = Classes/Commands/Dock.h; sourceTree = "<group>"; };
- FA3250CB14BA860800BF0781 /* Dock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Dock.m; path = Classes/Commands/Dock.m; sourceTree = "<group>"; };
- FA3250CE14BA860800BF0781 /* Path.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Path.h; path = Classes/Commands/Path.h; sourceTree = "<group>"; };
- FA3250CF14BA860800BF0781 /* Path.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Path.m; path = Classes/Commands/Path.m; sourceTree = "<group>"; };
- FA3250D014BA860800BF0781 /* Sound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Sound.h; path = Classes/Commands/Sound.h; sourceTree = "<group>"; };
- FA3250D114BA860800BF0781 /* Sound.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Sound.m; path = Classes/Commands/Sound.m; sourceTree = "<group>"; };
- FA3F7741168F70780027B324 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; };
- FAE451BA14BA79C600190544 /* ZeroTier One.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ZeroTier One.app"; sourceTree = BUILT_PRODUCTS_DIR; };
- FAE451BE14BA79C600190544 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
- FAE451C114BA79C600190544 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
- FAE451C214BA79C600190544 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
- FAE451C314BA79C600190544 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
- FAE451C614BA79C600190544 /* MacGap-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MacGap-Info.plist"; sourceTree = "<group>"; };
- FAE451C814BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
- FAE451CA14BA79C600190544 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
- FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MacGap-Prefix.pch"; sourceTree = "<group>"; };
- FAE451CE14BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
- FAE451D014BA79C600190544 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
- FAE451D114BA79C600190544 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
- FAE451D414BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- FAE451B714BA79C600190544 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- C1C2B9911AFB0CF10060D7C2 /* Security.framework in Frameworks */,
- 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */,
- FA3F7742168F70790027B324 /* Cocoa.framework in Frameworks */,
- FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- FA3250E014BA87B800BF0781 /* Classes */ = {
- isa = PBXGroup;
- children = (
- FA3250E114BA87DD00BF0781 /* Commands */,
- FA3250BA14BA85E700BF0781 /* Constants.h */,
- 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */,
- 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */,
- FA3250BB14BA85E700BF0781 /* ContentView.h */,
- FA3250BC14BA85E700BF0781 /* ContentView.m */,
- FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */,
- FA3250C014BA85E700BF0781 /* WebViewDelegate.m */,
- 88C0646B14BDF6A600E4BCE2 /* WindowController.h */,
- 88C0646C14BDF6A600E4BCE2 /* WindowController.m */,
- );
- name = Classes;
- sourceTree = "<group>";
- };
- FA3250E114BA87DD00BF0781 /* Commands */ = {
- isa = PBXGroup;
- children = (
- 6F169DA518CC332E005EDDF3 /* Command.h */,
- 6F169DA618CC332E005EDDF3 /* Command.m */,
- 1495814D15C15CCC00E1CFE5 /* Notice.h */,
- 1495814E15C15CCC00E1CFE5 /* Notice.m */,
- FA3250CA14BA860800BF0781 /* Dock.h */,
- FA3250CB14BA860800BF0781 /* Dock.m */,
- 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */,
- 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */,
- FA3250BD14BA85E700BF0781 /* Utils.h */,
- FA3250BE14BA85E700BF0781 /* Utils.m */,
- 6FD672B418FE618E00C0DAAD /* UserDefaults.h */,
- 6FD672B518FE618E00C0DAAD /* UserDefaults.m */,
- FA3250CE14BA860800BF0781 /* Path.h */,
- FA3250CF14BA860800BF0781 /* Path.m */,
- FA3250D014BA860800BF0781 /* Sound.h */,
- FA3250D114BA860800BF0781 /* Sound.m */,
- FA3250C814BA860800BF0781 /* App.h */,
- FA3250C914BA860800BF0781 /* App.m */,
- 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */,
- 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */,
- 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */,
- 6F169DB018CD906F005EDDF3 /* MenuProxy.m */,
- 88C0645E14BDE10A00E4BCE2 /* Window.h */,
- 88C0645F14BDE10A00E4BCE2 /* Window.m */,
- 88746BEC14CCA435001E160E /* JSEventHelper.h */,
- 88746BED14CCA435001E160E /* JSEventHelper.m */,
- F2B80014179E0FC100B069A8 /* Clipboard.h */,
- F2B80015179E0FC100B069A8 /* Clipboard.m */,
- );
- name = Commands;
- sourceTree = "<group>";
- };
- FAE451AF14BA79C600190544 = {
- isa = PBXGroup;
- children = (
- FA3F7741168F70780027B324 /* Cocoa.framework */,
- FAE451C414BA79C600190544 /* MacGap */,
- FAE451BD14BA79C600190544 /* Frameworks */,
- FAE451BB14BA79C600190544 /* Products */,
- );
- sourceTree = "<group>";
- };
- FAE451BB14BA79C600190544 /* Products */ = {
- isa = PBXGroup;
- children = (
- FAE451BA14BA79C600190544 /* ZeroTier One.app */,
- );
- name = Products;
- sourceTree = "<group>";
- };
- FAE451BD14BA79C600190544 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- C1C2B9901AFB0CF10060D7C2 /* Security.framework */,
- 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */,
- FA32509C14BA813600BF0781 /* WebKit.framework */,
- FAE451BE14BA79C600190544 /* Cocoa.framework */,
- FAE451C014BA79C600190544 /* Other Frameworks */,
- );
- name = Frameworks;
- sourceTree = "<group>";
- };
- FAE451C014BA79C600190544 /* Other Frameworks */ = {
- isa = PBXGroup;
- children = (
- FAE451C114BA79C600190544 /* AppKit.framework */,
- FAE451C214BA79C600190544 /* CoreData.framework */,
- FAE451C314BA79C600190544 /* Foundation.framework */,
- );
- name = "Other Frameworks";
- sourceTree = "<group>";
- };
- FAE451C414BA79C600190544 /* MacGap */ = {
- isa = PBXGroup;
- children = (
- FA3250E014BA87B800BF0781 /* Classes */,
- FAE451D014BA79C600190544 /* AppDelegate.h */,
- FAE451D114BA79C600190544 /* AppDelegate.m */,
- C14EFCA61B0986AF00894B5F /* ZeroTierIcon.icns */,
- FAE451D314BA79C600190544 /* MainMenu.xib */,
- 88C0646414BDEC5800E4BCE2 /* Window.xib */,
- FAE451C514BA79C600190544 /* Supporting Files */,
- );
- path = MacGap;
- sourceTree = "<group>";
- };
- FAE451C514BA79C600190544 /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- FAE451C614BA79C600190544 /* MacGap-Info.plist */,
- FAE451C714BA79C600190544 /* InfoPlist.strings */,
- FAE451CA14BA79C600190544 /* main.m */,
- FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */,
- FAE451CD14BA79C600190544 /* Credits.rtf */,
- );
- name = "Supporting Files";
- sourceTree = "<group>";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- FAE451B914BA79C600190544 /* MacGap */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */;
- buildPhases = (
- FAE451B814BA79C600190544 /* Resources */,
- FAE451B614BA79C600190544 /* Sources */,
- FAE451B714BA79C600190544 /* Frameworks */,
- FA3250DD14BA876F00BF0781 /* CopyFiles */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = MacGap;
- productName = MacGap;
- productReference = FAE451BA14BA79C600190544 /* ZeroTier One.app */;
- productType = "com.apple.product-type.application";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- FAE451B114BA79C600190544 /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastUpgradeCheck = 0710;
- ORGANIZATIONNAME = Twitter;
- };
- buildConfigurationList = FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- );
- mainGroup = FAE451AF14BA79C600190544;
- productRefGroup = FAE451BB14BA79C600190544 /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- FAE451B914BA79C600190544 /* MacGap */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- FAE451B814BA79C600190544 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- C14EFCA71B0986AF00894B5F /* ZeroTierIcon.icns in Resources */,
- FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */,
- FAE451CF14BA79C600190544 /* Credits.rtf in Resources */,
- FAE451D514BA79C600190544 /* MainMenu.xib in Resources */,
- 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- FAE451B614BA79C600190544 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */,
- FA3250D314BA860800BF0781 /* App.m in Sources */,
- FA3250D514BA860800BF0781 /* Dock.m in Sources */,
- FA3250D914BA860800BF0781 /* Path.m in Sources */,
- FA3250DB14BA860800BF0781 /* Sound.m in Sources */,
- FA3250C314BA85E700BF0781 /* ContentView.m in Sources */,
- FA3250C514BA85E700BF0781 /* Utils.m in Sources */,
- FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */,
- FAE451CB14BA79C600190544 /* main.m in Sources */,
- 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */,
- FAE451D214BA79C600190544 /* AppDelegate.m in Sources */,
- 6F169DA718CC332E005EDDF3 /* Command.m in Sources */,
- 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */,
- 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */,
- 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */,
- 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */,
- 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */,
- 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */,
- 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */,
- F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
- 88C0646414BDEC5800E4BCE2 /* Window.xib */ = {
- isa = PBXVariantGroup;
- children = (
- 88C0646514BDEC5800E4BCE2 /* en */,
- );
- name = Window.xib;
- sourceTree = "<group>";
- };
- FAE451C714BA79C600190544 /* InfoPlist.strings */ = {
- isa = PBXVariantGroup;
- children = (
- FAE451C814BA79C600190544 /* en */,
- );
- name = InfoPlist.strings;
- sourceTree = "<group>";
- };
- FAE451CD14BA79C600190544 /* Credits.rtf */ = {
- isa = PBXVariantGroup;
- children = (
- FAE451CE14BA79C600190544 /* en */,
- );
- name = Credits.rtf;
- sourceTree = "<group>";
- };
- FAE451D314BA79C600190544 /* MainMenu.xib */ = {
- isa = PBXVariantGroup;
- children = (
- FAE451D414BA79C600190544 /* en */,
- );
- name = MainMenu.xib;
- sourceTree = "<group>";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- FAE451D614BA79C600190544 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ENABLE_OBJC_ARC = YES;
- COPY_PHASE_STRIP = NO;
- ENABLE_TESTABILITY = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_VERSION = "";
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- ONLY_ACTIVE_ARCH = YES;
- PRODUCT_NAME = "ZeroTier One";
- SDKROOT = "";
- };
- name = Debug;
- };
- FAE451D714BA79C600190544 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ENABLE_OBJC_ARC = YES;
- COPY_PHASE_STRIP = YES;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
- GCC_VERSION = "";
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- PRODUCT_NAME = "ZeroTier One";
- SDKROOT = "";
- };
- name = Release;
- };
- FAE451D914BA79C600190544 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
- CLANG_CXX_LIBRARY = "compiler-default";
- COMBINE_HIDPI_IMAGES = YES;
- FRAMEWORK_SEARCH_PATHS = (
- "$(inherited)",
- "\"$(SRCROOT)/MacGap\"",
- );
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch";
- GCC_VERSION = "";
- INFOPLIST_FILE = "MacGap/MacGap-Info.plist";
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = "ZeroTier One";
- SDKROOT = macosx;
- WRAPPER_EXTENSION = app;
- };
- name = Debug;
- };
- FAE451DA14BA79C600190544 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
- CLANG_CXX_LIBRARY = "compiler-default";
- COMBINE_HIDPI_IMAGES = YES;
- FRAMEWORK_SEARCH_PATHS = (
- "$(inherited)",
- "\"$(SRCROOT)/MacGap\"",
- );
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch";
- GCC_VERSION = "";
- INFOPLIST_FILE = "MacGap/MacGap-Info.plist";
- MACOSX_DEPLOYMENT_TARGET = 10.7;
- PRODUCT_BUNDLE_IDENTIFIER = "com.zerotier.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = "ZeroTier One";
- SDKROOT = macosx;
- WRAPPER_EXTENSION = app;
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- FAE451D614BA79C600190544 /* Debug */,
- FAE451D714BA79C600190544 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- FAE451D914BA79C600190544 /* Debug */,
- FAE451DA14BA79C600190544 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = FAE451B114BA79C600190544 /* Project object */;
-}
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 88f36fc7..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
- version = "1.0">
- <FileRef
- location = "self:MacGap.xcodeproj">
- </FileRef>
-</Workspace>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout
deleted file mode 100644
index 7fdde853..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IDESourceControlProjectFavoriteDictionaryKey</key>
- <false/>
- <key>IDESourceControlProjectIdentifier</key>
- <string>4D486E78-E297-4CC3-AAAE-1A58EDAC87E6</string>
- <key>IDESourceControlProjectName</key>
- <string>MacGap</string>
- <key>IDESourceControlProjectOriginsDictionary</key>
- <dict>
- <key>ABA3617E9F0148F844A82502F0D808DE6591AA97</key>
- <string>http://adam.ierymenko@git.int.zerotier.com/zerotier/zerotierone</string>
- </dict>
- <key>IDESourceControlProjectPath</key>
- <string>ext/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj</string>
- <key>IDESourceControlProjectRelativeInstallPathDictionary</key>
- <dict>
- <key>ABA3617E9F0148F844A82502F0D808DE6591AA97</key>
- <string>../../../../..</string>
- </dict>
- <key>IDESourceControlProjectURL</key>
- <string>http://adam.ierymenko@git.int.zerotier.com/zerotier/zerotierone</string>
- <key>IDESourceControlProjectVersion</key>
- <integer>111</integer>
- <key>IDESourceControlProjectWCCIdentifier</key>
- <string>ABA3617E9F0148F844A82502F0D808DE6591AA97</string>
- <key>IDESourceControlProjectWCConfigurations</key>
- <array>
- <dict>
- <key>IDESourceControlRepositoryExtensionIdentifierKey</key>
- <string>public.vcs.git</string>
- <key>IDESourceControlWCCIdentifierKey</key>
- <string>ABA3617E9F0148F844A82502F0D808DE6591AA97</string>
- <key>IDESourceControlWCCName</key>
- <string>ZeroTierOne</string>
- </dict>
- </array>
-</dict>
-</plist>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index 20281812..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings
deleted file mode 100644
index 659c8766..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
- <true/>
- <key>SnapshotAutomaticallyBeforeSignificantChanges</key>
- <true/>
-</dict>
-</plist>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index 822ed3cb..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate
+++ /dev/null
Binary files differ
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings
deleted file mode 100644
index 6ff33e60..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
- <true/>
- <key>IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges</key>
- <true/>
-</dict>
-</plist>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h
deleted file mode 100644
index bf7370b5..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// AppDelegate.h
-// MacGap
-//
-// Created by Alex MacCaw on 08/01/2012.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import <Cocoa/Cocoa.h>
-#import "Classes/ContentView.h"
-
-#import "WindowController.h"
-
-@interface AppDelegate : NSObject <NSApplicationDelegate>
-
-@property (retain, nonatomic) WindowController *windowController;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m
deleted file mode 100644
index 45923bb3..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/AppDelegate.m
+++ /dev/null
@@ -1,159 +0,0 @@
-//
-// AppDelegate.m
-// MacGap
-//
-// Created by Alex MacCaw on 08/01/2012.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "AppDelegate.h"
-#include <sys/stat.h>
-#include <sys/types.h>
-
-@implementation AppDelegate
-
-@synthesize windowController;
-
-- (void) applicationWillFinishLaunching:(NSNotification *)aNotification
-{
-}
-
--(BOOL)applicationShouldHandleReopen:(NSApplication*)application
- hasVisibleWindows:(BOOL)visibleWindows{
- if(!visibleWindows){
- [self.windowController.window makeKeyAndOrderFront: nil];
- }
- return YES;
-}
-
-- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
- return YES;
-}
-
-- (void) applicationDidFinishLaunching:(NSNotification *)aNotification {
- char buf[16384],userAuthTokenPath[4096];
- struct stat systemAuthTokenStat,userAuthTokenStat;
-
- FILE *pf = fopen("/Library/Application Support/ZeroTier/One/zerotier-one.port","r");
- long port = 9993; // default
- if (pf) {
- long n = fread(buf,1,sizeof(buf)-1,pf);
- if (n > 0) {
- buf[n] = (char)0;
- port = strtol(buf,(char **)0,10);
- }
- fclose(pf);
- }
-
- char url[16384];
- memset(url,0,sizeof(url));
-
- const char *homeDir = getenv("HOME");
- if (homeDir) {
- snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir);
-
- bool userAuthTokenOutOfDate = false;
- memset(&systemAuthTokenStat,0,sizeof(systemAuthTokenStat));
- memset(&userAuthTokenStat,0,sizeof(userAuthTokenStat));
- if (stat("/Library/Application Support/ZeroTier/One/authtoken.secret",&systemAuthTokenStat) == 0) {
- if (stat(userAuthTokenPath,&userAuthTokenStat) == 0) {
- if (userAuthTokenStat.st_mtimespec.tv_sec < systemAuthTokenStat.st_mtimespec.tv_sec)
- userAuthTokenOutOfDate = true;
- }
- }
-
- if (!userAuthTokenOutOfDate) {
- pf = fopen(userAuthTokenPath,"r");
- if (pf) {
- long n = fread(buf,1,sizeof(buf)-1,pf);
- if (n > 0) {
- buf[n] = (char)0;
- snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf);
- }
- fclose(pf);
- }
- }
- }
-
- if (!url[0]) {
- // Create authorization reference
- OSStatus status;
- AuthorizationRef authorizationRef;
-
- // AuthorizationCreate and pass NULL as the initial
- // AuthorizationRights set so that the AuthorizationRef gets created
- // successfully, and then later call AuthorizationCopyRights to
- // determine or extend the allowable rights.
- // http://developer.apple.com/qa/qa2001/qa1172.html
- status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
- if (status != errAuthorizationSuccess)
- {
- NSLog(@"Error Creating Initial Authorization: %d", status);
- return;
- }
-
- // kAuthorizationRightExecute == "system.privilege.admin"
- AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
- AuthorizationRights rights = {1, &right};
- AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed |
- kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
-
- // Call AuthorizationCopyRights to determine or extend the allowable rights.
- status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL);
- if (status != errAuthorizationSuccess)
- {
- NSLog(@"Copy Rights Unsuccessful: %d", status);
- return;
- }
-
- // use rm tool with -rf
- char *tool = "/bin/cat";
- char *args[] = {"/Library/Application Support/ZeroTier/One/authtoken.secret", NULL};
- FILE *pipe = NULL;
-
- status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
- if (status != errAuthorizationSuccess)
- {
- NSLog(@"Error: %d", status);
- }
-
- if (pipe) {
- long n = (long)fread(buf,1,sizeof(buf)-1,pipe);
- if (n > 0) {
- buf[n] = (char)0;
- snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf);
-
- if (homeDir) {
- snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier",homeDir);
- mkdir(userAuthTokenPath,0755);
- snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One",homeDir);
- mkdir(userAuthTokenPath,0755);
- snprintf(userAuthTokenPath,sizeof(userAuthTokenPath),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",homeDir);
- pf = fopen(userAuthTokenPath,"w");
- if (pf) {
- fwrite(buf,1,strlen(buf),pf);
- fclose(pf);
- chmod(userAuthTokenPath,0600);
- }
- }
- }
- fclose(pipe);
- }
-
- // The only way to guarantee that a credential acquired when you
- // request a right is not shared with other authorization instances is
- // to destroy the credential. To do so, call the AuthorizationFree
- // function with the flag kAuthorizationFlagDestroyRights.
- // http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html
- status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights);
- }
-
- NSString *urlStr = [[NSString alloc] initWithCString:url];
- self.windowController = [[WindowController alloc] initWithURL: urlStr];
- [self.windowController showWindow: [NSApplication sharedApplication].delegate];
- self.windowController.contentView.webView.alphaValue = 1.0;
- self.windowController.contentView.alphaValue = 1.0;
- [self.windowController showWindow:self];
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h
deleted file mode 100755
index 0f31ee41..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// CallbackDelegate.h
-// MacGap
-//
-// Created by Joe Hildebrand on 1/10/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "Command.h"
-
-@interface CallbackDelegate : Command {
-}
-
-@property JSObjectRef callback;
-
-- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback;
-- (id) call;
-- (id) callWithParams:(id)firstOrNil, ... NS_REQUIRES_NIL_TERMINATION;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m
deleted file mode 100755
index 5ce8fbe3..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/CallbackDelegate.m
+++ /dev/null
@@ -1,168 +0,0 @@
-//
-// CallbackDelegate.m
-// MacGap
-//
-// Created by Joe Hildebrand on 1/10/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "CallbackDelegate.h"
-#import <JavaScriptCore/JavaScript.h>
-
-@implementation CallbackDelegate
-
-@synthesize callback;
-
-- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback
-{
- if (!aCallback)
- return nil;
- if ([aCallback isKindOfClass:[WebUndefined class]])
- return nil;
-
- self = [super initWithContext:aContext];
- if (!self)
- return nil;
-
- callback = [aCallback JSObject];
- JSValueProtect(context, callback);
- return self;
-}
-
-- (void) dealloc
-{
- if (callback)
- {
- JSValueUnprotect(context, callback);
- callback = nil;
- }
-}
-
-- (id) objectFromValue:(JSValueRef)val
-{
- JSStringRef jstr;
- NSString *rets;
-
- switch(JSValueGetType(context, val))
- {
- case kJSTypeUndefined:
- case kJSTypeNull:
- return nil;
- case kJSTypeBoolean:
- return [NSNumber numberWithBool:JSValueToBoolean(context, val)];
- case kJSTypeNumber:
- return [NSNumber numberWithDouble:JSValueToNumber(context, val, NULL)];
- case kJSTypeString:
- jstr = JSValueToStringCopy(context, val, NULL);
- size_t sz = JSStringGetMaximumUTF8CStringSize(jstr);
- char *buf = (char*)malloc(sz);
- JSStringGetUTF8CString(jstr, buf, sz);
- rets = [NSString stringWithUTF8String:buf];
- free(buf);
- return rets;
- case kJSTypeObject:
- // TODO: dictionary or something
- return nil;
- default:
- NSAssert(false, @"Invalid JavaScript type");
- return nil;
- }
-}
-
-- (JSValueRef) valueFromObject:(id)obj
-{
- JSValueRef val = nil;
- if (!obj)
- {
- val = JSValueMakeNull(context);
- }
- else if ([obj isKindOfClass:[NSString class]])
- {
- JSStringRef jstr = JSStringCreateWithUTF8CString([obj UTF8String]);
- val = JSValueMakeString(context, jstr);
- JSStringRelease(jstr);
- }
- else if ([obj isKindOfClass:[NSNumber class]])
- {
- val = JSValueMakeNumber(context, [obj doubleValue]);
- }
- else if ([obj isKindOfClass:[NSDictionary class]])
- {
- JSObjectRef o = JSObjectMake(context, NULL, NULL);
- for (NSString *key in obj)
- {
- JSStringRef kstr = JSStringCreateWithUTF8CString([key UTF8String]);
- JSValueRef v = [self valueFromObject:[obj objectForKey:key]];
-
- JSObjectSetProperty(context, o, kstr, v, kJSPropertyAttributeNone, NULL);
- JSStringRelease(kstr);
- }
- val = o;
- }
- else if ([obj isKindOfClass:[NSArray class]])
- {
- NSUInteger pcount = [obj count];
- JSValueRef jsArgs[pcount];
- NSUInteger i=0;
- for (id v in obj)
- {
- jsArgs[i++] = [self valueFromObject:v];
- }
- val = JSObjectMakeArray(context, pcount, jsArgs, NULL);
- }
- else if ([obj isKindOfClass:[NSDate class]])
- {
- NSTimeInterval secs = [obj timeIntervalSince1970];
- JSValueRef jsArgs[1];
- // call the Date(milliseconds) constructor in JS
- jsArgs[0] = JSValueMakeNumber(context, secs * 1000.0);
- val = JSObjectMakeDate(context, 1, jsArgs, NULL);
- }
- else
- {
- NSLog(@"Warning: unknown object type for: %@", obj);
- val = JSValueMakeUndefined(context);
- }
- return val;
-}
-
-- (id) call
-{
- NSAssert(callback, @"Callback required");
- if (!JSObjectIsFunction(context, callback))
- return nil;
-
- JSValueRef jsArgs[0];
- JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, 0, jsArgs, NULL);
- return [self objectFromValue:ret];
-}
-
-- (id) callWithParams:(id)firstOrNil, ...
-{
- NSAssert(callback, @"Callback required");
- if (!JSObjectIsFunction(context, callback))
- return nil;
- NSUInteger pcount = 0;
- id p;
- va_list args;
- va_start(args, firstOrNil);
- for (p=firstOrNil; p; p=va_arg(args, id))
- {
- pcount++;
- }
- va_end(args);
-
- JSValueRef jsArgs[pcount];
- NSUInteger j = 0;
- va_start(args, firstOrNil);
- for (p=firstOrNil; p; p=va_arg(args, id))
- {
- jsArgs[j++] = [self valueFromObject:p];
- }
- va_end(args);
-
- JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, j, jsArgs, NULL);
- return [self objectFromValue:ret];
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h
deleted file mode 100644
index f65ba61e..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#import <Foundation/Foundation.h>
-
-#import "WindowController.h"
-
-@interface App : NSObject {
-
-}
-
-@property (nonatomic, retain) WebView *webView;
-
-- (id) initWithWebView:(WebView *)view;
-
-- (void) terminate;
-- (void) activate;
-- (void) hide;
-- (void) unhide;
-- (void) beep;
-- (void) bounce;
-- (void) setCustomUserAgent:(NSString *)userAgentString;
-- (NSNumber*) systemIdleTime;
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m
deleted file mode 100644
index 6d47a17e..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/App.m
+++ /dev/null
@@ -1,128 +0,0 @@
-#import "App.h"
-
-#import "JSEventHelper.h"
-
-@implementation App
-
-@synthesize webView;
-
-- (id) initWithWebView:(WebView *) view{
- self = [super init];
-
- if (self) {
- self.webView = view;
- [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
- selector: @selector(receiveSleepNotification:)
- name: NSWorkspaceWillSleepNotification object: NULL];
- [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
- selector: @selector(receiveWakeNotification:)
- name: NSWorkspaceDidWakeNotification object: NULL];
- [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
- selector: @selector(receiveActivateNotification:)
- name: NSWorkspaceDidActivateApplicationNotification object: NULL];
- }
-
- return self;
-}
-
-- (void) terminate {
- [NSApp terminate:nil];
-}
-
-- (void) activate {
- [NSApp activateIgnoringOtherApps:YES];
-}
-
-- (void) hide {
- [NSApp hide:nil];
-}
-
-- (void) unhide {
- [NSApp unhide:nil];
-}
-
-- (void)beep {
- NSBeep();
-}
-
-- (void) bounce {
- [NSApp requestUserAttention:NSInformationalRequest];
-}
-
-- (void)setCustomUserAgent:(NSString *)userAgentString {
- [self.webView setCustomUserAgent: userAgentString];
-}
-
-- (void) open:(NSString*)url {
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]];
-}
-
-- (void) launch:(NSString *)name {
- [[NSWorkspace sharedWorkspace] launchApplication:name];
-}
-
-- (void)receiveSleepNotification:(NSNotification*)note{
- [JSEventHelper triggerEvent:@"sleep" forWebView:self.webView];
-}
-
-- (void) receiveWakeNotification:(NSNotification*)note{
- [JSEventHelper triggerEvent:@"wake" forWebView:self.webView];
-}
-
-- (void) receiveActivateNotification:(NSNotification*)notification{
- NSDictionary* userInfo = [notification userInfo];
- NSRunningApplication* runningApplication = [userInfo objectForKey:NSWorkspaceApplicationKey];
- if (runningApplication) {
- NSMutableDictionary* applicationDidGetFocusDict = [[NSMutableDictionary alloc] initWithCapacity:2];
- [applicationDidGetFocusDict setObject:runningApplication.localizedName
- forKey:@"localizedName"];
- [applicationDidGetFocusDict setObject:[runningApplication.bundleURL absoluteString]
- forKey:@"bundleURL"];
-
- [JSEventHelper triggerEvent:@"appActivated" withArgs:applicationDidGetFocusDict forWebView:self.webView];
- }
-}
-
-
-
-
-/*
- To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType.
- */
-- (NSNumber*)systemIdleTime {
- CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
-
- return [NSNumber numberWithDouble:timeSinceLastEvent];
-}
-
-
-
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector
-{
- id result = nil;
-
- if (selector == @selector(open:)) {
- result = @"open";
- } else if (selector == @selector(launch:)) {
- result = @"launch";
- } else if (selector == @selector(setCustomUserAgent:)) {
- result = @"setCustomUserAgent";
- } else if (selector == @selector(systemIdleTime)) {
- result = @"systemIdleTime";
- }
-
- return result;
-}
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return NO;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return YES;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h
deleted file mode 100755
index 65d6b6d4..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Command.h
-// MacGap
-//
-// Created by Joe Hildebrand on 1/10/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <Webkit/WebScriptObject.h>
-
-@interface Command : NSObject {
- JSContextRef context;
-}
-
-- (id) initWithContext:(JSContextRef)aContext;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m
deleted file mode 100755
index 39b85630..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Command.m
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Command.m
-// MacGap
-//
-// Created by Joe Hildebrand on 1/10/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "Command.h"
-#import <JavaScriptCore/JSContextRef.h>
-
-@implementation Command
-
-- (id) initWithContext:(JSContextRef)aContext {
- self = [super init];
- if (!self)
- return nil;
- context = aContext;
- JSGlobalContextRetain((JSGlobalContextRef)context);
- return self;
-}
-
-- (void)dealloc
-{
- if (context)
- JSGlobalContextRelease((JSGlobalContextRef)context);
-}
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h
deleted file mode 100644
index b3c533d7..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#import <Foundation/Foundation.h>
-
-@interface Dock : NSObject {
-
-}
-- (void) setBadge:(NSString*)value;
-- (NSString *) badge;
-
-@property (readwrite, copy) NSString *badge;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m
deleted file mode 100644
index a4494d16..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Dock.m
+++ /dev/null
@@ -1,31 +0,0 @@
-#import "Dock.h"
-
-@implementation Dock
-
-@synthesize badge;
-
-- (void) setBadge:(NSString *)value
-{
- NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
- [tile setBadgeLabel:value];
-}
-
-- (NSString *) badge
-{
- NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
- return [tile badgeLabel];
-}
-
-#pragma mark WebScripting Protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return NO;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return NO;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h
deleted file mode 100755
index d765978f..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// MenuItemProxy.h
-// MacGap
-//
-// Created by Joe Hildebrand on 1/15/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "Command.h"
-#import "CallbackDelegate.h"
-
-@class MenuProxy;
-
-@interface MenuItemProxy : Command {
- NSMenuItem *item;
- CallbackDelegate *callback;
-}
-
-+ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem;
-
-- (MenuProxy*)addSubmenu;
-
-- (void) remove;
-- (void) setCallback:(WebScriptObject*)aCallback;
-- (void) setKey:(NSString*)keyCommand;
-- (void) setTitle:(NSString*)title;
-- (void) enable;
-- (void) disable;
-- (MenuProxy*)submenu;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m
deleted file mode 100755
index 7b9702cc..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuItemProxy.m
+++ /dev/null
@@ -1,150 +0,0 @@
-//
-// MenuItemProxy.m
-// MacGap
-//
-// Created by Joe Hildebrand on 1/15/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "MenuItemProxy.h"
-#import "MenuProxy.h"
-
-@implementation MenuItemProxy
-
-- (id) initWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem
-{
- NSAssert(anItem, @"anItem required");
- self = [super initWithContext:aContext];
- if (!self)
- return nil;
- item = anItem;
- item.representedObject = self;
-
- return self;
-}
-
-+ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem
-{
- MenuItemProxy *proxy = [anItem representedObject];
- if (proxy)
- {
- NSLog(@"MIP Cache hit");
- NSAssert([proxy class] == [MenuItemProxy class], @"Bad proxy");
- return proxy;
- }
- return [[MenuItemProxy alloc] initWithContext:aContext andMenuItem:anItem];
-}
-
-- (NSString*) description
-{
- return [item description];
-}
-
-- (MenuProxy*)addSubmenu
-{
- NSMenu *s = [item submenu];
- if (!s)
- {
- s = [[NSMenu alloc] initWithTitle:@"FFFFFFOOOOO"];
- [item setSubmenu:s];
- }
- return [MenuProxy proxyWithContext:context andMenu:s];
-}
-
-- (void) remove
-{
- NSMenu *menu = [item menu];
- [menu removeItem:item];
-}
-
-- (void)callCallback:(id)sender
-{
- [callback callWithParams:[sender title], nil];
-}
-
-- (void) setCallback:(WebScriptObject*)aCallback
-{
- NSAssert(item, @"item required");
- callback = [[CallbackDelegate alloc] initWithContext:context forCallback:aCallback];
- [item setAction:@selector(callCallback:)];
- [item setTarget:self];
-}
-
-- (void)setKey:(NSString*)keyCommand
-{
- NSString *aKey = [MenuProxy getKeyFromString:keyCommand];
- [item setKeyEquivalent:aKey];
-
- NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand];
- [item setKeyEquivalentModifierMask:modifiers];
-}
-
-- (void) setTitle:(NSString*)title
-{
- [item setTitle:title];
-}
-
-- (MenuProxy*)submenu;
-{
- // TODO: make this work as a property
- NSMenu *s = [item submenu];
- if (!s)
- return nil;
- return [MenuProxy proxyWithContext:context andMenu:s];
-}
-
-- (void) enable
-{
- [item setEnabled:YES];
-}
-
-- (void) disable
-{
- [item setEnabled:NO];
-}
-
-#pragma mark WebScripting protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return [self webScriptNameForSelector:selector] == nil;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return YES;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector
-{
- id result = nil;
-
- if (selector == @selector(addSubmenu)) {
- result = @"addSubmenu";
- }
- else if (selector == @selector(remove)) {
- result = @"remove";
- }
- else if (selector == @selector(setCallback:)) {
- result = @"setCallback";
- }
- else if (selector == @selector(setKey:)) {
- result = @"setKey";
- }
- else if (selector == @selector(setTitle:)) {
- result = @"setTitle";
- }
- else if (selector == @selector(submenu)) {
- result = @"submenu";
- }
- else if (selector == @selector(enable)) {
- result = @"enable";
- }
- else if (selector == @selector(disable)) {
- result = @"disable";
- }
-
- return result;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h
deleted file mode 100755
index afd6c6ed..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// MenuProxy.h
-// MacGap
-//
-// Created by Joe Hildebrand on 1/14/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "Command.h"
-
-@class MenuItemProxy;
-
-@interface MenuProxy : Command {
- NSMenu *menu;
-}
-
-+ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu;
-
-- (MenuItemProxy*)addItemWithTitle:(NSString*)title
- keyEquivalent:(NSString*)aKey
- callback:(WebScriptObject*)aCallback
- atIndex:(NSInteger)index;
-
-- (MenuItemProxy*)addSeparator;
-- (MenuItemProxy*)itemForKey:(id)key;
-- (MenuProxy*)removeItem:(id)key;
-
-+ (NSString*)getKeyFromString:(NSString*)keyCommand;
-+ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m
deleted file mode 100755
index 5bc10a76..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/MenuProxy.m
+++ /dev/null
@@ -1,233 +0,0 @@
-//
-// MenuProxy.m
-// MacGap
-//
-// Created by Joe Hildebrand on 1/14/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import <objc/runtime.h>
-#import <JavaScriptCore/JavaScript.h>
-
-#import "MenuProxy.h"
-#import "MenuItemProxy.h"
-
-static char REPRESENTED_OBJECT;
-
-@interface NSMenu (represented)
-@property (strong) id representedObject;
-@end
-
-@implementation NSMenu (represented)
-
-- (id) representedObject
-{
- return objc_getAssociatedObject(self, &REPRESENTED_OBJECT);
-}
-
-- (void) setRepresentedObject:(id)representedObject
-{
- objc_setAssociatedObject(self,
- &REPRESENTED_OBJECT,
- representedObject,
- OBJC_ASSOCIATION_RETAIN);
-}
-
-@end
-
-@implementation MenuProxy
-
-- (id) initWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu
-{
- self = [super initWithContext:aContext];
- if (!self)
- return nil;
- menu = aMenu;
- menu.representedObject = self;
- return self;
-}
-
-+ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu
-{
- // singleton-ish.
- MenuProxy *ret = [aMenu representedObject];
- if (ret)
- {
- NSLog(@"MP cache hit");
- return ret;
- }
- return [[MenuProxy alloc] initWithContext:aContext andMenu:aMenu];
-}
-
-- (void) dealloc
-{
- menu.representedObject = nil;
-}
-
-- (NSString*) description
-{
- return [menu description];
-}
-
-static BOOL isNullish(id o)
-{
- if (!o)
- return YES;
- if ([o isKindOfClass:[WebUndefined class]])
- return YES;
- return NO;
-}
-
-- (MenuItemProxy*)addItemWithTitle:(NSString*)title
- keyEquivalent:(NSString*)keyCommand
- callback:(WebScriptObject*)aCallback
- atIndex:(NSInteger)index
-{
- if (isNullish(title))
- title = @"";
-
- NSString *aKey = [MenuProxy getKeyFromString:keyCommand];
- NSMenuItem *item = nil;
-
- if(index) {
- item = [menu insertItemWithTitle:title action:nil keyEquivalent:aKey atIndex:index ];
- } else {
- item = [menu addItemWithTitle:title action:nil keyEquivalent:aKey ];
-
- }
-
- // Set the modifiers.
- NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand];
- [item setKeyEquivalentModifierMask:modifiers];
-
- if(!menu.supermenu) {
- NSMenu *s = [[NSMenu alloc] initWithTitle:title];
- [item setSubmenu:s];
- }
-
- MenuItemProxy *mip = [MenuItemProxy proxyWithContext:context andMenuItem:item];
- if (!isNullish(aCallback))
- [mip setCallback:aCallback];
-
-
- return mip;
-}
-
-+ (NSString*)getKeyFromString:(NSString*)keyCommand {
- if (isNullish(keyCommand))
- keyCommand = @"";
-
- // Obtain the key (if there are modifiers, it will be the last character).
- NSString *aKey = @"";
- if ([keyCommand length] > 0) {
- aKey = [keyCommand substringFromIndex:[keyCommand length] - 1];
- }
-
- return aKey;
-}
-
-+ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand {
- // aKeys may optionally specify one or more modifiers.
- NSUInteger modifiers = 0;
-
- if ([keyCommand rangeOfString:@"caps"].location != NSNotFound) modifiers += NSAlphaShiftKeyMask;
- if ([keyCommand rangeOfString:@"shift"].location != NSNotFound) modifiers += NSShiftKeyMask;
- if ([keyCommand rangeOfString:@"cmd"].location != NSNotFound) modifiers += NSCommandKeyMask;
- if ([keyCommand rangeOfString:@"ctrl"].location != NSNotFound) modifiers += NSControlKeyMask;
- if ([keyCommand rangeOfString:@"opt"].location != NSNotFound) modifiers += NSAlternateKeyMask;
- if ([keyCommand rangeOfString:@"alt"].location != NSNotFound) modifiers += NSAlternateKeyMask;
-
- return modifiers;
-}
-
-- (MenuItemProxy*)addSeparator
-{
- NSMenuItem *sep = [NSMenuItem separatorItem];
- [menu addItem:sep];
- return [MenuItemProxy proxyWithContext:context andMenuItem:sep];
-}
-
-- (MenuItemProxy*)itemForKey:(id)key
-{
- if (isNullish(key))
- return nil;
- NSMenuItem *item = nil;
- if ([key isKindOfClass:[NSNumber class]])
- {
- item = [menu itemAtIndex:[key intValue]];
- }
- else if ([key isKindOfClass:[NSString class]])
- {
- item = [menu itemWithTitle:key];
- if (!item)
- {
- // Try again, with ... appended. e.g. "Save..."
- item = [menu itemWithTitle:
- [key stringByAppendingString:@"\u2026"]];
- }
- }
- if (!item)
- return nil;
-
- return [MenuItemProxy proxyWithContext:context andMenuItem:item];
-}
-
-- (MenuProxy*)removeItem:(id)key
-{
- if (isNullish(key))
- return nil;
-
- NSMenuItem *item = nil;
- if ([key isKindOfClass:[NSNumber class]])
- {
- item = [menu itemAtIndex:[key intValue]];
- }
- else if ([key isKindOfClass:[NSString class]])
- {
- item = [menu itemWithTitle:key];
- if (!item)
- {
- // Try again, with ... appended. e.g. "Save..."
- item = [menu itemWithTitle:
- [key stringByAppendingString:@"\u2026"]];
- }
- }
- if (!item)
- return nil;
-
- [menu removeItem:item];
- return [MenuProxy proxyWithContext:context andMenu:menu];
-}
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return [self webScriptNameForSelector:selector] == nil;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return YES;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector
-{
- id result = nil;
-
- if (selector == @selector(addItemWithTitle:keyEquivalent:callback:atIndex:)) {
- result = @"addItem";
- }
- else if (selector == @selector(addSeparator)) {
- result = @"addSeparator";
- }
- else if (selector == @selector(itemForKey:)) {
- result = @"getItem";
- }
- else if (selector == @selector(removeItem:)) {
- result = @"removeMenu";
- }
-
- return result;
-}
-
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h
deleted file mode 100644
index 51077a43..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Notice.h
-// MacGap
-//
-// Created by Christian Sullivan on 7/26/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "WindowController.h"
-
-#define APP_NOTICE_NOTIFICATION @"Notice"
-
-@interface Notice : NSObject <NSUserNotificationCenterDelegate> {
-
-}
-
-@property (nonatomic, retain) WebView *webView;
-
-- (id) initWithWebView:(WebView *)view;
-- (void) notify:(NSDictionary*)message;
-- (void) close:(NSString*)notificationId;
-+ (BOOL) available;
-
-@end
-
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m
deleted file mode 100644
index a4095f9f..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Notice.m
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// Notice.m
-// MacGap
-//
-// Created by Christian Sullivan on 7/26/12.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "Notice.h"
-
-#import "JSEventHelper.h"
-
-@implementation Notice
-
-- (id) initWithWebView:(WebView*)view
-{
- if(self = [super init]) {
- self.webView = view;
- [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
- }
- return self;
-}
-
-- (void) notify:(NSDictionary *)message {
- NSUserNotification *notification = [[NSUserNotification alloc] init];
- [notification setTitle:[message valueForKey:@"title"]];
- [notification setInformativeText:[message valueForKey:@"content"]];
- [notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]];
- BOOL playSound = true; // optional parameter, false only when {sound: false}
- @try {
- NSNumber *s = [message valueForKey:@"sound"];
- if ([[s className] isEqual: @"__NSCFBoolean"]) {
- playSound = [s boolValue];
- }
- }
- @catch (NSException *exception) {
- }
- if (playSound) {
- [notification setSoundName:NSUserNotificationDefaultSoundName];
- }
- NSString *id = @""; // optional, needed for close
- @try {
- id = [message valueForKey:@"id"];
- }
- @catch (NSException *exception) {
- }
- [notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:id, @"id", nil]];
- NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
- [center scheduleNotification:notification];
-}
-
-// close all notifications with id == notificationId or close all notifications if notificationId == "*"
-- (void) close:(NSString*)notificationId {
- NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
- for(NSUserNotification * deliveredNote in center.deliveredNotifications) {
- if ([notificationId isEqualToString:@"*"] || [deliveredNote.userInfo[@"id"] isEqualToString:notificationId]) {
- [center removeDeliveredNotification: deliveredNote];
- }
- }
-}
-
-+ (BOOL) available {
- if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)])
- return YES;
-
- return NO;
-}
-
-- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
-{
- NSString *notificationId = [notification.userInfo valueForKey:@"id"];
- [JSEventHelper triggerEvent:@"macgap.notify.activated" forDetail:notificationId forWebView:self.webView];
-}
-
-#pragma mark WebScripting Protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- BOOL result = YES;
- if (selector == @selector(notify:))
- result = NO;
- if (selector == @selector(close:))
- result = NO;
-
- return result;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector
-{
- id result = nil;
-
- if (selector == @selector(notify:)) {
- result = @"notify";
- }
- if (selector == @selector(close:)) {
- result = @"close";
- }
-
- return result;
-}
-
-// right now exclude all properties (eg keys)
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return YES;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h
deleted file mode 100644
index f931340d..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#import <Foundation/Foundation.h>
-
-@interface Path : NSObject {
-
-}
-
-- (NSString *) application;
-- (NSString *) resource;
-- (NSString *) documents;
-- (NSString *) library;
-- (NSString *) home;
-- (NSString *) temp;
-
-@property (readonly,copy) NSString* application;
-@property (readonly,copy) NSString* resource;
-@property (readonly,copy) NSString* documents;
-@property (readonly,copy) NSString* library;
-@property (readonly,copy) NSString* home;
-@property (readonly,copy) NSString* temp;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m
deleted file mode 100644
index 8c54100f..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Path.m
+++ /dev/null
@@ -1,53 +0,0 @@
-#import "Path.h"
-
-@implementation Path
-
-@synthesize application;
-@synthesize resource;
-@synthesize documents;
-@synthesize library;
-@synthesize home;
-@synthesize temp;
-
-- (NSString *)application {
- return [[NSBundle mainBundle] bundlePath];
-}
-
-- (NSString *)resource {
- return [[NSBundle mainBundle] resourcePath];
-}
-
-- (NSString *)documents {
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- return [paths objectAtIndex:0];
-}
-
-- (NSString *)library {
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
- NSLog( @"%@", paths );
- return [paths objectAtIndex:0];
-}
-
-- (NSString *)home {
- return NSHomeDirectory();
-}
-
-- (NSString *)temp {
- return NSTemporaryDirectory();
-}
-
-#pragma mark WebScripting Protocol
-
-/* checks whether a selector is acceptable to be called from JavaScript */
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return NO;
-}
-
-// right now exclude all properties (eg keys)
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return NO;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h
deleted file mode 100644
index 06707643..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#import <Cocoa/Cocoa.h>
-#import "Command.h"
-#import "CallbackDelegate.h"
-
-
-@interface Sound : Command {
-
-}
-
-// pending callbacks for sounds being played, to keep
-// ARC from freeing them too early
-@property (nonatomic, strong) NSMutableSet *pending;
-
-- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback;
-- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m
deleted file mode 100644
index 9f4a44db..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/Sound.m
+++ /dev/null
@@ -1,97 +0,0 @@
-#import "Sound.h"
-
-
-@interface PlayDelegate : CallbackDelegate <NSSoundDelegate> {
-}
-
-@property (nonatomic, weak) Sound *sound;
-
-- (id) initWithContext:(JSContextRef)aContext
- forCallback:(WebScriptObject*)aCallback
- withSound:(Sound*)aSound;
-@end
-
-@implementation PlayDelegate
-
-@synthesize sound;
-
-- (id) initWithContext:(JSContextRef)aContext
- forCallback:(WebScriptObject*)aCallback
- withSound:(Sound*)aSound
-{
- self = [super initWithContext:aContext forCallback:aCallback];
- if (!self)
- return nil;
- sound = aSound;
- return self;
-}
-
-- (void)sound:(NSSound *)aSound didFinishPlaying:(BOOL)finishedPlaying {
- [self callWithParams:[aSound name], nil];
- [sound.pending removeObject:self];
-}
-
-@end
-
-@implementation Sound
-
-@synthesize pending;
-
-- (id) initWithContext:(JSContextRef)aContext {
- self = [super initWithContext:aContext];
- if (!self) {
- return nil;
- }
-
- pending = [NSMutableSet new];
- return self;
-}
-
-- (void) playSound:(NSSound*)sound onComplete:(WebScriptObject*)callback {
- if (callback != (id)[WebUndefined undefined]) {
- PlayDelegate *d = [[PlayDelegate alloc] initWithContext:context
- forCallback:callback
- withSound:self];
- [pending addObject:d];
- [sound setDelegate:d];
- }
- [sound play];
-}
-
-- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback {
- NSURL* fileUrl = [NSURL fileURLWithPath:[[Utils sharedInstance] pathForResource:file]];
- DebugNSLog(@"Sound file:%@", [fileUrl description]);
-
- NSSound* sound = [[NSSound alloc] initWithContentsOfURL:fileUrl byReference:YES];
- [self playSound:sound onComplete:callback];
-}
-
-- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback {
- NSSound *systemSound = [NSSound soundNamed:name];
- [self playSound:systemSound onComplete:callback];
-}
-
-#pragma mark WebScripting Protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
- return [self webScriptNameForSelector:selector] == nil;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name {
- return YES;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector {
- id result = nil;
-
- if (selector == @selector(play:onComplete:)) {
- result = @"play";
- }
- else if (selector == @selector(playSystem:onComplete:)) {
- result = @"playSystem";
- }
-
- return result;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h
deleted file mode 100644
index 269191b3..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// UserDefaults.h
-// MacGap
-//
-// Created by Jeff Hanbury on 16/04/2014.
-// Copyright (c) 2014 Twitter. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-#import "WindowController.h"
-
-@interface UserDefaults : NSObject
-
-@property (nonatomic, retain) WebView *webView;
-
-- (id) initWithWebView:(WebView *)view;
-- (NSString*) getMyDefaults;
-- (NSDictionary*) myDefaultsDictionary;
-- (void) removeObjectForKey:(NSString*)key;
-- (NSArray*) getUserDefaultsKeys;
-
-- (NSString*) addPrefix:(NSString*)key;
-
-- (void) setString:(NSString*)key withValue:(NSString*)value;
-- (NSString*) getString:(NSString*)key;
-
-- (void) setInteger:(NSString*)key withValue:(NSString*)value;
-- (NSNumber*) getInteger:(NSString*)key;
-
-- (void) setBool:(NSString*)key withValue:(NSString*)value;
-- (NSNumber*) getBool:(NSString*)key;
-
-- (void) setFloat:(NSString*)key withValue:(NSString*)value;
-- (NSNumber*) getFloat:(NSString*)key;
-
-// Could also be implemented:
-//– setObject:forKey:
-//– setDouble:forKey:
-//– setURL:forKey:
-
-@end
-
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m
deleted file mode 100644
index 48568710..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/UserDefaults.m
+++ /dev/null
@@ -1,211 +0,0 @@
-//
-// UserDefaults.m
-// MacGap
-//
-// Created by Jeff Hanbury on 16/04/2014.
-// Copyright (c) 2014 Twitter. All rights reserved.
-//
-
-#import "UserDefaults.h"
-#import "JSEventHelper.h"
-
-@interface UserDefaults() {
-
-}
-
--(void) setupNotificationCenter;
-
-@end
-
-
-@implementation UserDefaults
-
-- (id) initWithWebView:(WebView *) view{
- self = [super init];
-
- if (self) {
- self.webView = view;
- [self setupNotificationCenter];
- }
-
- return self;
-}
-
-
--(void) setupNotificationCenter{
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(defaultsChanged:)
- name:NSUserDefaultsDidChangeNotification
- object:nil];
-}
-
-- (void)defaultsChanged:(NSNotification *)notification {
- NSDictionary* returnDict = [self myDefaultsDictionary];
- [JSEventHelper triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView];
-}
-
-- (NSString*) getMyDefaults {
- NSDictionary* myDefaults = [self myDefaultsDictionary];
-
- return [[Utils sharedInstance] convertDictionaryToJSON:myDefaults];
-}
-
-- (NSDictionary*) myDefaultsDictionary {
- NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
- NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init];
-
- // Get the user defaults.
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-
- // Build up a dictionary containing just the items beginning with our
- // prefix.
- for (NSString* key in [self getUserDefaultsKeys]) {
- if ([key hasPrefix:prefix]) {
- id val = [defaults valueForKey:key];
- [returnDict setObject:val forKey:key];
- }
- }
-
- return returnDict;
-}
-
-- (NSArray*) getUserDefaultsKeys {
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- return [[prefs dictionaryRepresentation] allKeys];
-}
-
-- (void) removeObjectForKey:(NSString*)key {
- NSString* prefixedKey;
- prefixedKey = [self addPrefix:key];
-
- [[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey];
- [[NSUserDefaults standardUserDefaults] synchronize];
-}
-
-// Check we have a standard prefix for JS-modified keys, for security purposes.
-// If not, add it. This stops JavaScript from ever being able to modify keys
-// it did not create.
-- (NSString*) addPrefix:(NSString*)key {
- NSString* prefix;
- prefix = [kWebScriptNamespace stringByAppendingString:@"_"];
-
- if (![key hasPrefix:prefix]) {
- key = [prefix stringByAppendingString:key];
- }
- return key;
-}
-
-// String
-
-- (void) setString:(NSString*)key withValue:(NSString*)value {
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- NSString* prefixedKey;
- prefixedKey = [self addPrefix:key];
- [prefs setObject:value forKey:prefixedKey];
-}
-
-- (NSString*) getString:(NSString *)key {
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- return [prefs stringForKey:key];
-}
-
-// All the following must convert their type to NSNumber for JavaScript.
-
-// Integer
-
-- (void) setInteger:(NSString*)key withValue:(NSString*)value {
- NSString* prefixedKey;
- prefixedKey = [self addPrefix:key];
-
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- NSInteger myInt = [value intValue];
- [prefs setInteger:myInt forKey:prefixedKey];
-}
-
-- (NSNumber*) getInteger:(NSString *)key {
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- return [NSNumber numberWithInteger:[prefs integerForKey:key]];
-}
-
-// Boolean
-
-- (void) setBool:(NSString*)key withValue:(NSString*)value {
- NSString* prefixedKey;
- prefixedKey = [self addPrefix:key];
-
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- BOOL myBool = [value boolValue];
- [prefs setBool:myBool forKey:prefixedKey];
-}
-
-- (NSNumber*) getBool:(NSString *)key {
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- return [NSNumber numberWithBool:[prefs boolForKey:key]];
-}
-
-// Float
-
-- (void) setFloat:(NSString*)key withValue:(NSString*)value {
- NSString* prefixedKey;
- prefixedKey = [self addPrefix:key];
-
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- float myFloat = [value floatValue];
- [prefs setFloat:myFloat forKey:prefixedKey];
-}
-
-- (NSNumber*) getFloat:(NSString *)key {
- NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- return [NSNumber numberWithFloat:[prefs floatForKey:key]];
-}
-
-
-#pragma mark WebScripting Protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
- return NO;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector {
- id result = nil;
-
- if (selector == @selector(getMyDefaults)) {
- result = @"getMyDefaults";
- }
-
- if (selector == @selector(removeObjectForKey:)) {
- result = @"removeObjectForKey";
- }
-
- else if (selector == @selector(setString:withValue:)) {
- result = @"setString";
- } else if (selector == @selector(getString:)) {
- result = @"getString";
- }
-
- else if (selector == @selector(setInteger:withValue:)) {
- result = @"setInteger";
- } else if (selector == @selector(getInteger:)) {
- result = @"getInteger";
- }
-
- else if (selector == @selector(setBool:withValue:)) {
- result = @"setBool";
- } else if (selector == @selector(getBool:)) {
- result = @"getBool";
- }
-
- else if (selector == @selector(setFloat:withValue:)) {
- result = @"setFloat";
- } else if (selector == @selector(getFloat:)) {
- result = @"getFloat";
- }
-
- return result;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name {
- return NO;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h
deleted file mode 100644
index 62c7b7e8..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.h
+++ /dev/null
@@ -1,9 +0,0 @@
-@interface Fonts : NSObject {
-}
-
-- (NSArray*) availableFonts;
-- (NSArray*) availableFontFamilies;
-- (NSArray*) availableMembersOfFontFamily:(NSString*)fontFamily;
-- (CGFloat) defaultLineHeightForFont:(NSString *)theFontName ofSize:(CGFloat)theFontSize;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m
deleted file mode 100644
index b17818a5..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Commands/fonts.m
+++ /dev/null
@@ -1,48 +0,0 @@
-#import "fonts.h"
-
-@implementation Fonts
-
-
-- (NSArray*) availableFonts {
- return [[NSFontManager sharedFontManager] availableFonts];
-}
-
-- (NSArray*) availableFontFamilies {
- return [[NSFontManager sharedFontManager] availableFontFamilies];
-}
-
-- (NSArray*) availableMembersOfFontFamily:(NSString *)fontFamily {
- return [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily];
-}
-
-- (CGFloat) defaultLineHeightForFont:(NSString*)theFontName ofSize:(CGFloat)theFontSize {
- NSFont *theFont = [NSFont fontWithName:theFontName size:theFontSize];
- NSLayoutManager *lm = [[NSLayoutManager alloc] init];
-
- return [lm defaultLineHeightForFont:theFont];
-}
-
-
-#pragma mark WebScripting Protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
- return NO;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector {
- id result = nil;
-
- if (selector == @selector(availableMembersOfFontFamily:)) {
- result = @"availableMembersOfFontFamily";
- } else if (selector == @selector(defaultLineHeightForFont:ofSize:)) {
- result = @"defaultLineHeightForFont";
- }
-
- return result;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name {
- return NO;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h
deleted file mode 100644
index 1fe59d6c..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Constants.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// Application constants
-
-#define kStartPage @"http://127.0.0.1:9993/"
-
-#define kStartFolder @"."
-
-#define kWebScriptNamespace @"macgap" \ No newline at end of file
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h
deleted file mode 100644
index 65890a5e..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#import <Cocoa/Cocoa.h>
-#import <WebKit/WebKit.h>
-
-@class WebViewDelegate;
-
-@interface ContentView : NSView {
- IBOutlet WebView* webView;
- WebViewDelegate* delegate;
-}
-
-@property (retain) WebView* webView;
-@property (retain) WebViewDelegate* delegate;
-@property (strong) IBOutlet NSMenu *mainMenu;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m
deleted file mode 100644
index 6558a191..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/ContentView.m
+++ /dev/null
@@ -1,68 +0,0 @@
-#import "ContentView.h"
-#import "WebViewDelegate.h"
-#import "AppDelegate.h"
-#import "JSEventHelper.h"
-
-@interface WebPreferences (WebPreferencesPrivate)
- - (void)_setLocalStorageDatabasePath:(NSString *)path;
- - (void) setLocalStorageEnabled: (BOOL) localStorageEnabled;
- - (void) setDatabasesEnabled:(BOOL)databasesEnabled;
- - (void) setDeveloperExtrasEnabled:(BOOL)developerExtrasEnabled;
- - (void) setWebGLEnabled:(BOOL)webGLEnabled;
- - (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled;
-@end
-
-@implementation ContentView
-
-@synthesize webView, delegate, mainMenu;
-
-- (void) awakeFromNib
-{
- WebPreferences *webPrefs = [WebPreferences standardPreferences];
-
- NSString *cappBundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
- NSString *applicationSupportFile = [@"~/Library/Application Support/" stringByExpandingTildeInPath];
- NSString *savePath = [NSString pathWithComponents:[NSArray arrayWithObjects:applicationSupportFile, cappBundleName, @"LocalStorage", nil]];
- [webPrefs _setLocalStorageDatabasePath:savePath];
- [webPrefs setLocalStorageEnabled:YES];
- [webPrefs setDatabasesEnabled:YES];
- [webPrefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]];
- [webPrefs setOfflineWebApplicationCacheEnabled:YES];
- [webPrefs setWebGLEnabled:YES];
-
- [self.webView setPreferences:webPrefs];
-
- NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage
- sharedHTTPCookieStorage];
- [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
-
- [self.webView setApplicationNameForUserAgent: @"MacGap"];
-
- self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]];
-// [self.webView setFrameLoadDelegate:self.delegate];
-// [self.webView setUIDelegate:self.delegate];
-// [self.webView setResourceLoadDelegate:self.delegate];
-// [self.webView setDownloadDelegate:self.delegate];
-// [self.webView setPolicyDelegate:self.delegate];
- [self.webView setDrawsBackground:NO];
- [self.webView setShouldCloseWithWindow:NO];
-
- [self.webView setGroupName:@"MacGap"];
-
-}
-
-- (void) windowResized:(NSNotification*)notification;
-{
- NSWindow* window = (NSWindow*)notification.object;
- NSSize size = [window frame].size;
-
- DebugNSLog(@"window width = %f, window height = %f", size.width, size.height);
-
- bool isFullScreen = (window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask;
- int titleBarHeight = isFullScreen ? 0 : [[Utils sharedInstance] titleBarHeight:window];
-
- [self.webView setFrame:NSMakeRect(0, 0, size.width, size.height - titleBarHeight)];
- [JSEventHelper triggerEvent:@"orientationchange" forWebView:self.webView];
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h
deleted file mode 100644
index 401f3e39..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Helper.h
-// MacGap
-//
-// Created by Liam Kaufman Simpkins on 12-01-22.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import "WindowController.h"
-
-@interface JSEventHelper : NSObject
-
-+ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView;
-+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView;
-+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView;
-+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView;
-+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m
deleted file mode 100644
index 65406b3c..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/JSEventHelper.m
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Helper.m
-// MacGap
-//
-// Created by Liam Kaufman Simpkins on 12-01-22.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import "JSEventHelper.h"
-
-@implementation JSEventHelper
-
-+ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView {
- [self triggerEvent:event withArgs:[NSMutableDictionary dictionary] forObject:@"document" forWebView:webView];
-}
-
-+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView {
- [self triggerEvent:event withArgs:args forObject:@"document" forWebView:webView];
-}
-
-+ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView {
-
- // Convert args Dictionary to JSON.
- NSString* jsonString = [[Utils sharedInstance] convertDictionaryToJSON:args];
-
- // Create the event JavaScript and run it.
- NSString * str = [NSString stringWithFormat:@"var e = document.createEvent('Events'); e.initEvent('%@', true, false); e.data=%@; %@.dispatchEvent(e); ", event, jsonString, objName];
- [webView stringByEvaluatingJavaScriptFromString:str];
-}
-
-+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView {
- [self triggerEvent:event forDetail:detail forObject:@"document" forWebView:webView];
-}
-
-+ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView {
- NSString *detailEscaped = [detail stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
- NSString *str = [NSString stringWithFormat:@"var e = new CustomEvent('%@', { 'detail': decodeURIComponent(\"%@\") }); %@.dispatchEvent(e); ", event, detailEscaped, objName];
- [webView stringByEvaluatingJavaScriptFromString:str];
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h
deleted file mode 100644
index f573d881..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#import <Foundation/Foundation.h>
-#import <Webkit/WebScriptObject.h>
-
-#define DEG_EPS 0.001
-#define fequal(a,b) (fabs((a) - (b)) < DEG_EPS)
-#define fequalzero(a) (fabs(a) < DEG_EPS)
-
-@class LoadingView;
-
-@interface Utils : NSObject {
-}
-
-- (float) titleBarHeight:(NSWindow*)aWindow;
-- (NSString*) pathForResource:(NSString*)resourcepath;
-- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict;
-- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray;
-
-+ (Utils*) sharedInstance;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m
deleted file mode 100644
index 8d85c294..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Utils.m
+++ /dev/null
@@ -1,93 +0,0 @@
-#import "Utils.h"
-#import <Webkit/WebScriptObject.h>
-
-static Utils* sharedInstance = nil;
-
-@implementation Utils
-
-- (float) titleBarHeight:(NSWindow*)aWindow
-{
- NSRect frame = [aWindow frame];
- NSRect contentRect = [NSWindow contentRectForFrameRect: frame
- styleMask: NSTitledWindowMask];
-
- return (frame.size.height - contentRect.size.height);
-}
-
-- (NSString*) pathForResource:(NSString*)resourcepath
-{
- NSBundle * mainBundle = [NSBundle mainBundle];
- NSMutableArray *directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]];
- NSString *filename = [directoryParts lastObject];
- [directoryParts removeLastObject];
-
- NSString *directoryStr = [NSString stringWithFormat:@"%@/%@", kStartFolder, [directoryParts componentsJoinedByString:@"/"]];
- return [mainBundle pathForResource:filename
- ofType:@""
- inDirectory:directoryStr];
-}
-
-- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict {
- // Convert defaults Dictionary to JSON.
- NSError *error;
- NSData *jsonData = [NSJSONSerialization
- dataWithJSONObject:dict
- options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
- error:&error];
-
- NSString *jsonString;
- if (! jsonData) {
- NSLog(@"Got an error converting to JSON: %@", error);
- }
- else {
- jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
- }
-
- return jsonString;
-}
-
-// Convert JavaScript array (arrives as a WebScriptObject) into an NSArray of strings.
-- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray {
- NSInteger count = [[jsArray valueForKey:@"length"] integerValue];
-
- NSMutableArray *args = [NSMutableArray array];
- for (int i = 0; i < count; i++) {
- NSString *item = [jsArray webScriptValueAtIndex:i];
- if ([item isKindOfClass:[NSString class]]) {
- [args addObject:item];
- }
- }
-
- return args;
-}
-
-#pragma mark -
-#pragma mark Singleton methods
-
-+ (Utils*) sharedInstance
-{
- @synchronized(self)
- {
- if (sharedInstance == nil){
- sharedInstance = [[Utils alloc] init];
- }
- }
- return sharedInstance;
-}
-
-+ (id) allocWithZone:(NSZone *)zone {
- @synchronized(self) {
- if (sharedInstance == nil) {
- sharedInstance = [super allocWithZone:zone];
- return sharedInstance; // assignment and return on first allocation
- }
- }
- return nil; // on subsequent allocation attempts return nil
-}
-
-- (id) copyWithZone:(NSZone *)zone
-{
- return self;
-}
-
-@end \ No newline at end of file
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h
deleted file mode 100644
index 49c6da6b..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#import <Cocoa/Cocoa.h>
-#import <WebKit/WebKit.h>
-
-@class Sound;
-@class Dock;
-@class Growl;
-@class Notice;
-@class Path;
-@class App;
-@class Window;
-@class Clipboard;
-@class Fonts;
-@class MenuProxy;
-@class UserDefaults;
-
-@class WindowController;
-
-@interface WebViewDelegate : NSObject {
- Sound* sound;
- Dock* dock;
- Growl* growl;
- Notice* notice;
- Path* path;
- App* app;
- Window* window;
- Clipboard* clipboard;
- Fonts* fonts;
- NSMenu *mainMenu;
- UserDefaults* userDefaults;
-}
-
-
-
-@property (nonatomic, retain) Sound* sound;
-@property (nonatomic, retain) Dock* dock;
-@property (nonatomic, retain) Growl* growl;
-@property (nonatomic, retain) Notice* notice;
-@property (nonatomic, retain) Path* path;
-@property (nonatomic, retain) App* app;
-@property (nonatomic, retain) Window* window;
-@property (nonatomic, retain) Clipboard* clipboard;
-@property (nonatomic, retain) Fonts* fonts;
-@property (nonatomic, retain) MenuProxy* menu;
-@property (nonatomic, retain) UserDefaults* userDefaults;
-
-@property (nonatomic, retain) WindowController *requestedWindow;
-
-- (id) initWithMenu:(NSMenu*)menu;
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m
deleted file mode 100644
index 50578018..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/WebViewDelegate.m
+++ /dev/null
@@ -1,206 +0,0 @@
-#import "WebViewDelegate.h"
-#import "Sound.h"
-#import "Dock.h"
-#import "Notice.h"
-#import "Path.h"
-#import "App.h"
-#import "Window.h"
-#import "WindowController.h"
-#import "Clipboard.h"
-#import "Fonts.h"
-#import "MenuProxy.h"
-#import "UserDefaults.h"
-
-@implementation WebViewDelegate
-
-@synthesize sound;
-@synthesize dock;
-@synthesize growl;
-@synthesize notice;
-@synthesize path;
-@synthesize app;
-@synthesize window;
-@synthesize requestedWindow;
-@synthesize clipboard;
-@synthesize fonts;
-@synthesize menu;
-@synthesize userDefaults;
-
-- (id) initWithMenu:(NSMenu*)aMenu
-{
- self = [super init];
- if (!self)
- return nil;
-
- mainMenu = aMenu;
- return self;
-}
-
-- (void) webView:(WebView*)webView didClearWindowObject:(WebScriptObject*)windowScriptObject forFrame:(WebFrame *)frame
-{
- JSContextRef context = [frame globalContext];
- if (self.sound == nil) { self.sound = [[Sound alloc] initWithContext:context]; }
- if (self.dock == nil) { self.dock = [Dock new]; }
- if (self.path == nil) { self.path = [Path new]; }
- if (self.clipboard == nil) { self.clipboard = [Clipboard new]; }
- if (self.fonts == nil) { self.fonts = [Fonts new]; }
-
- if (self.notice == nil && [Notice available] == YES) {
- self.notice = [[Notice alloc] initWithWebView:webView];
- }
-
- if (self.app == nil) {
- self.app = [[App alloc] initWithWebView:webView];
- }
-
- if (self.window == nil) {
- self.window = [[Window alloc] initWithWebView:webView];
- }
-
- if (self.menu == nil) {
- self.menu = [MenuProxy proxyWithContext:context andMenu:mainMenu];
- }
-
- if (self.userDefaults == nil) {
- self.userDefaults = [[UserDefaults alloc] initWithWebView:webView];
- }
-
- [windowScriptObject setValue:self forKey:kWebScriptNamespace];
-}
-
-
-- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles{
-
- NSOpenPanel * openDlg = [NSOpenPanel openPanel];
-
- [openDlg setCanChooseFiles:YES];
- [openDlg setCanChooseDirectories:NO];
-
- [openDlg beginWithCompletionHandler:^(NSInteger result){
- if (result == NSFileHandlingPanelOKButton) {
- NSArray * files = [[openDlg URLs] valueForKey: @"relativePath"];
- [resultListener chooseFilenames: files];
- } else {
- [resultListener cancel];
- }
- }];
-}
-
-- (void) webView:(WebView*)webView addMessageToConsole:(NSDictionary*)message
-{
- if (![message isKindOfClass:[NSDictionary class]]) {
- return;
- }
-
- NSLog(@"JavaScript console: %@:%@: %@",
- [[message objectForKey:@"sourceURL"] lastPathComponent], // could be nil
- [message objectForKey:@"lineNumber"],
- [message objectForKey:@"message"]);
-}
-
-- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
-{
- NSAlert *alert = [[NSAlert alloc] init];
- [alert addButtonWithTitle:@"OK"];
- [alert setMessageText:message];
- [alert setAlertStyle:NSWarningAlertStyle];
- [alert runModal];
-}
-
-- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame
-{
- NSAlert *alert = [[NSAlert alloc] init];
- [alert addButtonWithTitle:@"Yes"];
- [alert addButtonWithTitle:@"No"];
- [alert setMessageText:message];
- [alert setAlertStyle:NSWarningAlertStyle];
-
- if ([alert runModal] == NSAlertFirstButtonReturn)
- return YES;
- else
- return NO;
-}
-
-/*
- By default the size of a database is set to 0 [1]. When a database is being created
- it calls this delegate method to get an increase in quota size - or call an error.
- PS this method is defined in WebUIDelegatePrivate and may make it difficult, but
- not impossible [2], to get an app accepted into the mac app store.
-
- Further reading:
- [1] http://stackoverflow.com/questions/353808/implementing-a-webview-database-quota-delegate
- [2] http://stackoverflow.com/questions/4527905/how-do-i-enable-local-storage-in-my-webkit-based-application/4608549#4608549
- */
-- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier
-{
- static const unsigned long long defaultQuota = 5 * 1024 * 1024;
- if ([origin respondsToSelector: @selector(setQuota:)]) {
- [origin performSelector:@selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]];
- } else {
- NSLog(@"could not increase quota for %lld", defaultQuota);
- }
-}
-
-- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
-{
- NSMutableArray *webViewMenuItems = [defaultMenuItems mutableCopy];
-
- if (webViewMenuItems)
- {
- NSEnumerator *itemEnumerator = [defaultMenuItems objectEnumerator];
- NSMenuItem *menuItem = nil;
- while ((menuItem = [itemEnumerator nextObject]))
- {
- NSInteger tag = [menuItem tag];
-
- switch (tag)
- {
- case WebMenuItemTagOpenLinkInNewWindow:
- case WebMenuItemTagDownloadLinkToDisk:
- case WebMenuItemTagCopyLinkToClipboard:
- case WebMenuItemTagOpenImageInNewWindow:
- case WebMenuItemTagDownloadImageToDisk:
- case WebMenuItemTagCopyImageToClipboard:
- case WebMenuItemTagOpenFrameInNewWindow:
- case WebMenuItemTagGoBack:
- case WebMenuItemTagGoForward:
- case WebMenuItemTagStop:
- case WebMenuItemTagOpenWithDefaultApplication:
- case WebMenuItemTagReload:
- [webViewMenuItems removeObjectIdenticalTo: menuItem];
- }
- }
- }
-
- return webViewMenuItems;
-}
-
-- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request{
- requestedWindow = [[WindowController alloc] initWithRequest:request];
- return requestedWindow.contentView.webView;
-}
-
-- (void)webViewShow:(WebView *)sender{
- [requestedWindow showWindow:sender];
-}
-
-- (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener
-{
- [[NSWorkspace sharedWorkspace] openURL:[request URL]];
- [listener ignore];
-}
-
-#pragma mark WebScripting protocol
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return YES;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return NO;
-}
-
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h
deleted file mode 100644
index f721376e..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#import <Foundation/Foundation.h>
-
-#import "WindowController.h"
-
-@interface Window : NSObject{
- CGRect _oldRestoreFrame;
-}
-
-@property (retain, nonatomic) WindowController *windowController;
-@property (nonatomic, retain) WebView *webView;
-
-- (id) initWithWebView:(WebView *)view;
-- (void) open:(NSDictionary *)properties;
-- (void) move:(NSDictionary *)properties;
-- (void) resize:(NSDictionary *) properties;
-- (Boolean) isMaximized;
-- (CGFloat) getX;
-- (CGFloat) getY;
-- (void) maximize;
-- (void) restore;
-- (void) toggleFullscreen;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m
deleted file mode 100644
index 2444f62e..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Classes/Window.m
+++ /dev/null
@@ -1,94 +0,0 @@
-#import "Window.h"
-
-@implementation Window
-
-@synthesize windowController, webView;
-
-- (id) initWithWebView:(WebView*)view
-{
- if(self = [super init]) {
- self.webView = view;
- }
- return self;
-}
-
-- (void) open:(NSDictionary *)properties
-{
- self.windowController = [[WindowController alloc] initWithURL:[properties valueForKey:@"url"]];
- [self.windowController showWindow: [NSApplication sharedApplication].delegate];
- [self.windowController.window makeKeyWindow];
-}
-
-- (void) minimize {
- [[NSApp mainWindow] miniaturize:[NSApp mainWindow]];
-}
-
-- (void) toggleFullscreen {
- [[NSApp mainWindow] toggleFullScreen:[NSApp mainWindow]];
-}
-
-- (void) maximize {
- CGRect a = [NSApp mainWindow].frame;
- _oldRestoreFrame = CGRectMake(a.origin.x, a.origin.y, a.size.width, a.size.height);
- [[NSApp mainWindow] setFrame:[[NSScreen mainScreen] visibleFrame] display:YES];
-}
-
-- (Boolean) isMaximized {
- NSRect a = [NSApp mainWindow].frame;
- NSRect b = [[NSScreen mainScreen] visibleFrame];
- return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height;
-}
-
-- (CGFloat) getX {
- NSRect frame = [self.webView window].frame;
- return frame.origin.x;
-}
-
-- (CGFloat) getY {
- NSRect frame = [self.webView window].frame;
- return frame.origin.y;
-}
-
-- (void) move:(NSDictionary *)properties
-{
- NSRect frame = [self.webView window].frame;
- frame.origin.x = [[properties valueForKey:@"x"] doubleValue];
- frame.origin.y = [[properties valueForKey:@"y"] doubleValue];
- [[self.webView window] setFrame:frame display:YES];
-
-}
-
-- (void) resize:(NSDictionary *) properties
-{
- NSRect frame = [self.webView window].frame;
- frame.size.width = [[properties valueForKey:@"width"] doubleValue];
- frame.size.height = [[properties valueForKey:@"height"] doubleValue];
- [[self.webView window] setFrame:frame display:YES];
-}
-
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return NO;
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector{
- id result = nil;
-
- if (selector == @selector(open:)) {
- result = @"open";
- }else if (selector == @selector(move:)){
- result = @"move";
- }else if (selector == @selector(resize:)){
- result = @"resize";
- }
-
- return result;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return YES;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h
deleted file mode 100644
index 6c1a2f51..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#import <Foundation/Foundation.h>
-
-@interface Clipboard : NSObject {
-
-}
-
-- (void) copy:(NSString*)text;
-- (NSString *) paste;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m
deleted file mode 100644
index 1c18dea3..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/Clipboard.m
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// clipboard.m
-// MacGap
-//
-// Created by David Zorychta on 2013-07-22.
-// Copyright (c) 2013 Twitter. All rights reserved.
-//
-
-#import "Clipboard.h"
-
-@implementation Clipboard
-
-- (void) copy:(NSString*)text {
- [[NSPasteboard generalPasteboard] clearContents];
- [[NSPasteboard generalPasteboard] setString:text forType:NSStringPboardType];
-}
-
-- (NSString *) paste {
- NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
- NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
- NSDictionary *options = [NSDictionary dictionary];
- BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options];
- if (ok) {
- NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
- return (NSString *) [objectsToPaste objectAtIndex:0];
- }
- return @"";
-}
-
-+ (NSString*) webScriptNameForSelector:(SEL)selector
-{
- id result = nil;
-
- if (selector == @selector(copy:)) {
- result = @"copy";
- }
-
- return result;
-}
-
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector
-{
- return NO;
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char*)name
-{
- return YES;
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist
deleted file mode 100644
index 7f71ea22..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Info.plist
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>en</string>
- <key>CFBundleExecutable</key>
- <string>ZeroTier One</string>
- <key>CFBundleIconFile</key>
- <string>ZeroTierIcon</string>
- <key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>ZeroTier One</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.0</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>1</string>
- <key>LSApplicationCategoryType</key>
- <string>public.app-category.utilities</string>
- <key>LSMinimumSystemVersion</key>
- <string>${MACOSX_DEPLOYMENT_TARGET}</string>
- <key>NSMainNibFile</key>
- <string>MainMenu</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
- <key>NSAppTransportSecurity</key>
- <dict>
- <key>NSAllowsArbitraryLoads</key>
- <true/>
- </dict>
-</dict>
-</plist>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch
deleted file mode 100644
index ad05e842..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/MacGap-Prefix.pch
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Prefix header for all source files of the 'MacGap' target in the 'MacGap' project
-//
-
-#ifdef __OBJC__
- #ifdef _DEBUG
- #define DebugNSLog(format, ...) NSLog(format, ## __VA_ARGS__)
- #else
- #define DebugNSLog(format, ...)
- #endif
-
- #import <Cocoa/Cocoa.h>
- #import "Constants.h"
- #import "Utils.h"
-#endif
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h
deleted file mode 100644
index 72927eff..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#import <Cocoa/Cocoa.h>
-#import "ContentView.h"
-
-@interface WindowController : NSWindowController {
-
-}
-
-- (id) initWithURL:(NSString *) url;
-- (id) initWithRequest: (NSURLRequest *)request;
-@property (retain) NSURL * url;
-@property (retain) IBOutlet ContentView *contentView;
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m
deleted file mode 100644
index 2765a2e3..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/WindowController.m
+++ /dev/null
@@ -1,54 +0,0 @@
-#import "WindowController.h"
-
-
-@interface WindowController() {
-
-}
-
--(void) notificationCenter;
-
-@end
-
-@implementation WindowController
-
-@synthesize contentView, url;
-
-- (id) initWithURL:(NSString *) relativeURL{
- self = [super initWithWindowNibName:@"Window"];
- self.url = [NSURL URLWithString:relativeURL relativeToURL:[[NSBundle mainBundle] resourceURL]];
-
- [self.window setFrameAutosaveName:@"MacGapWindow"];
- [self notificationCenter];
-
- return self;
-}
-
--(id) initWithRequest: (NSURLRequest *)request{
- self = [super initWithWindowNibName:@"Window"];
- [self notificationCenter];
- [[self.contentView.webView mainFrame] loadRequest:request];
-
- return self;
-}
-
--(void) notificationCenter{
- [[NSNotificationCenter defaultCenter] addObserver:self.contentView
- selector:@selector(windowResized:)
- name:NSWindowDidResizeNotification
- object:[self window]];
-}
-
-- (void)windowDidLoad
-{
- [super windowDidLoad];
-
- if (self.url != nil) {
- [self.contentView.webView setMainFrameURL:[self.url absoluteString]];
- }
-
-
- // Implement this method to handle any initialization after your
- // window controller's window has been loaded from its nib file.
-}
-
-@end
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf
deleted file mode 100644
index 6f388f66..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Credits.rtf
+++ /dev/null
@@ -1,13 +0,0 @@
-{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\vieww9600\viewh8400\viewkind0
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
-
-\f0\b\fs24 \cf0 (c)2011-2015 ZeroTier, Inc.\
-Licensed under the GNU GPLv3\
-\
-UI Wrapper MacGap (c) Twitter, Inc.\
-Licensed under the MIT License\
-http://macgap.com/\
-} \ No newline at end of file
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings
deleted file mode 100644
index 477b28ff..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/InfoPlist.strings
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Localized versions of Info.plist keys */
-
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib
deleted file mode 100644
index dd67a86a..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib
+++ /dev/null
@@ -1,3404 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
- <data>
- <int key="IBDocument.SystemTarget">1070</int>
- <string key="IBDocument.SystemVersion">14D136</string>
- <string key="IBDocument.InterfaceBuilderVersion">7702</string>
- <string key="IBDocument.AppKitVersion">1347.57</string>
- <string key="IBDocument.HIToolboxVersion">758.70</string>
- <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="NS.object.0">7702</string>
- </object>
- <array key="IBDocument.IntegratedClassDependencies">
- <string>NSCustomObject</string>
- <string>NSMenu</string>
- <string>NSMenuItem</string>
- </array>
- <array key="IBDocument.PluginDependencies">
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- </array>
- <object class="NSMutableDictionary" key="IBDocument.Metadata">
- <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
- <integer value="1" key="NS.object.0"/>
- </object>
- <array class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
- <object class="NSCustomObject" id="1021">
- <string key="NSClassName">NSApplication</string>
- </object>
- <object class="NSCustomObject" id="1014">
- <string key="NSClassName">FirstResponder</string>
- </object>
- <object class="NSCustomObject" id="1050">
- <string key="NSClassName">NSApplication</string>
- </object>
- <object class="NSCustomObject" id="976324537">
- <string key="NSClassName">AppDelegate</string>
- </object>
- <object class="NSMenu" id="649796088">
- <string key="NSTitle">AMainMenu</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="694149608">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">ZeroTier One</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <object class="NSCustomResource" key="NSOnImage" id="35465992">
- <string key="NSClassName">NSImage</string>
- <string key="NSResourceName">NSMenuCheckmark</string>
- </object>
- <object class="NSCustomResource" key="NSMixedImage" id="502551668">
- <string key="NSClassName">NSImage</string>
- <string key="NSResourceName">NSMenuMixedState</string>
- </object>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="110575045"/>
- <object class="NSMenu" key="NSSubmenu" id="110575045">
- <string key="NSTitle">ZeroTier One</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="238522557">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">About ZeroTier One</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="304266470">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="609285721">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Preferences…</string>
- <string key="NSKeyEquiv">,</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="481834944">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1046388886">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Services</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="752062318"/>
- <object class="NSMenu" key="NSSubmenu" id="752062318">
- <string key="NSTitle">Services</string>
- <array class="NSMutableArray" key="NSMenuItems"/>
- <string key="NSName">_NSServicesMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="646227648">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="755159360">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Hide ZeroTier One</string>
- <string key="NSKeyEquiv">h</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="342932134">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Hide Others</string>
- <string key="NSKeyEquiv">h</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="908899353">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Show All</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1056857174">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="632727374">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Quit ZeroTier One</string>
- <string key="NSKeyEquiv">q</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- <string key="NSName">_NSAppleMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="379814623">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">File</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="720053764"/>
- <object class="NSMenu" key="NSSubmenu" id="720053764">
- <string key="NSTitle">File</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="705341025">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">New</string>
- <string key="NSKeyEquiv">n</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="722745758">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Open…</string>
- <string key="NSKeyEquiv">o</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1025936716">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Open Recent</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="1065607017"/>
- <object class="NSMenu" key="NSSubmenu" id="1065607017">
- <string key="NSTitle">Open Recent</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="759406840">
- <reference key="NSMenu" ref="1065607017"/>
- <string key="NSTitle">Clear Menu</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- <string key="NSName">_NSRecentDocumentsMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="425164168">
- <reference key="NSMenu" ref="720053764"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="776162233">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Close</string>
- <string key="NSKeyEquiv">w</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1023925487">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Save…</string>
- <string key="NSKeyEquiv">s</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="579971712">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Revert to Saved</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1010469920">
- <reference key="NSMenu" ref="720053764"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="294629803">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Page Setup...</string>
- <string key="NSKeyEquiv">P</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSToolTip"/>
- </object>
- <object class="NSMenuItem" id="49223823">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Print…</string>
- <string key="NSKeyEquiv">p</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="952259628">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Edit</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="789758025"/>
- <object class="NSMenu" key="NSSubmenu" id="789758025">
- <string key="NSTitle">Edit</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="1058277027">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Undo</string>
- <string key="NSKeyEquiv">z</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="790794224">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Redo</string>
- <string key="NSKeyEquiv">Z</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1040322652">
- <reference key="NSMenu" ref="789758025"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="296257095">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Cut</string>
- <string key="NSKeyEquiv">x</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="860595796">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Copy</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="29853731">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Paste</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="82994268">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Paste and Match Style</string>
- <string key="NSKeyEquiv">V</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="437104165">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Delete</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="583158037">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Select All</string>
- <string key="NSKeyEquiv">a</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="212016141">
- <reference key="NSMenu" ref="789758025"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="892235320">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Find</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="963351320"/>
- <object class="NSMenu" key="NSSubmenu" id="963351320">
- <string key="NSTitle">Find</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="447796847">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find…</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="738670835">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find and Replace…</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">12</int>
- </object>
- <object class="NSMenuItem" id="326711663">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find Next</string>
- <string key="NSKeyEquiv">g</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="270902937">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find Previous</string>
- <string key="NSKeyEquiv">G</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="159080638">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Use Selection for Find</string>
- <string key="NSKeyEquiv">e</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">7</int>
- </object>
- <object class="NSMenuItem" id="88285865">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Jump to Selection</string>
- <string key="NSKeyEquiv">j</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="972420730">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Spelling and Grammar</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="769623530"/>
- <object class="NSMenu" key="NSSubmenu" id="769623530">
- <string key="NSTitle">Spelling and Grammar</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="679648819">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Show Spelling and Grammar</string>
- <string key="NSKeyEquiv">:</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="96193923">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Check Document Now</string>
- <string key="NSKeyEquiv">;</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="859480356">
- <reference key="NSMenu" ref="769623530"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="948374510">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Check Spelling While Typing</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="967646866">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Check Grammar With Spelling</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="795346622">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Correct Spelling Automatically</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="507821607">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Substitutions</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="698887838"/>
- <object class="NSMenu" key="NSSubmenu" id="698887838">
- <string key="NSTitle">Substitutions</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="65139061">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Show Substitutions</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="19036812">
- <reference key="NSMenu" ref="698887838"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="605118523">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Copy/Paste</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="197661976">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Quotes</string>
- <string key="NSKeyEquiv">g</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="672708820">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Dashes</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="708854459">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Links</string>
- <string key="NSKeyEquiv">G</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="537092702">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Text Replacement</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="288088188">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Transformations</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="579392910"/>
- <object class="NSMenu" key="NSSubmenu" id="579392910">
- <string key="NSTitle">Transformations</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="1060694897">
- <reference key="NSMenu" ref="579392910"/>
- <string key="NSTitle">Make Upper Case</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="879586729">
- <reference key="NSMenu" ref="579392910"/>
- <string key="NSTitle">Make Lower Case</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="56570060">
- <reference key="NSMenu" ref="579392910"/>
- <string key="NSTitle">Capitalize</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="676164635">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Speech</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="785027613"/>
- <object class="NSMenu" key="NSSubmenu" id="785027613">
- <string key="NSTitle">Speech</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="731782645">
- <reference key="NSMenu" ref="785027613"/>
- <string key="NSTitle">Start Speaking</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="680220178">
- <reference key="NSMenu" ref="785027613"/>
- <string key="NSTitle">Stop Speaking</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="302598603">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Format</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="941447902"/>
- <object class="NSMenu" key="NSSubmenu" id="941447902">
- <string key="NSTitle">Format</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="792887677">
- <reference key="NSMenu" ref="941447902"/>
- <string key="NSTitle">Font</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="786677654"/>
- <object class="NSMenu" key="NSSubmenu" id="786677654">
- <string key="NSTitle">Font</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="159677712">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Show Fonts</string>
- <string key="NSKeyEquiv">t</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="305399458">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Bold</string>
- <string key="NSKeyEquiv">b</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="814362025">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Italic</string>
- <string key="NSKeyEquiv">i</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="330926929">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Underline</string>
- <string key="NSKeyEquiv">u</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="533507878">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="158063935">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Bigger</string>
- <string key="NSKeyEquiv">+</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="885547335">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Smaller</string>
- <string key="NSKeyEquiv">-</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">4</int>
- </object>
- <object class="NSMenuItem" id="901062459">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="767671776">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Kern</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="175441468"/>
- <object class="NSMenu" key="NSSubmenu" id="175441468">
- <string key="NSTitle">Kern</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="252969304">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="766922938">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Use None</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="677519740">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Tighten</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="238351151">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Loosen</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="691570813">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Ligature</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="1058217995"/>
- <object class="NSMenu" key="NSSubmenu" id="1058217995">
- <string key="NSTitle">Ligature</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="706297211">
- <reference key="NSMenu" ref="1058217995"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="568384683">
- <reference key="NSMenu" ref="1058217995"/>
- <string key="NSTitle">Use None</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="663508465">
- <reference key="NSMenu" ref="1058217995"/>
- <string key="NSTitle">Use All</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="769124883">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Baseline</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="18263474"/>
- <object class="NSMenu" key="NSSubmenu" id="18263474">
- <string key="NSTitle">Baseline</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="257962622">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="644725453">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Superscript</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1037576581">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Subscript</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="941806246">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Raise</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1045724900">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Lower</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="739652853">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1012600125">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Show Colors</string>
- <string key="NSKeyEquiv">C</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="214559597">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="596732606">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Copy Style</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="393423671">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Paste Style</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- <string key="NSName">_NSFontMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="215659978">
- <reference key="NSMenu" ref="941447902"/>
- <string key="NSTitle">Text</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="446991534"/>
- <object class="NSMenu" key="NSSubmenu" id="446991534">
- <string key="NSTitle">Text</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="875092757">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Align Left</string>
- <string key="NSKeyEquiv">{</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="630155264">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Center</string>
- <string key="NSKeyEquiv">|</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="945678886">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Justify</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="512868991">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Align Right</string>
- <string key="NSKeyEquiv">}</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="163117631">
- <reference key="NSMenu" ref="446991534"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="31516759">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Writing Direction</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="956096989"/>
- <object class="NSMenu" key="NSSubmenu" id="956096989">
- <string key="NSTitle">Writing Direction</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="257099033">
- <reference key="NSMenu" ref="956096989"/>
- <bool key="NSIsDisabled">YES</bool>
- <string key="NSTitle">Paragraph</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="551969625">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="249532473">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="607364498">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="508151438">
- <reference key="NSMenu" ref="956096989"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="981751889">
- <reference key="NSMenu" ref="956096989"/>
- <bool key="NSIsDisabled">YES</bool>
- <string key="NSTitle">Selection</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="380031999">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="825984362">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="560145579">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="908105787">
- <reference key="NSMenu" ref="446991534"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="644046920">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Show Ruler</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="231811626">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Copy Ruler</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1310720</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="883618387">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Paste Ruler</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1310720</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="586577488">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">View</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="466310130"/>
- <object class="NSMenu" key="NSSubmenu" id="466310130">
- <string key="NSTitle">View</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="102151532">
- <reference key="NSMenu" ref="466310130"/>
- <string key="NSTitle">Show Toolbar</string>
- <string key="NSKeyEquiv">t</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="237841660">
- <reference key="NSMenu" ref="466310130"/>
- <string key="NSTitle">Customize Toolbar…</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- </object>
- </object>
- <object class="NSMenuItem" id="713487014">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Window</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="835318025"/>
- <object class="NSMenu" key="NSSubmenu" id="835318025">
- <string key="NSTitle">Window</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="1011231497">
- <reference key="NSMenu" ref="835318025"/>
- <string key="NSTitle">Minimize</string>
- <string key="NSKeyEquiv">m</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="575023229">
- <reference key="NSMenu" ref="835318025"/>
- <string key="NSTitle">Zoom</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="299356726">
- <reference key="NSMenu" ref="835318025"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="625202149">
- <reference key="NSMenu" ref="835318025"/>
- <string key="NSTitle">Bring All to Front</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- <string key="NSName">_NSWindowsMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="448692316">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Help</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <reference key="NSTarget" ref="992780483"/>
- <object class="NSMenu" key="NSSubmenu" id="992780483">
- <string key="NSTitle">Help</string>
- <array class="NSMutableArray" key="NSMenuItems">
- <object class="NSMenuItem" id="105068016">
- <reference key="NSMenu" ref="992780483"/>
- <string key="NSTitle">ZeroTier One Help</string>
- <string key="NSKeyEquiv">?</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </array>
- <string key="NSName">_NSHelpMenu</string>
- </object>
- </object>
- </array>
- <string key="NSName">_NSMainMenu</string>
- </object>
- </array>
- <object class="IBObjectContainer" key="IBDocument.Objects">
- <array key="connectionRecords">
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">terminate:</string>
- <reference key="source" ref="1050"/>
- <reference key="destination" ref="632727374"/>
- </object>
- <int key="connectionID">449</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontStandardAboutPanel:</string>
- <reference key="source" ref="1021"/>
- <reference key="destination" ref="238522557"/>
- </object>
- <int key="connectionID">142</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">delegate</string>
- <reference key="source" ref="1021"/>
- <reference key="destination" ref="976324537"/>
- </object>
- <int key="connectionID">547</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performMiniaturize:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1011231497"/>
- </object>
- <int key="connectionID">37</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">arrangeInFront:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="625202149"/>
- </object>
- <int key="connectionID">39</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">print:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="49223823"/>
- </object>
- <int key="connectionID">86</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">runPageLayout:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="294629803"/>
- </object>
- <int key="connectionID">87</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">clearRecentDocuments:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="759406840"/>
- </object>
- <int key="connectionID">127</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performClose:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="776162233"/>
- </object>
- <int key="connectionID">193</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleContinuousSpellChecking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="948374510"/>
- </object>
- <int key="connectionID">222</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">undo:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1058277027"/>
- </object>
- <int key="connectionID">223</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">copy:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="860595796"/>
- </object>
- <int key="connectionID">224</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">checkSpelling:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="96193923"/>
- </object>
- <int key="connectionID">225</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">paste:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="29853731"/>
- </object>
- <int key="connectionID">226</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">stopSpeaking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="680220178"/>
- </object>
- <int key="connectionID">227</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">cut:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="296257095"/>
- </object>
- <int key="connectionID">228</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">showGuessPanel:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="679648819"/>
- </object>
- <int key="connectionID">230</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">redo:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="790794224"/>
- </object>
- <int key="connectionID">231</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">selectAll:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="583158037"/>
- </object>
- <int key="connectionID">232</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">startSpeaking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="731782645"/>
- </object>
- <int key="connectionID">233</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">delete:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="437104165"/>
- </object>
- <int key="connectionID">235</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performZoom:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="575023229"/>
- </object>
- <int key="connectionID">240</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="447796847"/>
- </object>
- <int key="connectionID">241</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">centerSelectionInVisibleArea:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="88285865"/>
- </object>
- <int key="connectionID">245</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleGrammarChecking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="967646866"/>
- </object>
- <int key="connectionID">347</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleSmartInsertDelete:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="605118523"/>
- </object>
- <int key="connectionID">355</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticQuoteSubstitution:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="197661976"/>
- </object>
- <int key="connectionID">356</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticLinkDetection:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="708854459"/>
- </object>
- <int key="connectionID">357</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">saveDocument:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1023925487"/>
- </object>
- <int key="connectionID">362</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">revertDocumentToSaved:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="579971712"/>
- </object>
- <int key="connectionID">364</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">runToolbarCustomizationPalette:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="237841660"/>
- </object>
- <int key="connectionID">365</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleToolbarShown:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="102151532"/>
- </object>
- <int key="connectionID">366</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">hide:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="755159360"/>
- </object>
- <int key="connectionID">367</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">hideOtherApplications:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="342932134"/>
- </object>
- <int key="connectionID">368</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">unhideAllApplications:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="908899353"/>
- </object>
- <int key="connectionID">370</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">newDocument:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="705341025"/>
- </object>
- <int key="connectionID">373</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">openDocument:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="722745758"/>
- </object>
- <int key="connectionID">374</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">raiseBaseline:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="941806246"/>
- </object>
- <int key="connectionID">426</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">lowerBaseline:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1045724900"/>
- </object>
- <int key="connectionID">427</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">copyFont:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="596732606"/>
- </object>
- <int key="connectionID">428</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">subscript:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1037576581"/>
- </object>
- <int key="connectionID">429</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">superscript:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="644725453"/>
- </object>
- <int key="connectionID">430</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">tightenKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="677519740"/>
- </object>
- <int key="connectionID">431</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">underline:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="330926929"/>
- </object>
- <int key="connectionID">432</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontColorPanel:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1012600125"/>
- </object>
- <int key="connectionID">433</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">useAllLigatures:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="663508465"/>
- </object>
- <int key="connectionID">434</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">loosenKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="238351151"/>
- </object>
- <int key="connectionID">435</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">pasteFont:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="393423671"/>
- </object>
- <int key="connectionID">436</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">unscript:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="257962622"/>
- </object>
- <int key="connectionID">437</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">useStandardKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="252969304"/>
- </object>
- <int key="connectionID">438</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">useStandardLigatures:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="706297211"/>
- </object>
- <int key="connectionID">439</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">turnOffLigatures:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="568384683"/>
- </object>
- <int key="connectionID">440</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">turnOffKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="766922938"/>
- </object>
- <int key="connectionID">441</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticSpellingCorrection:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="795346622"/>
- </object>
- <int key="connectionID">456</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontSubstitutionsPanel:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="65139061"/>
- </object>
- <int key="connectionID">458</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticDashSubstitution:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="672708820"/>
- </object>
- <int key="connectionID">461</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticTextReplacement:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="537092702"/>
- </object>
- <int key="connectionID">463</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">uppercaseWord:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1060694897"/>
- </object>
- <int key="connectionID">464</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">capitalizeWord:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="56570060"/>
- </object>
- <int key="connectionID">467</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">lowercaseWord:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="879586729"/>
- </object>
- <int key="connectionID">468</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">pasteAsPlainText:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="82994268"/>
- </object>
- <int key="connectionID">486</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="326711663"/>
- </object>
- <int key="connectionID">487</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="270902937"/>
- </object>
- <int key="connectionID">488</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="159080638"/>
- </object>
- <int key="connectionID">489</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">showHelp:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="105068016"/>
- </object>
- <int key="connectionID">493</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignCenter:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="630155264"/>
- </object>
- <int key="connectionID">518</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">pasteRuler:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="883618387"/>
- </object>
- <int key="connectionID">519</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleRuler:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="644046920"/>
- </object>
- <int key="connectionID">520</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignRight:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="512868991"/>
- </object>
- <int key="connectionID">521</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">copyRuler:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="231811626"/>
- </object>
- <int key="connectionID">522</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignJustified:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="945678886"/>
- </object>
- <int key="connectionID">523</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignLeft:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="875092757"/>
- </object>
- <int key="connectionID">524</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeBaseWritingDirectionNatural:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="551969625"/>
- </object>
- <int key="connectionID">525</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeBaseWritingDirectionLeftToRight:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="249532473"/>
- </object>
- <int key="connectionID">526</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeBaseWritingDirectionRightToLeft:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="607364498"/>
- </object>
- <int key="connectionID">527</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeTextWritingDirectionNatural:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="380031999"/>
- </object>
- <int key="connectionID">528</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeTextWritingDirectionLeftToRight:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="825984362"/>
- </object>
- <int key="connectionID">529</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeTextWritingDirectionRightToLeft:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="560145579"/>
- </object>
- <int key="connectionID">530</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="738670835"/>
- </object>
- <int key="connectionID">535</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">delegate</string>
- <reference key="source" ref="649796088"/>
- <reference key="destination" ref="1021"/>
- </object>
- <int key="connectionID">545</int>
- </object>
- </array>
- <object class="IBMutableOrderedSet" key="objectRecords">
- <array key="orderedObjects">
- <object class="IBObjectRecord">
- <int key="objectID">0</int>
- <array key="object" id="0"/>
- <reference key="children" ref="1048"/>
- <nil key="parent"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-2</int>
- <reference key="object" ref="1021"/>
- <reference key="parent" ref="0"/>
- <string key="objectName">File's Owner</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-1</int>
- <reference key="object" ref="1014"/>
- <reference key="parent" ref="0"/>
- <string key="objectName">First Responder</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-3</int>
- <reference key="object" ref="1050"/>
- <reference key="parent" ref="0"/>
- <string key="objectName">Application</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">29</int>
- <reference key="object" ref="649796088"/>
- <array class="NSMutableArray" key="children">
- <reference ref="713487014"/>
- <reference ref="694149608"/>
- <reference ref="952259628"/>
- <reference ref="379814623"/>
- <reference ref="586577488"/>
- <reference ref="302598603"/>
- <reference ref="448692316"/>
- </array>
- <reference key="parent" ref="0"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">19</int>
- <reference key="object" ref="713487014"/>
- <array class="NSMutableArray" key="children">
- <reference ref="835318025"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">56</int>
- <reference key="object" ref="694149608"/>
- <array class="NSMutableArray" key="children">
- <reference ref="110575045"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">217</int>
- <reference key="object" ref="952259628"/>
- <array class="NSMutableArray" key="children">
- <reference ref="789758025"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">83</int>
- <reference key="object" ref="379814623"/>
- <array class="NSMutableArray" key="children">
- <reference ref="720053764"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">81</int>
- <reference key="object" ref="720053764"/>
- <array class="NSMutableArray" key="children">
- <reference ref="1023925487"/>
- <reference ref="49223823"/>
- <reference ref="722745758"/>
- <reference ref="705341025"/>
- <reference ref="1025936716"/>
- <reference ref="294629803"/>
- <reference ref="776162233"/>
- <reference ref="425164168"/>
- <reference ref="579971712"/>
- <reference ref="1010469920"/>
- </array>
- <reference key="parent" ref="379814623"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">75</int>
- <reference key="object" ref="1023925487"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">78</int>
- <reference key="object" ref="49223823"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">72</int>
- <reference key="object" ref="722745758"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">82</int>
- <reference key="object" ref="705341025"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">124</int>
- <reference key="object" ref="1025936716"/>
- <array class="NSMutableArray" key="children">
- <reference ref="1065607017"/>
- </array>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">77</int>
- <reference key="object" ref="294629803"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">73</int>
- <reference key="object" ref="776162233"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">79</int>
- <reference key="object" ref="425164168"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">112</int>
- <reference key="object" ref="579971712"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">74</int>
- <reference key="object" ref="1010469920"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">125</int>
- <reference key="object" ref="1065607017"/>
- <array class="NSMutableArray" key="children">
- <reference ref="759406840"/>
- </array>
- <reference key="parent" ref="1025936716"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">126</int>
- <reference key="object" ref="759406840"/>
- <reference key="parent" ref="1065607017"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">205</int>
- <reference key="object" ref="789758025"/>
- <array class="NSMutableArray" key="children">
- <reference ref="437104165"/>
- <reference ref="583158037"/>
- <reference ref="1058277027"/>
- <reference ref="212016141"/>
- <reference ref="296257095"/>
- <reference ref="29853731"/>
- <reference ref="860595796"/>
- <reference ref="1040322652"/>
- <reference ref="790794224"/>
- <reference ref="892235320"/>
- <reference ref="972420730"/>
- <reference ref="676164635"/>
- <reference ref="507821607"/>
- <reference ref="288088188"/>
- <reference ref="82994268"/>
- </array>
- <reference key="parent" ref="952259628"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">202</int>
- <reference key="object" ref="437104165"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">198</int>
- <reference key="object" ref="583158037"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">207</int>
- <reference key="object" ref="1058277027"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">214</int>
- <reference key="object" ref="212016141"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">199</int>
- <reference key="object" ref="296257095"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">203</int>
- <reference key="object" ref="29853731"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">197</int>
- <reference key="object" ref="860595796"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">206</int>
- <reference key="object" ref="1040322652"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">215</int>
- <reference key="object" ref="790794224"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">218</int>
- <reference key="object" ref="892235320"/>
- <array class="NSMutableArray" key="children">
- <reference ref="963351320"/>
- </array>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">216</int>
- <reference key="object" ref="972420730"/>
- <array class="NSMutableArray" key="children">
- <reference ref="769623530"/>
- </array>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">200</int>
- <reference key="object" ref="769623530"/>
- <array class="NSMutableArray" key="children">
- <reference ref="948374510"/>
- <reference ref="96193923"/>
- <reference ref="679648819"/>
- <reference ref="967646866"/>
- <reference ref="859480356"/>
- <reference ref="795346622"/>
- </array>
- <reference key="parent" ref="972420730"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">219</int>
- <reference key="object" ref="948374510"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">201</int>
- <reference key="object" ref="96193923"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">204</int>
- <reference key="object" ref="679648819"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">220</int>
- <reference key="object" ref="963351320"/>
- <array class="NSMutableArray" key="children">
- <reference ref="270902937"/>
- <reference ref="88285865"/>
- <reference ref="159080638"/>
- <reference ref="326711663"/>
- <reference ref="447796847"/>
- <reference ref="738670835"/>
- </array>
- <reference key="parent" ref="892235320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">213</int>
- <reference key="object" ref="270902937"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">210</int>
- <reference key="object" ref="88285865"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">221</int>
- <reference key="object" ref="159080638"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">208</int>
- <reference key="object" ref="326711663"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">209</int>
- <reference key="object" ref="447796847"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">57</int>
- <reference key="object" ref="110575045"/>
- <array class="NSMutableArray" key="children">
- <reference ref="238522557"/>
- <reference ref="755159360"/>
- <reference ref="908899353"/>
- <reference ref="632727374"/>
- <reference ref="646227648"/>
- <reference ref="609285721"/>
- <reference ref="481834944"/>
- <reference ref="304266470"/>
- <reference ref="1046388886"/>
- <reference ref="1056857174"/>
- <reference ref="342932134"/>
- </array>
- <reference key="parent" ref="694149608"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">58</int>
- <reference key="object" ref="238522557"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">134</int>
- <reference key="object" ref="755159360"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">150</int>
- <reference key="object" ref="908899353"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">136</int>
- <reference key="object" ref="632727374"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">144</int>
- <reference key="object" ref="646227648"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">129</int>
- <reference key="object" ref="609285721"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">143</int>
- <reference key="object" ref="481834944"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">236</int>
- <reference key="object" ref="304266470"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">131</int>
- <reference key="object" ref="1046388886"/>
- <array class="NSMutableArray" key="children">
- <reference ref="752062318"/>
- </array>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">149</int>
- <reference key="object" ref="1056857174"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">145</int>
- <reference key="object" ref="342932134"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">130</int>
- <reference key="object" ref="752062318"/>
- <reference key="parent" ref="1046388886"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">24</int>
- <reference key="object" ref="835318025"/>
- <array class="NSMutableArray" key="children">
- <reference ref="299356726"/>
- <reference ref="625202149"/>
- <reference ref="575023229"/>
- <reference ref="1011231497"/>
- </array>
- <reference key="parent" ref="713487014"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">92</int>
- <reference key="object" ref="299356726"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">5</int>
- <reference key="object" ref="625202149"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">239</int>
- <reference key="object" ref="575023229"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">23</int>
- <reference key="object" ref="1011231497"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">295</int>
- <reference key="object" ref="586577488"/>
- <array class="NSMutableArray" key="children">
- <reference ref="466310130"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">296</int>
- <reference key="object" ref="466310130"/>
- <array class="NSMutableArray" key="children">
- <reference ref="102151532"/>
- <reference ref="237841660"/>
- </array>
- <reference key="parent" ref="586577488"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">297</int>
- <reference key="object" ref="102151532"/>
- <reference key="parent" ref="466310130"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">298</int>
- <reference key="object" ref="237841660"/>
- <reference key="parent" ref="466310130"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">211</int>
- <reference key="object" ref="676164635"/>
- <array class="NSMutableArray" key="children">
- <reference ref="785027613"/>
- </array>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">212</int>
- <reference key="object" ref="785027613"/>
- <array class="NSMutableArray" key="children">
- <reference ref="680220178"/>
- <reference ref="731782645"/>
- </array>
- <reference key="parent" ref="676164635"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">195</int>
- <reference key="object" ref="680220178"/>
- <reference key="parent" ref="785027613"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">196</int>
- <reference key="object" ref="731782645"/>
- <reference key="parent" ref="785027613"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">346</int>
- <reference key="object" ref="967646866"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">348</int>
- <reference key="object" ref="507821607"/>
- <array class="NSMutableArray" key="children">
- <reference ref="698887838"/>
- </array>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">349</int>
- <reference key="object" ref="698887838"/>
- <array class="NSMutableArray" key="children">
- <reference ref="605118523"/>
- <reference ref="197661976"/>
- <reference ref="708854459"/>
- <reference ref="65139061"/>
- <reference ref="19036812"/>
- <reference ref="672708820"/>
- <reference ref="537092702"/>
- </array>
- <reference key="parent" ref="507821607"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">350</int>
- <reference key="object" ref="605118523"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">351</int>
- <reference key="object" ref="197661976"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">354</int>
- <reference key="object" ref="708854459"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">375</int>
- <reference key="object" ref="302598603"/>
- <array class="NSMutableArray" key="children">
- <reference ref="941447902"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">376</int>
- <reference key="object" ref="941447902"/>
- <array class="NSMutableArray" key="children">
- <reference ref="792887677"/>
- <reference ref="215659978"/>
- </array>
- <reference key="parent" ref="302598603"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">377</int>
- <reference key="object" ref="792887677"/>
- <array class="NSMutableArray" key="children">
- <reference ref="786677654"/>
- </array>
- <reference key="parent" ref="941447902"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">388</int>
- <reference key="object" ref="786677654"/>
- <array class="NSMutableArray" key="children">
- <reference ref="159677712"/>
- <reference ref="305399458"/>
- <reference ref="814362025"/>
- <reference ref="330926929"/>
- <reference ref="533507878"/>
- <reference ref="158063935"/>
- <reference ref="885547335"/>
- <reference ref="901062459"/>
- <reference ref="767671776"/>
- <reference ref="691570813"/>
- <reference ref="769124883"/>
- <reference ref="739652853"/>
- <reference ref="1012600125"/>
- <reference ref="214559597"/>
- <reference ref="596732606"/>
- <reference ref="393423671"/>
- </array>
- <reference key="parent" ref="792887677"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">389</int>
- <reference key="object" ref="159677712"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">390</int>
- <reference key="object" ref="305399458"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">391</int>
- <reference key="object" ref="814362025"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">392</int>
- <reference key="object" ref="330926929"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">393</int>
- <reference key="object" ref="533507878"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">394</int>
- <reference key="object" ref="158063935"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">395</int>
- <reference key="object" ref="885547335"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">396</int>
- <reference key="object" ref="901062459"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">397</int>
- <reference key="object" ref="767671776"/>
- <array class="NSMutableArray" key="children">
- <reference ref="175441468"/>
- </array>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">398</int>
- <reference key="object" ref="691570813"/>
- <array class="NSMutableArray" key="children">
- <reference ref="1058217995"/>
- </array>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">399</int>
- <reference key="object" ref="769124883"/>
- <array class="NSMutableArray" key="children">
- <reference ref="18263474"/>
- </array>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">400</int>
- <reference key="object" ref="739652853"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">401</int>
- <reference key="object" ref="1012600125"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">402</int>
- <reference key="object" ref="214559597"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">403</int>
- <reference key="object" ref="596732606"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">404</int>
- <reference key="object" ref="393423671"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">405</int>
- <reference key="object" ref="18263474"/>
- <array class="NSMutableArray" key="children">
- <reference ref="257962622"/>
- <reference ref="644725453"/>
- <reference ref="1037576581"/>
- <reference ref="941806246"/>
- <reference ref="1045724900"/>
- </array>
- <reference key="parent" ref="769124883"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">406</int>
- <reference key="object" ref="257962622"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">407</int>
- <reference key="object" ref="644725453"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">408</int>
- <reference key="object" ref="1037576581"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">409</int>
- <reference key="object" ref="941806246"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">410</int>
- <reference key="object" ref="1045724900"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">411</int>
- <reference key="object" ref="1058217995"/>
- <array class="NSMutableArray" key="children">
- <reference ref="706297211"/>
- <reference ref="568384683"/>
- <reference ref="663508465"/>
- </array>
- <reference key="parent" ref="691570813"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">412</int>
- <reference key="object" ref="706297211"/>
- <reference key="parent" ref="1058217995"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">413</int>
- <reference key="object" ref="568384683"/>
- <reference key="parent" ref="1058217995"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">414</int>
- <reference key="object" ref="663508465"/>
- <reference key="parent" ref="1058217995"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">415</int>
- <reference key="object" ref="175441468"/>
- <array class="NSMutableArray" key="children">
- <reference ref="252969304"/>
- <reference ref="766922938"/>
- <reference ref="677519740"/>
- <reference ref="238351151"/>
- </array>
- <reference key="parent" ref="767671776"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">416</int>
- <reference key="object" ref="252969304"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">417</int>
- <reference key="object" ref="766922938"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">418</int>
- <reference key="object" ref="677519740"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">419</int>
- <reference key="object" ref="238351151"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">450</int>
- <reference key="object" ref="288088188"/>
- <array class="NSMutableArray" key="children">
- <reference ref="579392910"/>
- </array>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">451</int>
- <reference key="object" ref="579392910"/>
- <array class="NSMutableArray" key="children">
- <reference ref="1060694897"/>
- <reference ref="879586729"/>
- <reference ref="56570060"/>
- </array>
- <reference key="parent" ref="288088188"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">452</int>
- <reference key="object" ref="1060694897"/>
- <reference key="parent" ref="579392910"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">453</int>
- <reference key="object" ref="859480356"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">454</int>
- <reference key="object" ref="795346622"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">457</int>
- <reference key="object" ref="65139061"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">459</int>
- <reference key="object" ref="19036812"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">460</int>
- <reference key="object" ref="672708820"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">462</int>
- <reference key="object" ref="537092702"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">465</int>
- <reference key="object" ref="879586729"/>
- <reference key="parent" ref="579392910"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">466</int>
- <reference key="object" ref="56570060"/>
- <reference key="parent" ref="579392910"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">485</int>
- <reference key="object" ref="82994268"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">490</int>
- <reference key="object" ref="448692316"/>
- <array class="NSMutableArray" key="children">
- <reference ref="992780483"/>
- </array>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">491</int>
- <reference key="object" ref="992780483"/>
- <array class="NSMutableArray" key="children">
- <reference ref="105068016"/>
- </array>
- <reference key="parent" ref="448692316"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">492</int>
- <reference key="object" ref="105068016"/>
- <reference key="parent" ref="992780483"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">496</int>
- <reference key="object" ref="215659978"/>
- <array class="NSMutableArray" key="children">
- <reference ref="446991534"/>
- </array>
- <reference key="parent" ref="941447902"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">497</int>
- <reference key="object" ref="446991534"/>
- <array class="NSMutableArray" key="children">
- <reference ref="875092757"/>
- <reference ref="630155264"/>
- <reference ref="945678886"/>
- <reference ref="512868991"/>
- <reference ref="163117631"/>
- <reference ref="31516759"/>
- <reference ref="908105787"/>
- <reference ref="644046920"/>
- <reference ref="231811626"/>
- <reference ref="883618387"/>
- </array>
- <reference key="parent" ref="215659978"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">498</int>
- <reference key="object" ref="875092757"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">499</int>
- <reference key="object" ref="630155264"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">500</int>
- <reference key="object" ref="945678886"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">501</int>
- <reference key="object" ref="512868991"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">502</int>
- <reference key="object" ref="163117631"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">503</int>
- <reference key="object" ref="31516759"/>
- <array class="NSMutableArray" key="children">
- <reference ref="956096989"/>
- </array>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">504</int>
- <reference key="object" ref="908105787"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">505</int>
- <reference key="object" ref="644046920"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">506</int>
- <reference key="object" ref="231811626"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">507</int>
- <reference key="object" ref="883618387"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">508</int>
- <reference key="object" ref="956096989"/>
- <array class="NSMutableArray" key="children">
- <reference ref="257099033"/>
- <reference ref="551969625"/>
- <reference ref="249532473"/>
- <reference ref="607364498"/>
- <reference ref="508151438"/>
- <reference ref="981751889"/>
- <reference ref="380031999"/>
- <reference ref="825984362"/>
- <reference ref="560145579"/>
- </array>
- <reference key="parent" ref="31516759"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">509</int>
- <reference key="object" ref="257099033"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">510</int>
- <reference key="object" ref="551969625"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">511</int>
- <reference key="object" ref="249532473"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">512</int>
- <reference key="object" ref="607364498"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">513</int>
- <reference key="object" ref="508151438"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">514</int>
- <reference key="object" ref="981751889"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">515</int>
- <reference key="object" ref="380031999"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">516</int>
- <reference key="object" ref="825984362"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">517</int>
- <reference key="object" ref="560145579"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">534</int>
- <reference key="object" ref="738670835"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">546</int>
- <reference key="object" ref="976324537"/>
- <reference key="parent" ref="0"/>
- </object>
- </array>
- </object>
- <dictionary class="NSMutableDictionary" key="flattenedProperties">
- <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="112.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="124.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="125.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="126.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="129.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="130.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="131.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="134.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="136.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="143.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="144.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="145.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="149.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="150.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="19.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="195.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="196.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="197.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="198.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="199.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="200.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="201.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="202.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="203.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="204.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="205.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="206.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="207.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="208.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="209.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="210.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="211.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="212.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="213.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="214.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="215.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="216.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="217.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="218.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="219.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="220.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="221.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="236.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="239.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="24.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="29.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="295.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="296.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="297.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="298.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="346.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="348.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="349.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="350.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="351.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="354.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="375.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="376.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="377.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="388.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="389.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="390.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="391.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="392.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="393.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="394.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="395.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="396.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="397.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="398.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="399.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="400.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="401.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="402.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="403.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="404.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="405.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="406.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="407.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="408.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="409.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="410.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="411.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="412.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="413.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="414.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="415.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="416.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="417.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="418.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="419.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="450.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="451.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="452.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="453.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="454.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="457.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="459.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="460.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="462.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="465.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="466.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="485.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="490.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="491.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="492.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="496.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="497.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="498.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="499.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="500.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="501.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="502.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="503.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="504.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="505.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="506.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="507.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="508.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="509.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="510.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="511.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="512.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="513.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="514.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="515.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="516.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="517.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="534.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="546.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="56.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="57.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="58.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="72.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="73.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="74.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="75.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="77.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="78.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="79.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="81.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="82.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="83.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="92.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
- </dictionary>
- <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
- <nil key="activeLocalization"/>
- <dictionary class="NSMutableDictionary" key="localizations"/>
- <nil key="sourceID"/>
- <int key="maxID">547</int>
- </object>
- <object class="IBClassDescriber" key="IBDocument.Classes">
- <array class="NSMutableArray" key="referencedPartialClassDescriptions">
- <object class="IBPartialClassDescription">
- <string key="className">AppDelegate</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBProjectSource</string>
- <string key="minorKey">../MacGap/AppDelegate.h</string>
- </object>
- </object>
- </array>
- <array class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <string key="superclassName">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSBrowser</string>
- <string key="superclassName">NSControl</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSControl</string>
- <string key="superclassName">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSDocument</string>
- <string key="superclassName">NSObject</string>
- <dictionary class="NSMutableDictionary" key="actions">
- <string key="printDocument:">id</string>
- <string key="revertDocumentToSaved:">id</string>
- <string key="runPageLayout:">id</string>
- <string key="saveDocument:">id</string>
- <string key="saveDocumentAs:">id</string>
- <string key="saveDocumentTo:">id</string>
- </dictionary>
- <dictionary class="NSMutableDictionary" key="actionInfosByName">
- <object class="IBActionInfo" key="printDocument:">
- <string key="name">printDocument:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="revertDocumentToSaved:">
- <string key="name">revertDocumentToSaved:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="runPageLayout:">
- <string key="name">runPageLayout:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="saveDocument:">
- <string key="name">saveDocument:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="saveDocumentAs:">
- <string key="name">saveDocumentAs:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="saveDocumentTo:">
- <string key="name">saveDocumentTo:</string>
- <string key="candidateClassName">id</string>
- </object>
- </dictionary>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSDocumentController</string>
- <string key="superclassName">NSObject</string>
- <dictionary class="NSMutableDictionary" key="actions">
- <string key="clearRecentDocuments:">id</string>
- <string key="newDocument:">id</string>
- <string key="openDocument:">id</string>
- <string key="saveAllDocuments:">id</string>
- </dictionary>
- <dictionary class="NSMutableDictionary" key="actionInfosByName">
- <object class="IBActionInfo" key="clearRecentDocuments:">
- <string key="name">clearRecentDocuments:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="newDocument:">
- <string key="name">newDocument:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="openDocument:">
- <string key="name">openDocument:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="saveAllDocuments:">
- <string key="name">saveAllDocuments:</string>
- <string key="candidateClassName">id</string>
- </object>
- </dictionary>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSFormatter</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMatrix</string>
- <string key="superclassName">NSControl</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMenu</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMenuItem</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMovieView</string>
- <string key="superclassName">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSPopover</string>
- <string key="superclassName">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSPopover.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSResponder</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSTableView</string>
- <string key="superclassName">NSControl</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSText</string>
- <string key="superclassName">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSText.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSTextView</string>
- <string key="superclassName">NSText</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSTextView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSView</string>
- <string key="superclassName">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSViewController</string>
- <string key="superclassName">NSResponder</string>
- <object class="NSMutableDictionary" key="outlets">
- <string key="NS.key.0">view</string>
- <string key="NS.object.0">NSView</string>
- </object>
- <object class="NSMutableDictionary" key="toOneOutletInfosByName">
- <string key="NS.key.0">view</string>
- <object class="IBToOneOutletInfo" key="NS.object.0">
- <string key="name">view</string>
- <string key="candidateClassName">NSView</string>
- </object>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSViewController.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSWindow</string>
- <string key="superclassName">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">WebView</string>
- <string key="superclassName">NSView</string>
- <dictionary class="NSMutableDictionary" key="actions">
- <string key="goBack:">id</string>
- <string key="goForward:">id</string>
- <string key="makeTextLarger:">id</string>
- <string key="makeTextSmaller:">id</string>
- <string key="makeTextStandardSize:">id</string>
- <string key="reload:">id</string>
- <string key="reloadFromOrigin:">id</string>
- <string key="stopLoading:">id</string>
- <string key="takeStringURLFrom:">id</string>
- <string key="toggleContinuousSpellChecking:">id</string>
- <string key="toggleSmartInsertDelete:">id</string>
- </dictionary>
- <dictionary class="NSMutableDictionary" key="actionInfosByName">
- <object class="IBActionInfo" key="goBack:">
- <string key="name">goBack:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="goForward:">
- <string key="name">goForward:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="makeTextLarger:">
- <string key="name">makeTextLarger:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="makeTextSmaller:">
- <string key="name">makeTextSmaller:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="makeTextStandardSize:">
- <string key="name">makeTextStandardSize:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="reload:">
- <string key="name">reload:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="reloadFromOrigin:">
- <string key="name">reloadFromOrigin:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="stopLoading:">
- <string key="name">stopLoading:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="takeStringURLFrom:">
- <string key="name">takeStringURLFrom:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="toggleContinuousSpellChecking:">
- <string key="name">toggleContinuousSpellChecking:</string>
- <string key="candidateClassName">id</string>
- </object>
- <object class="IBActionInfo" key="toggleSmartInsertDelete:">
- <string key="name">toggleSmartInsertDelete:</string>
- <string key="candidateClassName">id</string>
- </object>
- </dictionary>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">WebKit.framework/Headers/WebView.h</string>
- </object>
- </object>
- </array>
- </object>
- <int key="IBDocument.localizationMode">0</int>
- <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
- <bool key="IBDocument.previouslyAttemptedUpgradeToXcode5">NO</bool>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
- <integer value="4600" key="NS.object.0"/>
- </object>
- <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
- <int key="IBDocument.defaultPropertyAccessControl">3</int>
- <dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
- <string key="NSMenuCheckmark">{12, 12}</string>
- <string key="NSMenuMixedState">{10, 2}</string>
- </dictionary>
- </data>
-</archive>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib
deleted file mode 100644
index fa70acaa..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/Window.xib
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
- <dependencies>
- <deployment identifier="macosx"/>
- <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9060"/>
- <plugIn identifier="com.apple.WebKitIBPlugin" version="9060"/>
- </dependencies>
- <objects>
- <customObject id="-2" userLabel="File's Owner" customClass="WindowController">
- <connections>
- <outlet property="contentView" destination="2" id="23"/>
- <outlet property="window" destination="1" id="25"/>
- </connections>
- </customObject>
- <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
- <customObject id="-3" userLabel="Application" customClass="NSObject"/>
- <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" animationBehavior="default" id="1">
- <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
- <rect key="contentRect" x="575" y="564" width="500" height="500"/>
- <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/>
- <view key="contentView" id="2" customClass="ContentView">
- <rect key="frame" x="0.0" y="0.0" width="500" height="500"/>
- <autoresizingMask key="autoresizingMask"/>
- <subviews>
- <webView id="5">
- <rect key="frame" x="0.0" y="0.0" width="500" height="500"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <animations/>
- <webPreferences key="preferences" defaultFontSize="12" defaultFixedFontSize="12">
- <nil key="identifier"/>
- </webPreferences>
- </webView>
- </subviews>
- <animations/>
- <connections>
- <outlet property="webView" destination="5" id="19"/>
- </connections>
- </view>
- <connections>
- <binding destination="-2" name="title" keyPath="contentView.webView.mainFrameTitle" id="31"/>
- </connections>
- </window>
- </objects>
-</document>
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/main.m b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/main.m
deleted file mode 100644
index 4ad50ad5..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/MacGap/main.m
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// main.m
-// MacGap
-//
-// Created by Alex MacCaw on 08/01/2012.
-// Copyright (c) 2012 Twitter. All rights reserved.
-//
-
-#import <Cocoa/Cocoa.h>
-
-int main(int argc, char *argv[])
-{
- return NSApplicationMain(argc, (const char **)argv);
-}
diff --git a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/README.md b/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/README.md
deleted file mode 100644
index daf3eae9..00000000
--- a/ext/installfiles/mac/mac-ui-macgap1-wrapper/src/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Mac Web UI Wrapper
-======
-
-This is a modified version of MacGap1 which launches a WebKit view and accesses the local ZeroTier service at its web URL. It builds the URL from the authtoken.secret file in the system home (or the user home) and the zerotier-one.port file that ZeroTier creates to advertise its control port.
-
-It's based on the original MacGap1 source by Twitter, Inc. which is licensed under the MIT license.
diff --git a/ext/installfiles/mac/postinst.sh b/ext/installfiles/mac/postinst.sh
index da15f9c8..b4ea2ee2 100755
--- a/ext/installfiles/mac/postinst.sh
+++ b/ext/installfiles/mac/postinst.sh
@@ -5,7 +5,7 @@ export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin
OSX_RELEASE=`sw_vers -productVersion | cut -d . -f 1,2`
launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1
-sleep 1
+sleep 0.5
cd "/Library/Application Support/ZeroTier/One"
@@ -22,25 +22,40 @@ if [ "$OSX_RELEASE" = "10.7" ]; then
rm -f tap.kext.10_7.tar.gz
fi
-rm -rf node.log node.log.old root-topology shutdownIfUnreadable autoupdate.log updates.d
+rm -rf node.log node.log.old root-topology shutdownIfUnreadable autoupdate.log updates.d ui peers.save
+
chown -R 0 tap.kext
chgrp -R 0 tap.kext
+
if [ ! -f authtoken.secret ]; then
- head -c 4096 /dev/urandom | md5 | head -c 24 >authtoken.secret
+ head -c 1024 /dev/urandom | md5 | head -c 24 >authtoken.secret
chown 0 authtoken.secret
chgrp 0 authtoken.secret
chmod 0600 authtoken.secret
fi
+
rm -f zerotier-cli zerotier-idtool
ln -sf zerotier-one zerotier-cli
ln -sf zerotier-one zerotier-idtool
-
mkdir -p /usr/local/bin
cd /usr/local/bin
rm -f zerotier-cli zerotier-idtool
ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-cli
ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" zerotier-idtool
+cd "/Library/Application Support/ZeroTier/One"
+kextload -r . tap.kext >>/dev/null 2>&1 &
+disown %1
+
launchctl load /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1
+sleep 1
+
+if [ -f /tmp/zt1-gui-restart.tmp ]; then
+ for u in `cat /tmp/zt1-gui-restart.tmp`; do
+ su $u -c '/Applications/ZeroTier\ One.app/Contents/MacOS/ZeroTier\ One &' >>/dev/null 2>&1 &
+ done
+fi
+rm -f /tmp/zt1-gui-restart.tmp
+
exit 0
diff --git a/ext/installfiles/mac/preinst.sh b/ext/installfiles/mac/preinst.sh
index c2cb494b..af2a9320 100755
--- a/ext/installfiles/mac/preinst.sh
+++ b/ext/installfiles/mac/preinst.sh
@@ -2,6 +2,19 @@
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
+rm -f /tmp/zt1-gui-restart.tmp
+for i in `ps axuwww | tr -s ' ' ',' | grep -F '/Applications/ZeroTier,One.app' | grep -F -v grep | cut -d , -f 1,2 | xargs`; do
+ u=`echo $i | cut -d , -f 1`
+ p=`echo $i | cut -d , -f 2`
+ if [ ! -z "$u" -a "0$p" -gt 0 ]; then
+ kill $p >>/dev/null 2>&1
+ sleep 0.2
+ kill -9 $p >>/dev/null 2>&1
+ echo "$u" >>/tmp/zt1-gui-restart.tmp
+ fi
+done
+chmod 0600 /tmp/zt1-gui-restart.tmp
+
if [ -f /Library/LaunchDaemons/com.zerotier.one.plist ]; then
launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist >>/dev/null 2>&1
fi
diff --git a/ext/installfiles/mac/ui/Makefile b/ext/installfiles/mac/ui/Makefile
deleted file mode 100644
index 4be03228..00000000
--- a/ext/installfiles/mac/ui/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-all:
- mkdir -p build
- jsx --target es3 -x jsx . ./build
- rm -f ztui.min.js
- minify build/*.js >>ztui.min.js
- rm -rf build
diff --git a/ext/installfiles/mac/ui/README.md b/ext/installfiles/mac/ui/README.md
deleted file mode 100644
index bd5eddb6..00000000
--- a/ext/installfiles/mac/ui/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-ZeroTier HTML5 UI
-======
-
-This is the new (as of 1.0.3) ZeroTier One UI. It's implemented in HTML5 and React.
-
-If you make changes to the .jsx files, type 'make'. You will need NodeJS, react-tools, and minify installed and available in your path.
-
-For this to work, these files must be installed in the 'ui' subfolder of the ZeroTier home path. For development it's nice to symlink this to the 'ui' folder in your working directory. If the 'ui' subfolder is not present, the UI static files will not be served by the embedded web server.
-
-Packaging for Mac and Windows is accomplished by way of the wrappers in ext/. For Mac this is done with a modified version of MacGap. Windows uses a custom project that embeds a web view.
diff --git a/ext/installfiles/mac/ui/ZeroTierNetwork.jsx b/ext/installfiles/mac/ui/ZeroTierNetwork.jsx
deleted file mode 100644
index f842d758..00000000
--- a/ext/installfiles/mac/ui/ZeroTierNetwork.jsx
+++ /dev/null
@@ -1,74 +0,0 @@
-var ZeroTierNetwork = React.createClass({
- getInitialState: function() {
- return {};
- },
-
- leaveNetwork: function(event) {
- Ajax.call({
- url: 'network/'+this.props.nwid+'?auth='+this.props.authToken,
- cache: false,
- type: 'DELETE',
- success: function(data) {
- if (this.props.onNetworkDeleted)
- this.props.onNetworkDeleted(this.props.nwid);
- }.bind(this),
- error: function(error) {
- }.bind(this)
- });
- event.preventDefault();
- },
-
- render: function() {
- return (
- <div className="zeroTierNetwork">
- <div className="networkInfo">
- <span className="networkId">{this.props.nwid}</span>&nbsp;
- <span className="networkName">{this.props.name}</span>
- </div>
- <div className="networkProps">
- <div className="row">
- <div className="name">Status</div>
- <div className="value">{this.props['status']}</div>
- </div>
- <div className="row">
- <div className="name">Type</div>
- <div className="value">{this.props['type']}</div>
- </div>
- <div className="row">
- <div className="name">MAC</div>
- <div className="value zeroTierAddress">{this.props['mac']}</div>
- </div>
- <div className="row">
- <div className="name">MTU</div>
- <div className="value">{this.props['mtu']}</div>
- </div>
- <div className="row">
- <div className="name">Broadcast</div>
- <div className="value">{(this.props['broadcastEnabled']) ? 'ENABLED' : 'DISABLED'}</div>
- </div>
- <div className="row">
- <div className="name">Bridging</div>
- <div className="value">{(this.props['bridge']) ? 'ACTIVE' : 'DISABLED'}</div>
- </div>
- <div className="row">
- <div className="name">Device</div>
- <div className="value">{(this.props['portDeviceName']) ? this.props['portDeviceName'] : '(none)'}</div>
- </div>
- <div className="row">
- <div className="name">Managed&nbsp;IPs</div>
- <div className="value ipList">
- {
- this.props['assignedAddresses'].map(function(ipAssignment) {
- return (
- <div key={ipAssignment} className="ipAddress">{ipAssignment}</div>
- );
- })
- }
- </div>
- </div>
- </div>
- <button type="button" className="leaveNetworkButton" onClick={this.leaveNetwork}>Leave&nbsp;Network</button>
- </div>
- );
- }
-});
diff --git a/ext/installfiles/mac/ui/ZeroTierNode.jsx b/ext/installfiles/mac/ui/ZeroTierNode.jsx
deleted file mode 100644
index b4c29220..00000000
--- a/ext/installfiles/mac/ui/ZeroTierNode.jsx
+++ /dev/null
@@ -1,158 +0,0 @@
-var ZeroTierNode = React.createClass({
- getInitialState: function() {
- return {
- address: '----------',
- online: false,
- version: '_._._',
- _networks: [],
- _peers: []
- };
- },
-
- ago: function(ms) {
- if (ms > 0) {
- var tmp = Math.round((Date.now() - ms) / 1000);
- return ((tmp > 0) ? tmp : 0);
- } else return 0;
- },
-
- updatePeers: function() {
- Ajax.call({
- url: 'peer?auth='+this.props.authToken,
- cache: false,
- type: 'GET',
- success: function(data) {
- if (data) {
- var pl = JSON.parse(data);
- if (Array.isArray(pl)) {
- this.setState({_peers: pl});
- }
- }
- }.bind(this),
- error: function() {
- }.bind(this)
- });
- },
- updateNetworks: function() {
- Ajax.call({
- url: 'network?auth='+this.props.authToken,
- cache: false,
- type: 'GET',
- success: function(data) {
- if (data) {
- var nwl = JSON.parse(data);
- if (Array.isArray(nwl)) {
- this.setState({_networks: nwl});
- }
- }
- }.bind(this),
- error: function() {
- }.bind(this)
- });
- },
- updateAll: function() {
- Ajax.call({
- url: 'status?auth='+this.props.authToken,
- cache: false,
- type: 'GET',
- success: function(data) {
- this.alertedToFailure = false;
- if (data) {
- var status = JSON.parse(data);
- this.setState(status);
- document.title = 'ZeroTier One [' + status.address + ']';
- }
- this.updateNetworks();
- this.updatePeers();
- }.bind(this),
- error: function() {
- this.setState(this.getInitialState());
- if (!this.alertedToFailure) {
- this.alertedToFailure = true;
- alert('Authorization token invalid or ZeroTier One service not running.');
- }
- }.bind(this)
- });
- },
- joinNetwork: function(event) {
- event.preventDefault();
- if ((this.networkToJoin)&&(this.networkToJoin.length === 16)) {
- Ajax.call({
- url: 'network/'+this.networkToJoin+'?auth='+this.props.authToken,
- cache: false,
- type: 'POST',
- success: function(data) {
- this.networkToJoin = '';
- if (this.networkInputElement)
- this.networkInputElement.value = '';
- this.updateNetworks();
- }.bind(this),
- error: function() {
- }.bind(this)
- });
- } else {
- alert('To join a network, enter its 16-digit network ID.');
- }
- },
- handleNetworkIdEntry: function(event) {
- this.networkInputElement = event.target;
- var nid = this.networkInputElement.value;
- if (nid) {
- nid = nid.toLowerCase();
- var nnid = '';
- for(var i=0;((i<nid.length)&&(i<16));++i) {
- if ("0123456789abcdef".indexOf(nid.charAt(i)) >= 0)
- nnid += nid.charAt(i);
- }
- this.networkToJoin = nnid;
- this.networkInputElement.value = nnid;
- } else {
- this.networkToJoin = '';
- this.networkInputElement.value = '';
- }
- },
-
- handleNetworkDelete: function(nwid) {
- var networks = [];
- for(var i=0;i<this.state._networks.length;++i) {
- if (this.state._networks[i].nwid !== nwid)
- networks.push(this.state._networks[i]);
- }
- this.setState({_networks: networks});
- },
-
- componentDidMount: function() {
- this.updateAll();
- this.updateIntervalId = setInterval(this.updateAll,2500);
- },
- componentWillUnmount: function() {
- clearInterval(this.updateIntervalId);
- },
- render: function() {
- return (
- <div className="zeroTierNode">
- <div className="middle"><div className="middleCell">
- <div className="middleScroll">
- <div className="networks" key="_networks">
- {
- this.state._networks.map(function(network) {
- network['authToken'] = this.props.authToken;
- network['onNetworkDeleted'] = this.handleNetworkDelete;
- return React.createElement('div',{className: 'network',key: network.nwid},React.createElement(ZeroTierNetwork,network));
- }.bind(this))
- }
- </div>
- </div>
- </div></div>
- <div className="bottom">
- <div className="left">
- <span className="statusLine"><span className="zeroTierAddress">{this.state.address}</span>&nbsp;&nbsp;{this.state.online ? (this.state.tcpFallbackActive ? 'TUNNELED' : 'ONLINE') : 'OFFLINE'}&nbsp;&nbsp;{this.state.version}</span>
- </div>
- <div className="right">
- <form onSubmit={this.joinNetwork}><input type="text" maxlength="16" placeholder="[ Network ID ]" onChange={this.handleNetworkIdEntry} size="16"/><button type="button" onClick={this.joinNetwork}>Join</button></form>
- </div>
- </div>
- </div>
- );
- }
-});
diff --git a/ext/installfiles/mac/ui/index.html b/ext/installfiles/mac/ui/index.html
deleted file mode 100644
index 44edb399..00000000
--- a/ext/installfiles/mac/ui/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>ZeroTier One</title>
- <link rel="stylesheet" href="zerotier.css">
- <script src="simpleajax.min.js"></script>
- <!-- <script src="https://fb.me/react-0.13.2.js"></script> -->
- <script src="react.min.js"></script>
- <script src="ztui.min.js"></script>
-</head>
-<body><div style="width: 100%; height: 100%;" id="main"></div></body>
-<script src="main.js"></script>
-<script>
-/* Windows hacks */
-function isIE() {
- var myNav = navigator.userAgent.toLowerCase();
- return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
-}
-var ieVersion = isIE();
-function resizeMiddleScrollClasses() {
- var elems = document.getElementsByTagName('*'), i;
- for (i in elems) {
- if ((' ' + elems[i].className + ' ').indexOf(' middleScroll ') > -1) {
- elems[i].style.height = (document.body.clientHeight - (elems[i].parentNode.parentNode.previousElementSibling.clientHeight + elems[i].parentNode.parentNode.nextElementSibling.clientHeight)) + "px";
- }
- }
-}
-if (ieVersion !== false) {
- if (ieVersion < 7) {
- alert("Upgrade Internet Explorer on your system to use this interface. (detected version: " + ieVersion + ")");
- } else {
- resizeMiddleScrollClasses();
- window.onresize = resizeMiddleScrollClasses;
- }
-}
-
-/* MacGap hacks */
-if (typeof macgap !== 'undefined') {
- if (macgap.menu) {
- var tmp = macgap.menu.getItem("Help");
- if (tmp)
- tmp.remove();
- tmp = macgap.menu.getItem("Format");
- if (tmp)
- tmp.remove();
- tmp = macgap.menu.getItem("View");
- if (tmp)
- tmp.remove();
- tmp = macgap.menu.getItem("File");
- if (tmp)
- tmp.remove();
- }
-}
-</script>
-</html>
diff --git a/ext/installfiles/mac/ui/main.js b/ext/installfiles/mac/ui/main.js
deleted file mode 100644
index a1647127..00000000
--- a/ext/installfiles/mac/ui/main.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2015 ZeroTier, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * ZeroTier may be used and distributed under the terms of the GPLv3, which
- * are available at: http://www.gnu.org/licenses/gpl-3.0.html
- *
- * If you would like to embed ZeroTier into a commercial application or
- * redistribute it in a modified binary form, please contact ZeroTier Networks
- * LLC. Start here: http://www.zerotier.com/
- */
-
-function getUrlParameter(parameter)
-{
- var currLocation = window.location.search;
- if (currLocation.indexOf('?') < 0)
- return '';
- var parArr = currLocation.split("?")[1].split("&");
- for(var i = 0; i < parArr.length; i++){
- parr = parArr[i].split("=");
- if (parr[0] == parameter) {
- return decodeURIComponent(parr[1]);
- }
- }
- return '';
-}
-
-var ztAuthToken = getUrlParameter('authToken');
-if ((!ztAuthToken)||(ztAuthToken.length <= 0)) {
- ztAuthToken = prompt('No authToken specified in URL. Enter token from\nauthtoken.secret to authorize.');
-}
-
-React.render(
- React.createElement(ZeroTierNode, {authToken: ztAuthToken}),
- document.getElementById('main')
-);
diff --git a/ext/installfiles/mac/ui/react.min.js b/ext/installfiles/mac/ui/react.min.js
deleted file mode 100644
index 9040c970..00000000
--- a/ext/installfiles/mac/ui/react.min.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * React v0.13.2
- *
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.React=e()}}(function(){return function e(t,n,r){function o(a,u){if(!n[a]){if(!t[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(i)return i(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){var n=t[a][1][e];return o(n?n:e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(e,t,n){"use strict";var r=e(19),o=e(32),i=e(34),a=e(33),u=e(38),s=e(39),l=e(55),c=(e(56),e(40)),p=e(51),d=e(54),f=e(64),h=e(68),m=e(73),v=e(76),g=e(79),y=e(82),C=e(27),E=e(115),b=e(142);d.inject();var _=l.createElement,x=l.createFactory,D=l.cloneElement,M=m.measure("React","render",h.render),N={Children:{map:o.map,forEach:o.forEach,count:o.count,only:b},Component:i,DOM:c,PropTypes:v,initializeTouchEvents:function(e){r.useTouchEvents=e},createClass:a.createClass,createElement:_,cloneElement:D,createFactory:x,createMixin:function(e){return e},constructAndRenderComponent:h.constructAndRenderComponent,constructAndRenderComponentByID:h.constructAndRenderComponentByID,findDOMNode:E,render:M,renderToString:y.renderToString,renderToStaticMarkup:y.renderToStaticMarkup,unmountComponentAtNode:h.unmountComponentAtNode,isValidElement:l.isValidElement,withContext:u.withContext,__spread:C};"undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject&&__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({CurrentOwner:s,InstanceHandles:f,Mount:h,Reconciler:g,TextComponent:p});N.version="0.13.2",t.exports=N},{115:115,142:142,19:19,27:27,32:32,33:33,34:34,38:38,39:39,40:40,51:51,54:54,55:55,56:56,64:64,68:68,73:73,76:76,79:79,82:82}],2:[function(e,t,n){"use strict";var r=e(117),o={componentDidMount:function(){this.props.autoFocus&&r(this.getDOMNode())}};t.exports=o},{117:117}],3:[function(e,t,n){"use strict";function r(){var e=window.opera;return"object"==typeof e&&"function"==typeof e.version&&parseInt(e.version(),10)<=12}function o(e){return(e.ctrlKey||e.altKey||e.metaKey)&&!(e.ctrlKey&&e.altKey)}function i(e){switch(e){case T.topCompositionStart:return R.compositionStart;case T.topCompositionEnd:return R.compositionEnd;case T.topCompositionUpdate:return R.compositionUpdate}}function a(e,t){return e===T.topKeyDown&&t.keyCode===b}function u(e,t){switch(e){case T.topKeyUp:return-1!==E.indexOf(t.keyCode);case T.topKeyDown:return t.keyCode!==b;case T.topKeyPress:case T.topMouseDown:case T.topBlur:return!0;default:return!1}}function s(e){var t=e.detail;return"object"==typeof t&&"data"in t?t.data:null}function l(e,t,n,r){var o,l;if(_?o=i(e):w?u(e,r)&&(o=R.compositionEnd):a(e,r)&&(o=R.compositionStart),!o)return null;M&&(w||o!==R.compositionStart?o===R.compositionEnd&&w&&(l=w.getData()):w=v.getPooled(t));var c=g.getPooled(o,n,r);if(l)c.data=l;else{var p=s(r);null!==p&&(c.data=p)}return h.accumulateTwoPhaseDispatches(c),c}function c(e,t){switch(e){case T.topCompositionEnd:return s(t);case T.topKeyPress:var n=t.which;return n!==N?null:(P=!0,I);case T.topTextInput:var r=t.data;return r===I&&P?null:r;default:return null}}function p(e,t){if(w){if(e===T.topCompositionEnd||u(e,t)){var n=w.getData();return v.release(w),w=null,n}return null}switch(e){case T.topPaste:return null;case T.topKeyPress:return t.which&&!o(t)?String.fromCharCode(t.which):null;case T.topCompositionEnd:return M?null:t.data;default:return null}}function d(e,t,n,r){var o;if(o=D?c(e,r):p(e,r),!o)return null;var i=y.getPooled(R.beforeInput,n,r);return i.data=o,h.accumulateTwoPhaseDispatches(i),i}var f=e(15),h=e(20),m=e(21),v=e(22),g=e(91),y=e(95),C=e(139),E=[9,13,27,32],b=229,_=m.canUseDOM&&"CompositionEvent"in window,x=null;m.canUseDOM&&"documentMode"in document&&(x=document.documentMode);var D=m.canUseDOM&&"TextEvent"in window&&!x&&!r(),M=m.canUseDOM&&(!_||x&&x>8&&11>=x),N=32,I=String.fromCharCode(N),T=f.topLevelTypes,R={beforeInput:{phasedRegistrationNames:{bubbled:C({onBeforeInput:null}),captured:C({onBeforeInputCapture:null})},dependencies:[T.topCompositionEnd,T.topKeyPress,T.topTextInput,T.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:C({onCompositionEnd:null}),captured:C({onCompositionEndCapture:null})},dependencies:[T.topBlur,T.topCompositionEnd,T.topKeyDown,T.topKeyPress,T.topKeyUp,T.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:C({onCompositionStart:null}),captured:C({onCompositionStartCapture:null})},dependencies:[T.topBlur,T.topCompositionStart,T.topKeyDown,T.topKeyPress,T.topKeyUp,T.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:C({onCompositionUpdate:null}),captured:C({onCompositionUpdateCapture:null})},dependencies:[T.topBlur,T.topCompositionUpdate,T.topKeyDown,T.topKeyPress,T.topKeyUp,T.topMouseDown]}},P=!1,w=null,O={eventTypes:R,extractEvents:function(e,t,n,r){return[l(e,t,n,r),d(e,t,n,r)]}};t.exports=O},{139:139,15:15,20:20,21:21,22:22,91:91,95:95}],4:[function(e,t,n){"use strict";function r(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}var o={boxFlex:!0,boxFlexGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0},i=["Webkit","ms","Moz","O"];Object.keys(o).forEach(function(e){i.forEach(function(t){o[r(t,e)]=o[e]})});var a={background:{backgroundImage:!0,backgroundPosition:!0,backgroundRepeat:!0,backgroundColor:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0}},u={isUnitlessNumber:o,shorthandPropertyExpansions:a};t.exports=u},{}],5:[function(e,t,n){"use strict";var r=e(4),o=e(21),i=(e(106),e(111)),a=e(131),u=e(141),s=(e(150),u(function(e){return a(e)})),l="cssFloat";o.canUseDOM&&void 0===document.documentElement.style.cssFloat&&(l="styleFloat");var c={createMarkupForStyles:function(e){var t="";for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];null!=r&&(t+=s(n)+":",t+=i(n,r)+";")}return t||null},setValueForStyles:function(e,t){var n=e.style;for(var o in t)if(t.hasOwnProperty(o)){var a=i(o,t[o]);if("float"===o&&(o=l),a)n[o]=a;else{var u=r.shorthandPropertyExpansions[o];if(u)for(var s in u)n[s]="";else n[o]=""}}}};t.exports=c},{106:106,111:111,131:131,141:141,150:150,21:21,4:4}],6:[function(e,t,n){"use strict";function r(){this._callbacks=null,this._contexts=null}var o=e(28),i=e(27),a=e(133);i(r.prototype,{enqueue:function(e,t){this._callbacks=this._callbacks||[],this._contexts=this._contexts||[],this._callbacks.push(e),this._contexts.push(t)},notifyAll:function(){var e=this._callbacks,t=this._contexts;if(e){a(e.length===t.length),this._callbacks=null,this._contexts=null;for(var n=0,r=e.length;r>n;n++)e[n].call(t[n]);e.length=0,t.length=0}},reset:function(){this._callbacks=null,this._contexts=null},destructor:function(){this.reset()}}),o.addPoolingTo(r),t.exports=r},{133:133,27:27,28:28}],7:[function(e,t,n){"use strict";function r(e){return"SELECT"===e.nodeName||"INPUT"===e.nodeName&&"file"===e.type}function o(e){var t=x.getPooled(T.change,P,e);E.accumulateTwoPhaseDispatches(t),_.batchedUpdates(i,t)}function i(e){C.enqueueEvents(e),C.processEventQueue()}function a(e,t){R=e,P=t,R.attachEvent("onchange",o)}function u(){R&&(R.detachEvent("onchange",o),R=null,P=null)}function s(e,t,n){return e===I.topChange?n:void 0}function l(e,t,n){e===I.topFocus?(u(),a(t,n)):e===I.topBlur&&u()}function c(e,t){R=e,P=t,w=e.value,O=Object.getOwnPropertyDescriptor(e.constructor.prototype,"value"),Object.defineProperty(R,"value",k),R.attachEvent("onpropertychange",d)}function p(){R&&(delete R.value,R.detachEvent("onpropertychange",d),R=null,P=null,w=null,O=null)}function d(e){if("value"===e.propertyName){var t=e.srcElement.value;t!==w&&(w=t,o(e))}}function f(e,t,n){return e===I.topInput?n:void 0}function h(e,t,n){e===I.topFocus?(p(),c(t,n)):e===I.topBlur&&p()}function m(e,t,n){return e!==I.topSelectionChange&&e!==I.topKeyUp&&e!==I.topKeyDown||!R||R.value===w?void 0:(w=R.value,P)}function v(e){return"INPUT"===e.nodeName&&("checkbox"===e.type||"radio"===e.type)}function g(e,t,n){return e===I.topClick?n:void 0}var y=e(15),C=e(17),E=e(20),b=e(21),_=e(85),x=e(93),D=e(134),M=e(136),N=e(139),I=y.topLevelTypes,T={change:{phasedRegistrationNames:{bubbled:N({onChange:null}),captured:N({onChangeCapture:null})},dependencies:[I.topBlur,I.topChange,I.topClick,I.topFocus,I.topInput,I.topKeyDown,I.topKeyUp,I.topSelectionChange]}},R=null,P=null,w=null,O=null,S=!1;b.canUseDOM&&(S=D("change")&&(!("documentMode"in document)||document.documentMode>8));var A=!1;b.canUseDOM&&(A=D("input")&&(!("documentMode"in document)||document.documentMode>9));var k={get:function(){return O.get.call(this)},set:function(e){w=""+e,O.set.call(this,e)}},L={eventTypes:T,extractEvents:function(e,t,n,o){var i,a;if(r(t)?S?i=s:a=l:M(t)?A?i=f:(i=m,a=h):v(t)&&(i=g),i){var u=i(e,t,n);if(u){var c=x.getPooled(T.change,u,o);return E.accumulateTwoPhaseDispatches(c),c}}a&&a(e,t,n)}};t.exports=L},{134:134,136:136,139:139,15:15,17:17,20:20,21:21,85:85,93:93}],8:[function(e,t,n){"use strict";var r=0,o={createReactRootIndex:function(){return r++}};t.exports=o},{}],9:[function(e,t,n){"use strict";function r(e,t,n){e.insertBefore(t,e.childNodes[n]||null)}var o=e(12),i=e(70),a=e(145),u=e(133),s={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,updateTextContent:a,processUpdates:function(e,t){for(var n,s=null,l=null,c=0;c<e.length;c++)if(n=e[c],n.type===i.MOVE_EXISTING||n.type===i.REMOVE_NODE){var p=n.fromIndex,d=n.parentNode.childNodes[p],f=n.parentID;u(d),s=s||{},s[f]=s[f]||[],s[f][p]=d,l=l||[],l.push(d)}var h=o.dangerouslyRenderMarkup(t);if(l)for(var m=0;m<l.length;m++)l[m].parentNode.removeChild(l[m]);for(var v=0;v<e.length;v++)switch(n=e[v],n.type){case i.INSERT_MARKUP:r(n.parentNode,h[n.markupIndex],n.toIndex);break;case i.MOVE_EXISTING:r(n.parentNode,s[n.parentID][n.fromIndex],n.toIndex);break;case i.TEXT_CONTENT:a(n.parentNode,n.textContent);break;case i.REMOVE_NODE:}}};t.exports=s},{12:12,133:133,145:145,70:70}],10:[function(e,t,n){"use strict";function r(e,t){return(e&t)===t}var o=e(133),i={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(e){var t=e.Properties||{},n=e.DOMAttributeNames||{},a=e.DOMPropertyNames||{},s=e.DOMMutationMethods||{};e.isCustomAttribute&&u._isCustomAttributeFunctions.push(e.isCustomAttribute);for(var l in t){o(!u.isStandardName.hasOwnProperty(l)),u.isStandardName[l]=!0;var c=l.toLowerCase();if(u.getPossibleStandardName[c]=l,n.hasOwnProperty(l)){var p=n[l];u.getPossibleStandardName[p]=l,u.getAttributeName[l]=p}else u.getAttributeName[l]=c;u.getPropertyName[l]=a.hasOwnProperty(l)?a[l]:l,s.hasOwnProperty(l)?u.getMutationMethod[l]=s[l]:u.getMutationMethod[l]=null;var d=t[l];u.mustUseAttribute[l]=r(d,i.MUST_USE_ATTRIBUTE),u.mustUseProperty[l]=r(d,i.MUST_USE_PROPERTY),u.hasSideEffects[l]=r(d,i.HAS_SIDE_EFFECTS),u.hasBooleanValue[l]=r(d,i.HAS_BOOLEAN_VALUE),u.hasNumericValue[l]=r(d,i.HAS_NUMERIC_VALUE),u.hasPositiveNumericValue[l]=r(d,i.HAS_POSITIVE_NUMERIC_VALUE),u.hasOverloadedBooleanValue[l]=r(d,i.HAS_OVERLOADED_BOOLEAN_VALUE),o(!u.mustUseAttribute[l]||!u.mustUseProperty[l]),o(u.mustUseProperty[l]||!u.hasSideEffects[l]),o(!!u.hasBooleanValue[l]+!!u.hasNumericValue[l]+!!u.hasOverloadedBooleanValue[l]<=1)}}},a={},u={ID_ATTRIBUTE_NAME:"data-reactid",isStandardName:{},getPossibleStandardName:{},getAttributeName:{},getPropertyName:{},getMutationMethod:{},mustUseAttribute:{},mustUseProperty:{},hasSideEffects:{},hasBooleanValue:{},hasNumericValue:{},hasPositiveNumericValue:{},hasOverloadedBooleanValue:{},_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t<u._isCustomAttributeFunctions.length;t++){var n=u._isCustomAttributeFunctions[t];if(n(e))return!0}return!1},getDefaultValueForProperty:function(e,t){var n,r=a[e];return r||(a[e]=r={}),t in r||(n=document.createElement(e),r[t]=n[t]),r[t]},injection:i};t.exports=u},{133:133}],11:[function(e,t,n){"use strict";function r(e,t){return null==t||o.hasBooleanValue[e]&&!t||o.hasNumericValue[e]&&isNaN(t)||o.hasPositiveNumericValue[e]&&1>t||o.hasOverloadedBooleanValue[e]&&t===!1}var o=e(10),i=e(143),a=(e(150),{createMarkupForID:function(e){return o.ID_ATTRIBUTE_NAME+"="+i(e)},createMarkupForProperty:function(e,t){if(o.isStandardName.hasOwnProperty(e)&&o.isStandardName[e]){if(r(e,t))return"";var n=o.getAttributeName[e];return o.hasBooleanValue[e]||o.hasOverloadedBooleanValue[e]&&t===!0?n:n+"="+i(t)}return o.isCustomAttribute(e)?null==t?"":e+"="+i(t):null},setValueForProperty:function(e,t,n){if(o.isStandardName.hasOwnProperty(t)&&o.isStandardName[t]){var i=o.getMutationMethod[t];if(i)i(e,n);else if(r(t,n))this.deleteValueForProperty(e,t);else if(o.mustUseAttribute[t])e.setAttribute(o.getAttributeName[t],""+n);else{var a=o.getPropertyName[t];o.hasSideEffects[t]&&""+e[a]==""+n||(e[a]=n)}}else o.isCustomAttribute(t)&&(null==n?e.removeAttribute(t):e.setAttribute(t,""+n))},deleteValueForProperty:function(e,t){if(o.isStandardName.hasOwnProperty(t)&&o.isStandardName[t]){var n=o.getMutationMethod[t];if(n)n(e,void 0);else if(o.mustUseAttribute[t])e.removeAttribute(o.getAttributeName[t]);else{var r=o.getPropertyName[t],i=o.getDefaultValueForProperty(e.nodeName,r);o.hasSideEffects[t]&&""+e[r]===i||(e[r]=i)}}else o.isCustomAttribute(t)&&e.removeAttribute(t)}});t.exports=a},{10:10,143:143,150:150}],12:[function(e,t,n){"use strict";function r(e){return e.substring(1,e.indexOf(" "))}var o=e(21),i=e(110),a=e(112),u=e(125),s=e(133),l=/^(<[^ \/>]+)/,c="data-danger-index",p={dangerouslyRenderMarkup:function(e){s(o.canUseDOM);for(var t,n={},p=0;p<e.length;p++)s(e[p]),t=r(e[p]),t=u(t)?t:"*",n[t]=n[t]||[],n[t][p]=e[p];var d=[],f=0;for(t in n)if(n.hasOwnProperty(t)){var h,m=n[t];for(h in m)if(m.hasOwnProperty(h)){var v=m[h];m[h]=v.replace(l,"$1 "+c+'="'+h+'" ')}for(var g=i(m.join(""),a),y=0;y<g.length;++y){var C=g[y];C.hasAttribute&&C.hasAttribute(c)&&(h=+C.getAttribute(c),C.removeAttribute(c),s(!d.hasOwnProperty(h)),d[h]=C,f+=1)}}return s(f===d.length),s(d.length===e.length),d},dangerouslyReplaceNodeWithMarkup:function(e,t){s(o.canUseDOM),s(t),s("html"!==e.tagName.toLowerCase());var n=i(t,a)[0];e.parentNode.replaceChild(n,e)}};t.exports=p},{110:110,112:112,125:125,133:133,21:21}],13:[function(e,t,n){"use strict";var r=e(139),o=[r({ResponderEventPlugin:null}),r({SimpleEventPlugin:null}),r({TapEventPlugin:null}),r({EnterLeaveEventPlugin:null}),r({ChangeEventPlugin:null}),r({SelectEventPlugin:null}),r({BeforeInputEventPlugin:null}),r({AnalyticsEventPlugin:null}),r({MobileSafariClickEventPlugin:null})];t.exports=o},{139:139}],14:[function(e,t,n){"use strict";var r=e(15),o=e(20),i=e(97),a=e(68),u=e(139),s=r.topLevelTypes,l=a.getFirstReactDOM,c={mouseEnter:{registrationName:u({onMouseEnter:null}),dependencies:[s.topMouseOut,s.topMouseOver]},mouseLeave:{registrationName:u({onMouseLeave:null}),dependencies:[s.topMouseOut,s.topMouseOver]}},p=[null,null],d={eventTypes:c,extractEvents:function(e,t,n,r){if(e===s.topMouseOver&&(r.relatedTarget||r.fromElement))return null;if(e!==s.topMouseOut&&e!==s.topMouseOver)return null;var u;if(t.window===t)u=t;else{var d=t.ownerDocument;u=d?d.defaultView||d.parentWindow:window}var f,h;if(e===s.topMouseOut?(f=t,h=l(r.relatedTarget||r.toElement)||u):(f=u,h=t),f===h)return null;var m=f?a.getID(f):"",v=h?a.getID(h):"",g=i.getPooled(c.mouseLeave,m,r);g.type="mouseleave",g.target=f,g.relatedTarget=h;var y=i.getPooled(c.mouseEnter,v,r);return y.type="mouseenter",y.target=h,y.relatedTarget=f,o.accumulateEnterLeaveDispatches(g,y,m,v),p[0]=g,p[1]=y,p}};t.exports=d},{139:139,15:15,20:20,68:68,97:97}],15:[function(e,t,n){"use strict";var r=e(138),o=r({bubbled:null,captured:null}),i=r({topBlur:null,topChange:null,topClick:null,topCompositionEnd:null,topCompositionStart:null,topCompositionUpdate:null,topContextMenu:null,topCopy:null,topCut:null,topDoubleClick:null,topDrag:null,topDragEnd:null,topDragEnter:null,topDragExit:null,topDragLeave:null,topDragOver:null,topDragStart:null,topDrop:null,topError:null,topFocus:null,topInput:null,topKeyDown:null,topKeyPress:null,topKeyUp:null,topLoad:null,topMouseDown:null,topMouseMove:null,topMouseOut:null,topMouseOver:null,topMouseUp:null,topPaste:null,topReset:null,topScroll:null,topSelectionChange:null,topSubmit:null,topTextInput:null,topTouchCancel:null,topTouchEnd:null,topTouchMove:null,topTouchStart:null,topWheel:null}),a={topLevelTypes:i,PropagationPhases:o};t.exports=a},{138:138}],16:[function(e,t,n){var r=e(112),o={listen:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!1),{remove:function(){e.removeEventListener(t,n,!1)}}):e.attachEvent?(e.attachEvent("on"+t,n),{remove:function(){e.detachEvent("on"+t,n)}}):void 0},capture:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!0),{remove:function(){e.removeEventListener(t,n,!0)}}):{remove:r}},registerDefault:function(){}};t.exports=o},{112:112}],17:[function(e,t,n){"use strict";var r=e(18),o=e(19),i=e(103),a=e(118),u=e(133),s={},l=null,c=function(e){if(e){var t=o.executeDispatch,n=r.getPluginModuleForEvent(e);n&&n.executeDispatch&&(t=n.executeDispatch),o.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e)}},p=null,d={injection:{injectMount:o.injection.injectMount,injectInstanceHandle:function(e){p=e},getInstanceHandle:function(){return p},injectEventPluginOrder:r.injectEventPluginOrder,injectEventPluginsByName:r.injectEventPluginsByName},eventNameDispatchConfigs:r.eventNameDispatchConfigs,registrationNameModules:r.registrationNameModules,putListener:function(e,t,n){u(!n||"function"==typeof n);var r=s[t]||(s[t]={});r[e]=n},getListener:function(e,t){var n=s[t];return n&&n[e]},deleteListener:function(e,t){var n=s[t];n&&delete n[e]},deleteAllListeners:function(e){for(var t in s)delete s[t][e]},extractEvents:function(e,t,n,o){for(var a,u=r.plugins,s=0,l=u.length;l>s;s++){var c=u[s];if(c){var p=c.extractEvents(e,t,n,o);p&&(a=i(a,p))}}return a},enqueueEvents:function(e){e&&(l=i(l,e))},processEventQueue:function(){var e=l;l=null,a(e,c),u(!l)},__purge:function(){s={}},__getListenerBank:function(){return s}};t.exports=d},{103:103,118:118,133:133,18:18,19:19}],18:[function(e,t,n){"use strict";function r(){if(u)for(var e in s){var t=s[e],n=u.indexOf(e);if(a(n>-1),!l.plugins[n]){a(t.extractEvents),l.plugins[n]=t;var r=t.eventTypes;for(var i in r)a(o(r[i],t,i))}}}function o(e,t,n){a(!l.eventNameDispatchConfigs.hasOwnProperty(n)),l.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var o in r)if(r.hasOwnProperty(o)){var u=r[o];i(u,t,n)}return!0}return e.registrationName?(i(e.registrationName,t,n),!0):!1}function i(e,t,n){a(!l.registrationNameModules[e]),l.registrationNameModules[e]=t,l.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var a=e(133),u=null,s={},l={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(e){a(!u),u=Array.prototype.slice.call(e),r()},injectEventPluginsByName:function(e){var t=!1;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];s.hasOwnProperty(n)&&s[n]===o||(a(!s[n]),s[n]=o,t=!0)}t&&r()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return l.registrationNameModules[t.registrationName]||null;for(var n in t.phasedRegistrationNames)if(t.phasedRegistrationNames.hasOwnProperty(n)){var r=l.registrationNameModules[t.phasedRegistrationNames[n]];if(r)return r}return null},_resetEventPlugins:function(){u=null;for(var e in s)s.hasOwnProperty(e)&&delete s[e];l.plugins.length=0;var t=l.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=l.registrationNameModules;for(var o in r)r.hasOwnProperty(o)&&delete r[o]}};t.exports=l},{133:133}],19:[function(e,t,n){"use strict";function r(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function o(e){return e===v.topMouseMove||e===v.topTouchMove}function i(e){return e===v.topMouseDown||e===v.topTouchStart}function a(e,t){var n=e._dispatchListeners,r=e._dispatchIDs;if(Array.isArray(n))for(var o=0;o<n.length&&!e.isPropagationStopped();o++)t(e,n[o],r[o]);else n&&t(e,n,r)}function u(e,t,n){e.currentTarget=m.Mount.getNode(n);var r=t(e,n);return e.currentTarget=null,r}function s(e,t){a(e,t),e._dispatchListeners=null,e._dispatchIDs=null}function l(e){var t=e._dispatchListeners,n=e._dispatchIDs;if(Array.isArray(t)){for(var r=0;r<t.length&&!e.isPropagationStopped();r++)if(t[r](e,n[r]))return n[r]}else if(t&&t(e,n))return n;return null}function c(e){var t=l(e);return e._dispatchIDs=null,e._dispatchListeners=null,t}function p(e){var t=e._dispatchListeners,n=e._dispatchIDs;h(!Array.isArray(t));var r=t?t(e,n):null;return e._dispatchListeners=null,e._dispatchIDs=null,r}function d(e){return!!e._dispatchListeners}var f=e(15),h=e(133),m={Mount:null,injectMount:function(e){m.Mount=e}},v=f.topLevelTypes,g={isEndish:r,isMoveish:o,isStartish:i,executeDirectDispatch:p,executeDispatch:u,executeDispatchesInOrder:s,executeDispatchesInOrderStopAtTrue:c,hasDispatches:d,injection:m,useTouchEvents:!1};t.exports=g},{133:133,15:15}],20:[function(e,t,n){"use strict";function r(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return v(e,r)}function o(e,t,n){var o=t?m.bubbled:m.captured,i=r(e,n,o);i&&(n._dispatchListeners=f(n._dispatchListeners,i),n._dispatchIDs=f(n._dispatchIDs,e))}function i(e){e&&e.dispatchConfig.phasedRegistrationNames&&d.injection.getInstanceHandle().traverseTwoPhase(e.dispatchMarker,o,e)}function a(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,o=v(e,r);o&&(n._dispatchListeners=f(n._dispatchListeners,o),n._dispatchIDs=f(n._dispatchIDs,e))}}function u(e){e&&e.dispatchConfig.registrationName&&a(e.dispatchMarker,null,e)}function s(e){h(e,i)}function l(e,t,n,r){d.injection.getInstanceHandle().traverseEnterLeave(n,r,a,e,t)}function c(e){h(e,u)}var p=e(15),d=e(17),f=e(103),h=e(118),m=p.PropagationPhases,v=d.getListener,g={accumulateTwoPhaseDispatches:s,accumulateDirectDispatches:c,accumulateEnterLeaveDispatches:l};t.exports=g},{103:103,118:118,15:15,17:17}],21:[function(e,t,n){"use strict";var r=!("undefined"==typeof window||!window.document||!window.document.createElement),o={canUseDOM:r,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:r&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:r&&!!window.screen,isInWorker:!r};t.exports=o},{}],22:[function(e,t,n){"use strict";function r(e){this._root=e,this._startText=this.getText(),this._fallbackText=null}var o=e(28),i=e(27),a=e(128);i(r.prototype,{getText:function(){return"value"in this._root?this._root.value:this._root[a()]},getData:function(){if(this._fallbackText)return this._fallbackText;var e,t,n=this._startText,r=n.length,o=this.getText(),i=o.length;for(e=0;r>e&&n[e]===o[e];e++);var a=r-e;for(t=1;a>=t&&n[r-t]===o[i-t];t++);var u=t>1?1-t:void 0;return this._fallbackText=o.slice(e,u),this._fallbackText}}),o.addPoolingTo(r),t.exports=r},{128:128,27:27,28:28}],23:[function(e,t,n){"use strict";var r,o=e(10),i=e(21),a=o.injection.MUST_USE_ATTRIBUTE,u=o.injection.MUST_USE_PROPERTY,s=o.injection.HAS_BOOLEAN_VALUE,l=o.injection.HAS_SIDE_EFFECTS,c=o.injection.HAS_NUMERIC_VALUE,p=o.injection.HAS_POSITIVE_NUMERIC_VALUE,d=o.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(i.canUseDOM){var f=document.implementation;r=f&&f.hasFeature&&f.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var h={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,acceptCharset:null,accessKey:null,action:null,allowFullScreen:a|s,allowTransparency:a,alt:null,async:s,autoComplete:null,autoPlay:s,cellPadding:null,cellSpacing:null,charSet:a,checked:u|s,classID:a,className:r?a:u,cols:a|p,colSpan:null,content:null,contentEditable:null,contextMenu:a,controls:u|s,coords:null,crossOrigin:null,data:null,dateTime:a,defer:s,dir:null,disabled:a|s,download:d,draggable:null,encType:null,form:a,formAction:a,formEncType:a,formMethod:a,formNoValidate:s,formTarget:a,frameBorder:a,headers:null,height:a,hidden:a|s,high:null,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:u,label:null,lang:null,list:a,loop:u|s,low:null,manifest:a,marginHeight:null,marginWidth:null,max:null,maxLength:a,media:a,mediaGroup:null,method:null,min:null,multiple:u|s,muted:u|s,name:null,noValidate:s,open:s,optimum:null,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:u|s,rel:null,required:s,role:a,rows:a|p,rowSpan:null,sandbox:null,scope:null,scoped:s,scrolling:null,seamless:a|s,selected:u|s,shape:null,size:a|p,sizes:a,span:p,spellCheck:null,src:null,srcDoc:u,srcSet:a,start:c,step:null,style:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:u|l,width:a,wmode:a,autoCapitalize:null,autoCorrect:null,itemProp:a,itemScope:a|s,itemType:a,itemID:a,itemRef:a,property:null,unselectable:a},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoCapitalize:"autocapitalize",autoComplete:"autocomplete",autoCorrect:"autocorrect",autoFocus:"autofocus",autoPlay:"autoplay",encType:"encoding",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};t.exports=h},{10:10,21:21}],24:[function(e,t,n){"use strict";function r(e){l(null==e.props.checkedLink||null==e.props.valueLink)}function o(e){r(e),l(null==e.props.value&&null==e.props.onChange)}function i(e){r(e),l(null==e.props.checked&&null==e.props.onChange)}function a(e){this.props.valueLink.requestChange(e.target.value)}function u(e){this.props.checkedLink.requestChange(e.target.checked)}var s=e(76),l=e(133),c={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0},p={Mixin:{propTypes:{value:function(e,t,n){return!e[t]||c[e.type]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,t,n){return!e[t]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:s.func}},getValue:function(e){return e.props.valueLink?(o(e),e.props.valueLink.value):e.props.value},getChecked:function(e){return e.props.checkedLink?(i(e),e.props.checkedLink.value):e.props.checked},getOnChange:function(e){return e.props.valueLink?(o(e),a):e.props.checkedLink?(i(e),u):e.props.onChange}};t.exports=p},{133:133,76:76}],25:[function(e,t,n){"use strict";function r(e){e.remove()}var o=e(30),i=e(103),a=e(118),u=e(133),s={trapBubbledEvent:function(e,t){u(this.isMounted());var n=this.getDOMNode();u(n);var r=o.trapBubbledEvent(e,t,n);this._localEventListeners=i(this._localEventListeners,r)},componentWillUnmount:function(){this._localEventListeners&&a(this._localEventListeners,r)}};t.exports=s},{103:103,118:118,133:133,30:30}],26:[function(e,t,n){"use strict";var r=e(15),o=e(112),i=r.topLevelTypes,a={eventTypes:null,extractEvents:function(e,t,n,r){if(e===i.topTouchStart){var a=r.target;a&&!a.onclick&&(a.onclick=o)}}};t.exports=a},{112:112,15:15}],27:[function(e,t,n){"use strict";function r(e,t){if(null==e)throw new TypeError("Object.assign target cannot be null or undefined");for(var n=Object(e),r=Object.prototype.hasOwnProperty,o=1;o<arguments.length;o++){var i=arguments[o];if(null!=i){var a=Object(i);for(var u in a)r.call(a,u)&&(n[u]=a[u])}}return n}t.exports=r},{}],28:[function(e,t,n){"use strict";var r=e(133),o=function(e){var t=this;if(t.instancePool.length){var n=t.instancePool.pop();return t.call(n,e),n}return new t(e)},i=function(e,t){var n=this;if(n.instancePool.length){var r=n.instancePool.pop();return n.call(r,e,t),r}return new n(e,t)},a=function(e,t,n){var r=this;if(r.instancePool.length){var o=r.instancePool.pop();return r.call(o,e,t,n),o}return new r(e,t,n)},u=function(e,t,n,r,o){var i=this;if(i.instancePool.length){var a=i.instancePool.pop();return i.call(a,e,t,n,r,o),a}return new i(e,t,n,r,o)},s=function(e){var t=this;r(e instanceof t),e.destructor&&e.destructor(),t.instancePool.length<t.poolSize&&t.instancePool.push(e)},l=10,c=o,p=function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||c,n.poolSize||(n.poolSize=l),n.release=s,n},d={addPoolingTo:p,oneArgumentPooler:o,twoArgumentPooler:i,threeArgumentPooler:a,fiveArgumentPooler:u};t.exports=d},{133:133}],29:[function(e,t,n){"use strict";var r=e(115),o={getDOMNode:function(){return r(this)}};t.exports=o},{115:115}],30:[function(e,t,n){"use strict";function r(e){return Object.prototype.hasOwnProperty.call(e,m)||(e[m]=f++,p[e[m]]={}),p[e[m]]}var o=e(15),i=e(17),a=e(18),u=e(59),s=e(102),l=e(27),c=e(134),p={},d=!1,f=0,h={topBlur:"blur",topChange:"change",topClick:"click",topCompositionEnd:"compositionend",topCompositionStart:"compositionstart",topCompositionUpdate:"compositionupdate",topContextMenu:"contextmenu",topCopy:"copy",topCut:"cut",topDoubleClick:"dblclick",topDrag:"drag",topDragEnd:"dragend",topDragEnter:"dragenter",topDragExit:"dragexit",topDragLeave:"dragleave",topDragOver:"dragover",topDragStart:"dragstart",topDrop:"drop",topFocus:"focus",topInput:"input",topKeyDown:"keydown",topKeyPress:"keypress",topKeyUp:"keyup",topMouseDown:"mousedown",topMouseMove:"mousemove",topMouseOut:"mouseout",topMouseOver:"mouseover",topMouseUp:"mouseup",topPaste:"paste",topScroll:"scroll",topSelectionChange:"selectionchange",topTextInput:"textInput",topTouchCancel:"touchcancel",topTouchEnd:"touchend",topTouchMove:"touchmove",topTouchStart:"touchstart",topWheel:"wheel"},m="_reactListenersID"+String(Math.random()).slice(2),v=l({},u,{ReactEventListener:null,injection:{injectReactEventListener:function(e){e.setHandleTopLevel(v.handleTopLevel),v.ReactEventListener=e}},setEnabled:function(e){v.ReactEventListener&&v.ReactEventListener.setEnabled(e)},isEnabled:function(){return!(!v.ReactEventListener||!v.ReactEventListener.isEnabled())},listenTo:function(e,t){for(var n=t,i=r(n),u=a.registrationNameDependencies[e],s=o.topLevelTypes,l=0,p=u.length;p>l;l++){var d=u[l];i.hasOwnProperty(d)&&i[d]||(d===s.topWheel?c("wheel")?v.ReactEventListener.trapBubbledEvent(s.topWheel,"wheel",n):c("mousewheel")?v.ReactEventListener.trapBubbledEvent(s.topWheel,"mousewheel",n):v.ReactEventListener.trapBubbledEvent(s.topWheel,"DOMMouseScroll",n):d===s.topScroll?c("scroll",!0)?v.ReactEventListener.trapCapturedEvent(s.topScroll,"scroll",n):v.ReactEventListener.trapBubbledEvent(s.topScroll,"scroll",v.ReactEventListener.WINDOW_HANDLE):d===s.topFocus||d===s.topBlur?(c("focus",!0)?(v.ReactEventListener.trapCapturedEvent(s.topFocus,"focus",n),v.ReactEventListener.trapCapturedEvent(s.topBlur,"blur",n)):c("focusin")&&(v.ReactEventListener.trapBubbledEvent(s.topFocus,"focusin",n),v.ReactEventListener.trapBubbledEvent(s.topBlur,"focusout",n)),i[s.topBlur]=!0,i[s.topFocus]=!0):h.hasOwnProperty(d)&&v.ReactEventListener.trapBubbledEvent(d,h[d],n),i[d]=!0)}},trapBubbledEvent:function(e,t,n){
-return v.ReactEventListener.trapBubbledEvent(e,t,n)},trapCapturedEvent:function(e,t,n){return v.ReactEventListener.trapCapturedEvent(e,t,n)},ensureScrollValueMonitoring:function(){if(!d){var e=s.refreshScrollValues;v.ReactEventListener.monitorScrollValue(e),d=!0}},eventNameDispatchConfigs:i.eventNameDispatchConfigs,registrationNameModules:i.registrationNameModules,putListener:i.putListener,getListener:i.getListener,deleteListener:i.deleteListener,deleteAllListeners:i.deleteAllListeners});t.exports=v},{102:102,134:134,15:15,17:17,18:18,27:27,59:59}],31:[function(e,t,n){"use strict";var r=e(79),o=e(116),i=e(132),a=e(147),u={instantiateChildren:function(e,t,n){var r=o(e);for(var a in r)if(r.hasOwnProperty(a)){var u=r[a],s=i(u,null);r[a]=s}return r},updateChildren:function(e,t,n,u){var s=o(t);if(!s&&!e)return null;var l;for(l in s)if(s.hasOwnProperty(l)){var c=e&&e[l],p=c&&c._currentElement,d=s[l];if(a(p,d))r.receiveComponent(c,d,n,u),s[l]=c;else{c&&r.unmountComponent(c,l);var f=i(d,null);s[l]=f}}for(l in e)!e.hasOwnProperty(l)||s&&s.hasOwnProperty(l)||r.unmountComponent(e[l]);return s},unmountChildren:function(e){for(var t in e){var n=e[t];r.unmountComponent(n)}}};t.exports=u},{116:116,132:132,147:147,79:79}],32:[function(e,t,n){"use strict";function r(e,t){this.forEachFunction=e,this.forEachContext=t}function o(e,t,n,r){var o=e;o.forEachFunction.call(o.forEachContext,t,r)}function i(e,t,n){if(null==e)return e;var i=r.getPooled(t,n);f(e,o,i),r.release(i)}function a(e,t,n){this.mapResult=e,this.mapFunction=t,this.mapContext=n}function u(e,t,n,r){var o=e,i=o.mapResult,a=!i.hasOwnProperty(n);if(a){var u=o.mapFunction.call(o.mapContext,t,r);i[n]=u}}function s(e,t,n){if(null==e)return e;var r={},o=a.getPooled(r,t,n);return f(e,u,o),a.release(o),d.create(r)}function l(e,t,n,r){return null}function c(e,t){return f(e,l,null)}var p=e(28),d=e(61),f=e(149),h=(e(150),p.twoArgumentPooler),m=p.threeArgumentPooler;p.addPoolingTo(r,h),p.addPoolingTo(a,m);var v={forEach:i,map:s,count:c};t.exports=v},{149:149,150:150,28:28,61:61}],33:[function(e,t,n){"use strict";function r(e,t){var n=D.hasOwnProperty(t)?D[t]:null;N.hasOwnProperty(t)&&y(n===_.OVERRIDE_BASE),e.hasOwnProperty(t)&&y(n===_.DEFINE_MANY||n===_.DEFINE_MANY_MERGED)}function o(e,t){if(t){y("function"!=typeof t),y(!d.isValidElement(t));var n=e.prototype;t.hasOwnProperty(b)&&M.mixins(e,t.mixins);for(var o in t)if(t.hasOwnProperty(o)&&o!==b){var i=t[o];if(r(n,o),M.hasOwnProperty(o))M[o](e,i);else{var a=D.hasOwnProperty(o),l=n.hasOwnProperty(o),c=i&&i.__reactDontBind,p="function"==typeof i,f=p&&!a&&!l&&!c;if(f)n.__reactAutoBindMap||(n.__reactAutoBindMap={}),n.__reactAutoBindMap[o]=i,n[o]=i;else if(l){var h=D[o];y(a&&(h===_.DEFINE_MANY_MERGED||h===_.DEFINE_MANY)),h===_.DEFINE_MANY_MERGED?n[o]=u(n[o],i):h===_.DEFINE_MANY&&(n[o]=s(n[o],i))}else n[o]=i}}}}function i(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in M;y(!o);var i=n in e;y(!i),e[n]=r}}}function a(e,t){y(e&&t&&"object"==typeof e&&"object"==typeof t);for(var n in t)t.hasOwnProperty(n)&&(y(void 0===e[n]),e[n]=t[n]);return e}function u(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);if(null==n)return r;if(null==r)return n;var o={};return a(o,n),a(o,r),o}}function s(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}function l(e,t){var n=t.bind(e);return n}function c(e){for(var t in e.__reactAutoBindMap)if(e.__reactAutoBindMap.hasOwnProperty(t)){var n=e.__reactAutoBindMap[t];e[t]=l(e,f.guard(n,e.constructor.displayName+"."+t))}}var p=e(34),d=(e(39),e(55)),f=e(58),h=e(65),m=e(66),v=(e(75),e(74),e(84)),g=e(27),y=e(133),C=e(138),E=e(139),b=(e(150),E({mixins:null})),_=C({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),x=[],D={mixins:_.DEFINE_MANY,statics:_.DEFINE_MANY,propTypes:_.DEFINE_MANY,contextTypes:_.DEFINE_MANY,childContextTypes:_.DEFINE_MANY,getDefaultProps:_.DEFINE_MANY_MERGED,getInitialState:_.DEFINE_MANY_MERGED,getChildContext:_.DEFINE_MANY_MERGED,render:_.DEFINE_ONCE,componentWillMount:_.DEFINE_MANY,componentDidMount:_.DEFINE_MANY,componentWillReceiveProps:_.DEFINE_MANY,shouldComponentUpdate:_.DEFINE_ONCE,componentWillUpdate:_.DEFINE_MANY,componentDidUpdate:_.DEFINE_MANY,componentWillUnmount:_.DEFINE_MANY,updateComponent:_.OVERRIDE_BASE},M={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n<t.length;n++)o(e,t[n])},childContextTypes:function(e,t){e.childContextTypes=g({},e.childContextTypes,t)},contextTypes:function(e,t){e.contextTypes=g({},e.contextTypes,t)},getDefaultProps:function(e,t){e.getDefaultProps?e.getDefaultProps=u(e.getDefaultProps,t):e.getDefaultProps=t},propTypes:function(e,t){e.propTypes=g({},e.propTypes,t)},statics:function(e,t){i(e,t)}},N={replaceState:function(e,t){v.enqueueReplaceState(this,e),t&&v.enqueueCallback(this,t)},isMounted:function(){var e=h.get(this);return e&&e!==m.currentlyMountingInstance},setProps:function(e,t){v.enqueueSetProps(this,e),t&&v.enqueueCallback(this,t)},replaceProps:function(e,t){v.enqueueReplaceProps(this,e),t&&v.enqueueCallback(this,t)}},I=function(){};g(I.prototype,p.prototype,N);var T={createClass:function(e){var t=function(e,t){this.__reactAutoBindMap&&c(this),this.props=e,this.context=t,this.state=null;var n=this.getInitialState?this.getInitialState():null;y("object"==typeof n&&!Array.isArray(n)),this.state=n};t.prototype=new I,t.prototype.constructor=t,x.forEach(o.bind(null,t)),o(t,e),t.getDefaultProps&&(t.defaultProps=t.getDefaultProps()),y(t.prototype.render);for(var n in D)t.prototype[n]||(t.prototype[n]=null);return t.type=t,t},injection:{injectMixin:function(e){x.push(e)}}};t.exports=T},{133:133,138:138,139:139,150:150,27:27,34:34,39:39,55:55,58:58,65:65,66:66,74:74,75:75,84:84}],34:[function(e,t,n){"use strict";function r(e,t){this.props=e,this.context=t}{var o=e(84),i=e(133);e(150)}r.prototype.setState=function(e,t){i("object"==typeof e||"function"==typeof e||null==e),o.enqueueSetState(this,e),t&&o.enqueueCallback(this,t)},r.prototype.forceUpdate=function(e){o.enqueueForceUpdate(this),e&&o.enqueueCallback(this,e)};t.exports=r},{133:133,150:150,84:84}],35:[function(e,t,n){"use strict";var r=e(44),o=e(68),i={processChildrenUpdates:r.dangerouslyProcessChildrenUpdates,replaceNodeWithMarkupByID:r.dangerouslyReplaceNodeWithMarkupByID,unmountIDFromEnvironment:function(e){o.purgeID(e)}};t.exports=i},{44:44,68:68}],36:[function(e,t,n){"use strict";var r=e(133),o=!1,i={unmountIDFromEnvironment:null,replaceNodeWithMarkupByID:null,processChildrenUpdates:null,injection:{injectEnvironment:function(e){r(!o),i.unmountIDFromEnvironment=e.unmountIDFromEnvironment,i.replaceNodeWithMarkupByID=e.replaceNodeWithMarkupByID,i.processChildrenUpdates=e.processChildrenUpdates,o=!0}}};t.exports=i},{133:133}],37:[function(e,t,n){"use strict";function r(e){var t=e._currentElement._owner||null;if(t){var n=t.getName();if(n)return" Check the render method of `"+n+"`."}return""}var o=e(36),i=e(38),a=e(39),u=e(55),s=(e(56),e(65)),l=e(66),c=e(71),p=e(73),d=e(75),f=(e(74),e(79)),h=e(85),m=e(27),v=e(113),g=e(133),y=e(147),C=(e(150),1),E={construct:function(e){this._currentElement=e,this._rootNodeID=null,this._instance=null,this._pendingElement=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._renderedComponent=null,this._context=null,this._mountOrder=0,this._isTopLevel=!1,this._pendingCallbacks=null},mountComponent:function(e,t,n){this._context=n,this._mountOrder=C++,this._rootNodeID=e;var r=this._processProps(this._currentElement.props),o=this._processContext(this._currentElement._context),i=c.getComponentClassForElement(this._currentElement),a=new i(r,o);a.props=r,a.context=o,a.refs=v,this._instance=a,s.set(a,this);var u=a.state;void 0===u&&(a.state=u=null),g("object"==typeof u&&!Array.isArray(u)),this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1;var p,d=l.currentlyMountingInstance;l.currentlyMountingInstance=this;try{a.componentWillMount&&(a.componentWillMount(),this._pendingStateQueue&&(a.state=this._processPendingState(a.props,a.context))),p=this._renderValidatedComponent()}finally{l.currentlyMountingInstance=d}this._renderedComponent=this._instantiateReactComponent(p,this._currentElement.type);var h=f.mountComponent(this._renderedComponent,e,t,this._processChildContext(n));return a.componentDidMount&&t.getReactMountReady().enqueue(a.componentDidMount,a),h},unmountComponent:function(){var e=this._instance;if(e.componentWillUnmount){var t=l.currentlyUnmountingInstance;l.currentlyUnmountingInstance=this;try{e.componentWillUnmount()}finally{l.currentlyUnmountingInstance=t}}f.unmountComponent(this._renderedComponent),this._renderedComponent=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._pendingCallbacks=null,this._pendingElement=null,this._context=null,this._rootNodeID=null,s.remove(e)},_setPropsInternal:function(e,t){var n=this._pendingElement||this._currentElement;this._pendingElement=u.cloneAndReplaceProps(n,m({},n.props,e)),h.enqueueUpdate(this,t)},_maskContext:function(e){var t=null;if("string"==typeof this._currentElement.type)return v;var n=this._currentElement.type.contextTypes;if(!n)return v;t={};for(var r in n)t[r]=e[r];return t},_processContext:function(e){var t=this._maskContext(e);return t},_processChildContext:function(e){var t=this._instance,n=t.getChildContext&&t.getChildContext();if(n){g("object"==typeof t.constructor.childContextTypes);for(var r in n)g(r in t.constructor.childContextTypes);return m({},e,n)}return e},_processProps:function(e){return e},_checkPropTypes:function(e,t,n){var o=this.getName();for(var i in e)if(e.hasOwnProperty(i)){var a;try{g("function"==typeof e[i]),a=e[i](t,i,o,n)}catch(u){a=u}a instanceof Error&&(r(this),n===d.prop)}},receiveComponent:function(e,t,n){var r=this._currentElement,o=this._context;this._pendingElement=null,this.updateComponent(t,r,e,o,n)},performUpdateIfNecessary:function(e){null!=this._pendingElement&&f.receiveComponent(this,this._pendingElement||this._currentElement,e,this._context),(null!==this._pendingStateQueue||this._pendingForceUpdate)&&this.updateComponent(e,this._currentElement,this._currentElement,this._context,this._context)},_warnIfContextsDiffer:function(e,t){e=this._maskContext(e),t=this._maskContext(t);for(var n=Object.keys(t).sort(),r=(this.getName()||"ReactCompositeComponent",0);r<n.length;r++)n[r]},updateComponent:function(e,t,n,r,o){var i=this._instance,a=i.context,u=i.props;t!==n&&(a=this._processContext(n._context),u=this._processProps(n.props),i.componentWillReceiveProps&&i.componentWillReceiveProps(u,a));var s=this._processPendingState(u,a),l=this._pendingForceUpdate||!i.shouldComponentUpdate||i.shouldComponentUpdate(u,s,a);l?(this._pendingForceUpdate=!1,this._performComponentUpdate(n,u,s,a,e,o)):(this._currentElement=n,this._context=o,i.props=u,i.state=s,i.context=a)},_processPendingState:function(e,t){var n=this._instance,r=this._pendingStateQueue,o=this._pendingReplaceState;if(this._pendingReplaceState=!1,this._pendingStateQueue=null,!r)return n.state;for(var i=m({},o?r[0]:n.state),a=o?1:0;a<r.length;a++){var u=r[a];m(i,"function"==typeof u?u.call(n,i,e,t):u)}return i},_performComponentUpdate:function(e,t,n,r,o,i){var a=this._instance,u=a.props,s=a.state,l=a.context;a.componentWillUpdate&&a.componentWillUpdate(t,n,r),this._currentElement=e,this._context=i,a.props=t,a.state=n,a.context=r,this._updateRenderedComponent(o,i),a.componentDidUpdate&&o.getReactMountReady().enqueue(a.componentDidUpdate.bind(a,u,s,l),a)},_updateRenderedComponent:function(e,t){var n=this._renderedComponent,r=n._currentElement,o=this._renderValidatedComponent();if(y(r,o))f.receiveComponent(n,o,e,this._processChildContext(t));else{var i=this._rootNodeID,a=n._rootNodeID;f.unmountComponent(n),this._renderedComponent=this._instantiateReactComponent(o,this._currentElement.type);var u=f.mountComponent(this._renderedComponent,i,e,this._processChildContext(t));this._replaceNodeWithMarkupByID(a,u)}},_replaceNodeWithMarkupByID:function(e,t){o.replaceNodeWithMarkupByID(e,t)},_renderValidatedComponentWithoutOwnerOrContext:function(){var e=this._instance,t=e.render();return t},_renderValidatedComponent:function(){var e,t=i.current;i.current=this._processChildContext(this._currentElement._context),a.current=this;try{e=this._renderValidatedComponentWithoutOwnerOrContext()}finally{i.current=t,a.current=null}return g(null===e||e===!1||u.isValidElement(e)),e},attachRef:function(e,t){var n=this.getPublicInstance(),r=n.refs===v?n.refs={}:n.refs;r[e]=t.getPublicInstance()},detachRef:function(e){var t=this.getPublicInstance().refs;delete t[e]},getName:function(){var e=this._currentElement.type,t=this._instance&&this._instance.constructor;return e.displayName||t&&t.displayName||e.name||t&&t.name||null},getPublicInstance:function(){return this._instance},_instantiateReactComponent:null};p.measureMethods(E,"ReactCompositeComponent",{mountComponent:"mountComponent",updateComponent:"updateComponent",_renderValidatedComponent:"_renderValidatedComponent"});var b={Mixin:E};t.exports=b},{113:113,133:133,147:147,150:150,27:27,36:36,38:38,39:39,55:55,56:56,65:65,66:66,71:71,73:73,74:74,75:75,79:79,85:85}],38:[function(e,t,n){"use strict";var r=e(27),o=e(113),i=(e(150),{current:o,withContext:function(e,t){var n,o=i.current;i.current=r({},o,e);try{n=t()}finally{i.current=o}return n}});t.exports=i},{113:113,150:150,27:27}],39:[function(e,t,n){"use strict";var r={current:null};t.exports=r},{}],40:[function(e,t,n){"use strict";function r(e){return o.createFactory(e)}var o=e(55),i=(e(56),e(140)),a=i({a:"a",abbr:"abbr",address:"address",area:"area",article:"article",aside:"aside",audio:"audio",b:"b",base:"base",bdi:"bdi",bdo:"bdo",big:"big",blockquote:"blockquote",body:"body",br:"br",button:"button",canvas:"canvas",caption:"caption",cite:"cite",code:"code",col:"col",colgroup:"colgroup",data:"data",datalist:"datalist",dd:"dd",del:"del",details:"details",dfn:"dfn",dialog:"dialog",div:"div",dl:"dl",dt:"dt",em:"em",embed:"embed",fieldset:"fieldset",figcaption:"figcaption",figure:"figure",footer:"footer",form:"form",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",head:"head",header:"header",hr:"hr",html:"html",i:"i",iframe:"iframe",img:"img",input:"input",ins:"ins",kbd:"kbd",keygen:"keygen",label:"label",legend:"legend",li:"li",link:"link",main:"main",map:"map",mark:"mark",menu:"menu",menuitem:"menuitem",meta:"meta",meter:"meter",nav:"nav",noscript:"noscript",object:"object",ol:"ol",optgroup:"optgroup",option:"option",output:"output",p:"p",param:"param",picture:"picture",pre:"pre",progress:"progress",q:"q",rp:"rp",rt:"rt",ruby:"ruby",s:"s",samp:"samp",script:"script",section:"section",select:"select",small:"small",source:"source",span:"span",strong:"strong",style:"style",sub:"sub",summary:"summary",sup:"sup",table:"table",tbody:"tbody",td:"td",textarea:"textarea",tfoot:"tfoot",th:"th",thead:"thead",time:"time",title:"title",tr:"tr",track:"track",u:"u",ul:"ul","var":"var",video:"video",wbr:"wbr",circle:"circle",defs:"defs",ellipse:"ellipse",g:"g",line:"line",linearGradient:"linearGradient",mask:"mask",path:"path",pattern:"pattern",polygon:"polygon",polyline:"polyline",radialGradient:"radialGradient",rect:"rect",stop:"stop",svg:"svg",text:"text",tspan:"tspan"},r);t.exports=a},{140:140,55:55,56:56}],41:[function(e,t,n){"use strict";var r=e(2),o=e(29),i=e(33),a=e(55),u=e(138),s=a.createFactory("button"),l=u({onClick:!0,onDoubleClick:!0,onMouseDown:!0,onMouseMove:!0,onMouseUp:!0,onClickCapture:!0,onDoubleClickCapture:!0,onMouseDownCapture:!0,onMouseMoveCapture:!0,onMouseUpCapture:!0}),c=i.createClass({displayName:"ReactDOMButton",tagName:"BUTTON",mixins:[r,o],render:function(){var e={};for(var t in this.props)!this.props.hasOwnProperty(t)||this.props.disabled&&l[t]||(e[t]=this.props[t]);return s(e,this.props.children)}});t.exports=c},{138:138,2:2,29:29,33:33,55:55}],42:[function(e,t,n){"use strict";function r(e){e&&(null!=e.dangerouslySetInnerHTML&&(g(null==e.children),g(null!=e.dangerouslySetInnerHTML.__html)),g(null==e.style||"object"==typeof e.style))}function o(e,t,n,r){var o=d.findReactContainerForID(e);if(o){var i=o.nodeType===D?o.ownerDocument:o;E(t,i)}r.getPutListenerQueue().enqueuePutListener(e,t,n)}function i(e){R.call(T,e)||(g(I.test(e)),T[e]=!0)}function a(e){i(e),this._tag=e,this._renderedChildren=null,this._previousStyleCopy=null,this._rootNodeID=null}var u=e(5),s=e(10),l=e(11),c=e(30),p=e(35),d=e(68),f=e(69),h=e(73),m=e(27),v=e(114),g=e(133),y=(e(134),e(139)),C=(e(150),c.deleteListener),E=c.listenTo,b=c.registrationNameModules,_={string:!0,number:!0},x=y({style:null}),D=1,M=null,N={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},I=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,T={},R={}.hasOwnProperty;a.displayName="ReactDOMComponent",a.Mixin={construct:function(e){this._currentElement=e},mountComponent:function(e,t,n){this._rootNodeID=e,r(this._currentElement.props);var o=N[this._tag]?"":"</"+this._tag+">";return this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t,n)+o},_createOpenTagMarkupAndPutListeners:function(e){var t=this._currentElement.props,n="<"+this._tag;for(var r in t)if(t.hasOwnProperty(r)){var i=t[r];if(null!=i)if(b.hasOwnProperty(r))o(this._rootNodeID,r,i,e);else{r===x&&(i&&(i=this._previousStyleCopy=m({},t.style)),i=u.createMarkupForStyles(i));var a=l.createMarkupForProperty(r,i);a&&(n+=" "+a)}}if(e.renderToStaticMarkup)return n+">";var s=l.createMarkupForID(this._rootNodeID);return n+" "+s+">"},_createContentMarkup:function(e,t){var n="";("listing"===this._tag||"pre"===this._tag||"textarea"===this._tag)&&(n="\n");var r=this._currentElement.props,o=r.dangerouslySetInnerHTML;if(null!=o){if(null!=o.__html)return n+o.__html}else{var i=_[typeof r.children]?r.children:null,a=null!=i?null:r.children;if(null!=i)return n+v(i);if(null!=a){var u=this.mountChildren(a,e,t);return n+u.join("")}}return n},receiveComponent:function(e,t,n){var r=this._currentElement;this._currentElement=e,this.updateComponent(t,r,e,n)},updateComponent:function(e,t,n,o){r(this._currentElement.props),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e,o)},_updateDOMProperties:function(e,t){var n,r,i,a=this._currentElement.props;for(n in e)if(!a.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===x){var u=this._previousStyleCopy;for(r in u)u.hasOwnProperty(r)&&(i=i||{},i[r]="");this._previousStyleCopy=null}else b.hasOwnProperty(n)?C(this._rootNodeID,n):(s.isStandardName[n]||s.isCustomAttribute(n))&&M.deletePropertyByID(this._rootNodeID,n);for(n in a){var l=a[n],c=n===x?this._previousStyleCopy:e[n];if(a.hasOwnProperty(n)&&l!==c)if(n===x)if(l?l=this._previousStyleCopy=m({},l):this._previousStyleCopy=null,c){for(r in c)!c.hasOwnProperty(r)||l&&l.hasOwnProperty(r)||(i=i||{},i[r]="");for(r in l)l.hasOwnProperty(r)&&c[r]!==l[r]&&(i=i||{},i[r]=l[r])}else i=l;else b.hasOwnProperty(n)?o(this._rootNodeID,n,l,t):(s.isStandardName[n]||s.isCustomAttribute(n))&&M.updatePropertyByID(this._rootNodeID,n,l)}i&&M.updateStylesByID(this._rootNodeID,i)},_updateDOMChildren:function(e,t,n){var r=this._currentElement.props,o=_[typeof e.children]?e.children:null,i=_[typeof r.children]?r.children:null,a=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,u=r.dangerouslySetInnerHTML&&r.dangerouslySetInnerHTML.__html,s=null!=o?null:e.children,l=null!=i?null:r.children,c=null!=o||null!=a,p=null!=i||null!=u;null!=s&&null==l?this.updateChildren(null,t,n):c&&!p&&this.updateTextContent(""),null!=i?o!==i&&this.updateTextContent(""+i):null!=u?a!==u&&M.updateInnerHTMLByID(this._rootNodeID,u):null!=l&&this.updateChildren(l,t,n)},unmountComponent:function(){this.unmountChildren(),c.deleteAllListeners(this._rootNodeID),p.unmountIDFromEnvironment(this._rootNodeID),this._rootNodeID=null}},h.measureMethods(a,"ReactDOMComponent",{mountComponent:"mountComponent",updateComponent:"updateComponent"}),m(a.prototype,a.Mixin,f.Mixin),a.injection={injectIDOperations:function(e){a.BackendIDOperations=M=e}},t.exports=a},{10:10,11:11,114:114,133:133,134:134,139:139,150:150,27:27,30:30,35:35,5:5,68:68,69:69,73:73}],43:[function(e,t,n){"use strict";var r=e(15),o=e(25),i=e(29),a=e(33),u=e(55),s=u.createFactory("form"),l=a.createClass({displayName:"ReactDOMForm",tagName:"FORM",mixins:[i,o],render:function(){return s(this.props)},componentDidMount:function(){this.trapBubbledEvent(r.topLevelTypes.topReset,"reset"),this.trapBubbledEvent(r.topLevelTypes.topSubmit,"submit")}});t.exports=l},{15:15,25:25,29:29,33:33,55:55}],44:[function(e,t,n){"use strict";var r=e(5),o=e(9),i=e(11),a=e(68),u=e(73),s=e(133),l=e(144),c={dangerouslySetInnerHTML:"`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.",style:"`style` must be set using `updateStylesByID()`."},p={updatePropertyByID:function(e,t,n){var r=a.getNode(e);s(!c.hasOwnProperty(t)),null!=n?i.setValueForProperty(r,t,n):i.deleteValueForProperty(r,t)},deletePropertyByID:function(e,t,n){var r=a.getNode(e);s(!c.hasOwnProperty(t)),i.deleteValueForProperty(r,t,n)},updateStylesByID:function(e,t){var n=a.getNode(e);r.setValueForStyles(n,t)},updateInnerHTMLByID:function(e,t){var n=a.getNode(e);l(n,t)},updateTextContentByID:function(e,t){var n=a.getNode(e);o.updateTextContent(n,t)},dangerouslyReplaceNodeWithMarkupByID:function(e,t){var n=a.getNode(e);o.dangerouslyReplaceNodeWithMarkup(n,t)},dangerouslyProcessChildrenUpdates:function(e,t){for(var n=0;n<e.length;n++)e[n].parentNode=a.getNode(e[n].parentID);o.processUpdates(e,t)}};u.measureMethods(p,"ReactDOMIDOperations",{updatePropertyByID:"updatePropertyByID",deletePropertyByID:"deletePropertyByID",updateStylesByID:"updateStylesByID",updateInnerHTMLByID:"updateInnerHTMLByID",updateTextContentByID:"updateTextContentByID",dangerouslyReplaceNodeWithMarkupByID:"dangerouslyReplaceNodeWithMarkupByID",dangerouslyProcessChildrenUpdates:"dangerouslyProcessChildrenUpdates"}),t.exports=p},{11:11,133:133,144:144,5:5,68:68,73:73,9:9}],45:[function(e,t,n){"use strict";var r=e(15),o=e(25),i=e(29),a=e(33),u=e(55),s=u.createFactory("iframe"),l=a.createClass({displayName:"ReactDOMIframe",tagName:"IFRAME",mixins:[i,o],render:function(){return s(this.props)},componentDidMount:function(){this.trapBubbledEvent(r.topLevelTypes.topLoad,"load")}});t.exports=l},{15:15,25:25,29:29,33:33,55:55}],46:[function(e,t,n){"use strict";var r=e(15),o=e(25),i=e(29),a=e(33),u=e(55),s=u.createFactory("img"),l=a.createClass({displayName:"ReactDOMImg",tagName:"IMG",mixins:[i,o],render:function(){return s(this.props)},componentDidMount:function(){this.trapBubbledEvent(r.topLevelTypes.topLoad,"load"),this.trapBubbledEvent(r.topLevelTypes.topError,"error")}});t.exports=l},{15:15,25:25,29:29,33:33,55:55}],47:[function(e,t,n){"use strict";function r(){this.isMounted()&&this.forceUpdate()}var o=e(2),i=e(11),a=e(24),u=e(29),s=e(33),l=e(55),c=e(68),p=e(85),d=e(27),f=e(133),h=l.createFactory("input"),m={},v=s.createClass({displayName:"ReactDOMInput",tagName:"INPUT",mixins:[o,a.Mixin,u],getInitialState:function(){var e=this.props.defaultValue;return{initialChecked:this.props.defaultChecked||!1,initialValue:null!=e?e:null}},render:function(){var e=d({},this.props);e.defaultChecked=null,e.defaultValue=null;var t=a.getValue(this);e.value=null!=t?t:this.state.initialValue;var n=a.getChecked(this);return e.checked=null!=n?n:this.state.initialChecked,e.onChange=this._handleChange,h(e,this.props.children)},componentDidMount:function(){var e=c.getID(this.getDOMNode());m[e]=this},componentWillUnmount:function(){var e=this.getDOMNode(),t=c.getID(e);delete m[t]},componentDidUpdate:function(e,t,n){var r=this.getDOMNode();null!=this.props.checked&&i.setValueForProperty(r,"checked",this.props.checked||!1);var o=a.getValue(this);null!=o&&i.setValueForProperty(r,"value",""+o)},_handleChange:function(e){var t,n=a.getOnChange(this);n&&(t=n.call(this,e)),p.asap(r,this);var o=this.props.name;if("radio"===this.props.type&&null!=o){for(var i=this.getDOMNode(),u=i;u.parentNode;)u=u.parentNode;for(var s=u.querySelectorAll("input[name="+JSON.stringify(""+o)+'][type="radio"]'),l=0,d=s.length;d>l;l++){var h=s[l];if(h!==i&&h.form===i.form){var v=c.getID(h);f(v);var g=m[v];f(g),p.asap(r,g)}}}return t}});t.exports=v},{11:11,133:133,2:2,24:24,27:27,29:29,33:33,55:55,68:68,85:85}],48:[function(e,t,n){"use strict";var r=e(29),o=e(33),i=e(55),a=(e(150),i.createFactory("option")),u=o.createClass({displayName:"ReactDOMOption",tagName:"OPTION",mixins:[r],componentWillMount:function(){},render:function(){return a(this.props,this.props.children)}});t.exports=u},{150:150,29:29,33:33,55:55}],49:[function(e,t,n){"use strict";function r(){if(this._pendingUpdate){this._pendingUpdate=!1;var e=u.getValue(this);null!=e&&this.isMounted()&&i(this,e)}}function o(e,t,n){if(null==e[t])return null;if(e.multiple){if(!Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be an array if `multiple` is true.")}else if(Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be a scalar value if `multiple` is false.")}function i(e,t){var n,r,o,i=e.getDOMNode().options;if(e.props.multiple){for(n={},r=0,o=t.length;o>r;r++)n[""+t[r]]=!0;for(r=0,o=i.length;o>r;r++){var a=n.hasOwnProperty(i[r].value);i[r].selected!==a&&(i[r].selected=a)}}else{for(n=""+t,r=0,o=i.length;o>r;r++)if(i[r].value===n)return void(i[r].selected=!0);i.length&&(i[0].selected=!0)}}var a=e(2),u=e(24),s=e(29),l=e(33),c=e(55),p=e(85),d=e(27),f=c.createFactory("select"),h=l.createClass({displayName:"ReactDOMSelect",tagName:"SELECT",mixins:[a,u.Mixin,s],propTypes:{defaultValue:o,value:o},render:function(){var e=d({},this.props);return e.onChange=this._handleChange,e.value=null,f(e,this.props.children)},componentWillMount:function(){this._pendingUpdate=!1},componentDidMount:function(){var e=u.getValue(this);null!=e?i(this,e):null!=this.props.defaultValue&&i(this,this.props.defaultValue)},componentDidUpdate:function(e){var t=u.getValue(this);null!=t?(this._pendingUpdate=!1,i(this,t)):!e.multiple!=!this.props.multiple&&(null!=this.props.defaultValue?i(this,this.props.defaultValue):i(this,this.props.multiple?[]:""))},_handleChange:function(e){var t,n=u.getOnChange(this);return n&&(t=n.call(this,e)),this._pendingUpdate=!0,p.asap(r,this),t}});t.exports=h},{2:2,24:24,27:27,29:29,33:33,55:55,85:85}],50:[function(e,t,n){"use strict";function r(e,t,n,r){return e===n&&t===r}function o(e){var t=document.selection,n=t.createRange(),r=n.text.length,o=n.duplicate();o.moveToElementText(e),o.setEndPoint("EndToStart",n);var i=o.text.length,a=i+r;return{start:i,end:a}}function i(e){var t=window.getSelection&&window.getSelection();if(!t||0===t.rangeCount)return null;var n=t.anchorNode,o=t.anchorOffset,i=t.focusNode,a=t.focusOffset,u=t.getRangeAt(0),s=r(t.anchorNode,t.anchorOffset,t.focusNode,t.focusOffset),l=s?0:u.toString().length,c=u.cloneRange();c.selectNodeContents(e),c.setEnd(u.startContainer,u.startOffset);var p=r(c.startContainer,c.startOffset,c.endContainer,c.endOffset),d=p?0:c.toString().length,f=d+l,h=document.createRange();h.setStart(n,o),h.setEnd(i,a);var m=h.collapsed;return{start:m?f:d,end:m?d:f}}function a(e,t){var n,r,o=document.selection.createRange().duplicate();"undefined"==typeof t.end?(n=t.start,r=n):t.start>t.end?(n=t.end,r=t.start):(n=t.start,r=t.end),o.moveToElementText(e),o.moveStart("character",n),o.setEndPoint("EndToStart",o),o.moveEnd("character",r-n),o.select()}function u(e,t){if(window.getSelection){var n=window.getSelection(),r=e[c()].length,o=Math.min(t.start,r),i="undefined"==typeof t.end?o:Math.min(t.end,r);if(!n.extend&&o>i){var a=i;i=o,o=a}var u=l(e,o),s=l(e,i);if(u&&s){var p=document.createRange();p.setStart(u.node,u.offset),n.removeAllRanges(),o>i?(n.addRange(p),n.extend(s.node,s.offset)):(p.setEnd(s.node,s.offset),n.addRange(p))}}}var s=e(21),l=e(126),c=e(128),p=s.canUseDOM&&"selection"in document&&!("getSelection"in window),d={getOffsets:p?o:i,setOffsets:p?a:u};t.exports=d},{126:126,128:128,21:21}],51:[function(e,t,n){"use strict";var r=e(11),o=e(35),i=e(42),a=e(27),u=e(114),s=function(e){};a(s.prototype,{construct:function(e){this._currentElement=e,this._stringText=""+e,this._rootNodeID=null,this._mountIndex=0},mountComponent:function(e,t,n){this._rootNodeID=e;var o=u(this._stringText);return t.renderToStaticMarkup?o:"<span "+r.createMarkupForID(e)+">"+o+"</span>"},receiveComponent:function(e,t){if(e!==this._currentElement){this._currentElement=e;var n=""+e;n!==this._stringText&&(this._stringText=n,i.BackendIDOperations.updateTextContentByID(this._rootNodeID,n))}},unmountComponent:function(){o.unmountIDFromEnvironment(this._rootNodeID)}}),t.exports=s},{11:11,114:114,27:27,35:35,42:42}],52:[function(e,t,n){"use strict";function r(){this.isMounted()&&this.forceUpdate()}var o=e(2),i=e(11),a=e(24),u=e(29),s=e(33),l=e(55),c=e(85),p=e(27),d=e(133),f=(e(150),l.createFactory("textarea")),h=s.createClass({displayName:"ReactDOMTextarea",tagName:"TEXTAREA",mixins:[o,a.Mixin,u],getInitialState:function(){var e=this.props.defaultValue,t=this.props.children;null!=t&&(d(null==e),Array.isArray(t)&&(d(t.length<=1),t=t[0]),e=""+t),null==e&&(e="");var n=a.getValue(this);return{initialValue:""+(null!=n?n:e)}},render:function(){var e=p({},this.props);return d(null==e.dangerouslySetInnerHTML),e.defaultValue=null,e.value=null,e.onChange=this._handleChange,f(e,this.state.initialValue)},componentDidUpdate:function(e,t,n){var r=a.getValue(this);if(null!=r){var o=this.getDOMNode();i.setValueForProperty(o,"value",""+r)}},_handleChange:function(e){var t,n=a.getOnChange(this);return n&&(t=n.call(this,e)),c.asap(r,this),t}});t.exports=h},{11:11,133:133,150:150,2:2,24:24,27:27,29:29,33:33,55:55,85:85}],53:[function(e,t,n){"use strict";function r(){this.reinitializeTransaction()}var o=e(85),i=e(101),a=e(27),u=e(112),s={initialize:u,close:function(){d.isBatchingUpdates=!1}},l={initialize:u,close:o.flushBatchedUpdates.bind(o)},c=[l,s];a(r.prototype,i.Mixin,{getTransactionWrappers:function(){return c}});var p=new r,d={isBatchingUpdates:!1,batchedUpdates:function(e,t,n,r,o){var i=d.isBatchingUpdates;d.isBatchingUpdates=!0,i?e(t,n,r,o):p.perform(e,null,t,n,r,o)}};t.exports=d},{101:101,112:112,27:27,85:85}],54:[function(e,t,n){"use strict";function r(e){return h.createClass({tagName:e.toUpperCase(),render:function(){return new T(e,null,null,null,null,this.props)}})}function o(){P.EventEmitter.injectReactEventListener(R),P.EventPluginHub.injectEventPluginOrder(s),P.EventPluginHub.injectInstanceHandle(w),P.EventPluginHub.injectMount(O),P.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:L,EnterLeaveEventPlugin:l,ChangeEventPlugin:a,MobileSafariClickEventPlugin:d,SelectEventPlugin:A,BeforeInputEventPlugin:i}),P.NativeComponent.injectGenericComponentClass(g),P.NativeComponent.injectTextComponentClass(I),P.NativeComponent.injectAutoWrapper(r),P.Class.injectMixin(f),P.NativeComponent.injectComponentClasses({button:y,form:C,iframe:_,img:E,input:x,option:D,select:M,textarea:N,html:F("html"),head:F("head"),body:F("body")}),P.DOMProperty.injectDOMPropertyConfig(p),P.DOMProperty.injectDOMPropertyConfig(U),P.EmptyComponent.injectEmptyComponent("noscript"),P.Updates.injectReconcileTransaction(S),P.Updates.injectBatchingStrategy(v),P.RootIndex.injectCreateReactRootIndex(c.canUseDOM?u.createReactRootIndex:k.createReactRootIndex),P.Component.injectEnvironment(m),P.DOMComponent.injectIDOperations(b)}var i=e(3),a=e(7),u=e(8),s=e(13),l=e(14),c=e(21),p=e(23),d=e(26),f=e(29),h=e(33),m=e(35),v=e(53),g=e(42),y=e(41),C=e(43),E=e(46),b=e(44),_=e(45),x=e(47),D=e(48),M=e(49),N=e(52),I=e(51),T=e(55),R=e(60),P=e(62),w=e(64),O=e(68),S=e(78),A=e(87),k=e(88),L=e(89),U=e(86),F=e(109);t.exports={inject:o}},{109:109,13:13,14:14,21:21,23:23,26:26,29:29,3:3,33:33,35:35,41:41,42:42,43:43,44:44,45:45,46:46,47:47,48:48,49:49,51:51,52:52,53:53,55:55,60:60,62:62,64:64,68:68,7:7,78:78,8:8,86:86,87:87,88:88,
-89:89}],55:[function(e,t,n){"use strict";var r=e(38),o=e(39),i=e(27),a=(e(150),{key:!0,ref:!0}),u=function(e,t,n,r,o,i){this.type=e,this.key=t,this.ref=n,this._owner=r,this._context=o,this.props=i};u.prototype={_isReactElement:!0},u.createElement=function(e,t,n){var i,s={},l=null,c=null;if(null!=t){c=void 0===t.ref?null:t.ref,l=void 0===t.key?null:""+t.key;for(i in t)t.hasOwnProperty(i)&&!a.hasOwnProperty(i)&&(s[i]=t[i])}var p=arguments.length-2;if(1===p)s.children=n;else if(p>1){for(var d=Array(p),f=0;p>f;f++)d[f]=arguments[f+2];s.children=d}if(e&&e.defaultProps){var h=e.defaultProps;for(i in h)"undefined"==typeof s[i]&&(s[i]=h[i])}return new u(e,l,c,o.current,r.current,s)},u.createFactory=function(e){var t=u.createElement.bind(null,e);return t.type=e,t},u.cloneAndReplaceProps=function(e,t){var n=new u(e.type,e.key,e.ref,e._owner,e._context,t);return n},u.cloneElement=function(e,t,n){var r,s=i({},e.props),l=e.key,c=e.ref,p=e._owner;if(null!=t){void 0!==t.ref&&(c=t.ref,p=o.current),void 0!==t.key&&(l=""+t.key);for(r in t)t.hasOwnProperty(r)&&!a.hasOwnProperty(r)&&(s[r]=t[r])}var d=arguments.length-2;if(1===d)s.children=n;else if(d>1){for(var f=Array(d),h=0;d>h;h++)f[h]=arguments[h+2];s.children=f}return new u(e.type,l,c,p,e._context,s)},u.isValidElement=function(e){var t=!(!e||!e._isReactElement);return t},t.exports=u},{150:150,27:27,38:38,39:39}],56:[function(e,t,n){"use strict";function r(){if(y.current){var e=y.current.getName();if(e)return" Check the render method of `"+e+"`."}return""}function o(e){var t=e&&e.getPublicInstance();if(!t)return void 0;var n=t.constructor;return n?n.displayName||n.name||void 0:void 0}function i(){var e=y.current;return e&&o(e)||void 0}function a(e,t){e._store.validated||null!=e.key||(e._store.validated=!0,s('Each child in an array or iterator should have a unique "key" prop.',e,t))}function u(e,t,n){D.test(e)&&s("Child objects should have non-numeric keys so ordering is preserved.",t,n)}function s(e,t,n){var r=i(),a="string"==typeof n?n:n.displayName||n.name,u=r||a,s=_[e]||(_[e]={});if(!s.hasOwnProperty(u)){s[u]=!0;var l="";if(t&&t._owner&&t._owner!==y.current){var c=o(t._owner);l=" It was passed a child from "+c+"."}}}function l(e,t){if(Array.isArray(e))for(var n=0;n<e.length;n++){var r=e[n];m.isValidElement(r)&&a(r,t)}else if(m.isValidElement(e))e._store.validated=!0;else if(e){var o=E(e);if(o){if(o!==e.entries)for(var i,s=o.call(e);!(i=s.next()).done;)m.isValidElement(i.value)&&a(i.value,t)}else if("object"==typeof e){var l=v.extractIfFragment(e);for(var c in l)l.hasOwnProperty(c)&&u(c,l[c],t)}}}function c(e,t,n,o){for(var i in t)if(t.hasOwnProperty(i)){var a;try{b("function"==typeof t[i]),a=t[i](n,i,e,o)}catch(u){a=u}a instanceof Error&&!(a.message in x)&&(x[a.message]=!0,r(this))}}function p(e,t){var n=t.type,r="string"==typeof n?n:n.displayName,o=t._owner?t._owner.getPublicInstance().constructor.displayName:null,i=e+"|"+r+"|"+o;if(!M.hasOwnProperty(i)){M[i]=!0;var a="";r&&(a=" <"+r+" />");var u="";o&&(u=" The element was created by "+o+".")}}function d(e,t){return e!==e?t!==t:0===e&&0===t?1/e===1/t:e===t}function f(e){if(e._store){var t=e._store.originalProps,n=e.props;for(var r in n)n.hasOwnProperty(r)&&(t.hasOwnProperty(r)&&d(t[r],n[r])||(p(r,e),t[r]=n[r]))}}function h(e){if(null!=e.type){var t=C.getComponentClassForElement(e),n=t.displayName||t.name;t.propTypes&&c(n,t.propTypes,e.props,g.prop),"function"==typeof t.getDefaultProps}}var m=e(55),v=e(61),g=e(75),y=(e(74),e(39)),C=e(71),E=e(124),b=e(133),_=(e(150),{}),x={},D=/^\d+$/,M={},N={checkAndWarnForMutatedProps:f,createElement:function(e,t,n){var r=m.createElement.apply(this,arguments);if(null==r)return r;for(var o=2;o<arguments.length;o++)l(arguments[o],e);return h(r),r},createFactory:function(e){var t=N.createElement.bind(null,e);return t.type=e,t},cloneElement:function(e,t,n){for(var r=m.cloneElement.apply(this,arguments),o=2;o<arguments.length;o++)l(arguments[o],r.type);return h(r),r}};t.exports=N},{124:124,133:133,150:150,39:39,55:55,61:61,71:71,74:74,75:75}],57:[function(e,t,n){"use strict";function r(e){c[e]=!0}function o(e){delete c[e]}function i(e){return!!c[e]}var a,u=e(55),s=e(65),l=e(133),c={},p={injectEmptyComponent:function(e){a=u.createFactory(e)}},d=function(){};d.prototype.componentDidMount=function(){var e=s.get(this);e&&r(e._rootNodeID)},d.prototype.componentWillUnmount=function(){var e=s.get(this);e&&o(e._rootNodeID)},d.prototype.render=function(){return l(a),a()};var f=u.createElement(d),h={emptyElement:f,injection:p,isNullComponentID:i};t.exports=h},{133:133,55:55,65:65}],58:[function(e,t,n){"use strict";var r={guard:function(e,t){return e}};t.exports=r},{}],59:[function(e,t,n){"use strict";function r(e){o.enqueueEvents(e),o.processEventQueue()}var o=e(17),i={handleTopLevel:function(e,t,n,i){var a=o.extractEvents(e,t,n,i);r(a)}};t.exports=i},{17:17}],60:[function(e,t,n){"use strict";function r(e){var t=p.getID(e),n=c.getReactRootIDFromNodeID(t),r=p.findReactContainerForID(n),o=p.getFirstReactDOM(r);return o}function o(e,t){this.topLevelType=e,this.nativeEvent=t,this.ancestors=[]}function i(e){for(var t=p.getFirstReactDOM(h(e.nativeEvent))||window,n=t;n;)e.ancestors.push(n),n=r(n);for(var o=0,i=e.ancestors.length;i>o;o++){t=e.ancestors[o];var a=p.getID(t)||"";v._handleTopLevel(e.topLevelType,t,a,e.nativeEvent)}}function a(e){var t=m(window);e(t)}var u=e(16),s=e(21),l=e(28),c=e(64),p=e(68),d=e(85),f=e(27),h=e(123),m=e(129);f(o.prototype,{destructor:function(){this.topLevelType=null,this.nativeEvent=null,this.ancestors.length=0}}),l.addPoolingTo(o,l.twoArgumentPooler);var v={_enabled:!0,_handleTopLevel:null,WINDOW_HANDLE:s.canUseDOM?window:null,setHandleTopLevel:function(e){v._handleTopLevel=e},setEnabled:function(e){v._enabled=!!e},isEnabled:function(){return v._enabled},trapBubbledEvent:function(e,t,n){var r=n;return r?u.listen(r,t,v.dispatchEvent.bind(null,e)):null},trapCapturedEvent:function(e,t,n){var r=n;return r?u.capture(r,t,v.dispatchEvent.bind(null,e)):null},monitorScrollValue:function(e){var t=a.bind(null,e);u.listen(window,"scroll",t)},dispatchEvent:function(e,t){if(v._enabled){var n=o.getPooled(e,t);try{d.batchedUpdates(i,n)}finally{o.release(n)}}}};t.exports=v},{123:123,129:129,16:16,21:21,27:27,28:28,64:64,68:68,85:85}],61:[function(e,t,n){"use strict";var r=(e(55),e(150),{create:function(e){return e},extract:function(e){return e},extractIfFragment:function(e){return e}});t.exports=r},{150:150,55:55}],62:[function(e,t,n){"use strict";var r=e(10),o=e(17),i=e(36),a=e(33),u=e(57),s=e(30),l=e(71),c=e(42),p=e(73),d=e(81),f=e(85),h={Component:i.injection,Class:a.injection,DOMComponent:c.injection,DOMProperty:r.injection,EmptyComponent:u.injection,EventPluginHub:o.injection,EventEmitter:s.injection,NativeComponent:l.injection,Perf:p.injection,RootIndex:d.injection,Updates:f.injection};t.exports=h},{10:10,17:17,30:30,33:33,36:36,42:42,57:57,71:71,73:73,81:81,85:85}],63:[function(e,t,n){"use strict";function r(e){return i(document.documentElement,e)}var o=e(50),i=e(107),a=e(117),u=e(119),s={hasSelectionCapabilities:function(e){return e&&("INPUT"===e.nodeName&&"text"===e.type||"TEXTAREA"===e.nodeName||"true"===e.contentEditable)},getSelectionInformation:function(){var e=u();return{focusedElem:e,selectionRange:s.hasSelectionCapabilities(e)?s.getSelection(e):null}},restoreSelection:function(e){var t=u(),n=e.focusedElem,o=e.selectionRange;t!==n&&r(n)&&(s.hasSelectionCapabilities(n)&&s.setSelection(n,o),a(n))},getSelection:function(e){var t;if("selectionStart"in e)t={start:e.selectionStart,end:e.selectionEnd};else if(document.selection&&"INPUT"===e.nodeName){var n=document.selection.createRange();n.parentElement()===e&&(t={start:-n.moveStart("character",-e.value.length),end:-n.moveEnd("character",-e.value.length)})}else t=o.getOffsets(e);return t||{start:0,end:0}},setSelection:function(e,t){var n=t.start,r=t.end;if("undefined"==typeof r&&(r=n),"selectionStart"in e)e.selectionStart=n,e.selectionEnd=Math.min(r,e.value.length);else if(document.selection&&"INPUT"===e.nodeName){var i=e.createTextRange();i.collapse(!0),i.moveStart("character",n),i.moveEnd("character",r-n),i.select()}else o.setOffsets(e,t)}};t.exports=s},{107:107,117:117,119:119,50:50}],64:[function(e,t,n){"use strict";function r(e){return f+e.toString(36)}function o(e,t){return e.charAt(t)===f||t===e.length}function i(e){return""===e||e.charAt(0)===f&&e.charAt(e.length-1)!==f}function a(e,t){return 0===t.indexOf(e)&&o(t,e.length)}function u(e){return e?e.substr(0,e.lastIndexOf(f)):""}function s(e,t){if(d(i(e)&&i(t)),d(a(e,t)),e===t)return e;var n,r=e.length+h;for(n=r;n<t.length&&!o(t,n);n++);return t.substr(0,n)}function l(e,t){var n=Math.min(e.length,t.length);if(0===n)return"";for(var r=0,a=0;n>=a;a++)if(o(e,a)&&o(t,a))r=a;else if(e.charAt(a)!==t.charAt(a))break;var u=e.substr(0,r);return d(i(u)),u}function c(e,t,n,r,o,i){e=e||"",t=t||"",d(e!==t);var l=a(t,e);d(l||a(e,t));for(var c=0,p=l?u:s,f=e;;f=p(f,t)){var h;if(o&&f===e||i&&f===t||(h=n(f,l,r)),h===!1||f===t)break;d(c++<m)}}var p=e(81),d=e(133),f=".",h=f.length,m=100,v={createReactRootID:function(){return r(p.createReactRootIndex())},createReactID:function(e,t){return e+t},getReactRootIDFromNodeID:function(e){if(e&&e.charAt(0)===f&&e.length>1){var t=e.indexOf(f,1);return t>-1?e.substr(0,t):e}return null},traverseEnterLeave:function(e,t,n,r,o){var i=l(e,t);i!==e&&c(e,i,n,r,!1,!0),i!==t&&c(i,t,n,o,!0,!1)},traverseTwoPhase:function(e,t,n){e&&(c("",e,t,n,!0,!1),c(e,"",t,n,!1,!0))},traverseAncestors:function(e,t,n){c("",e,t,n,!0,!1)},_getFirstCommonAncestorID:l,_getNextDescendantID:s,isAncestorIDOf:a,SEPARATOR:f};t.exports=v},{133:133,81:81}],65:[function(e,t,n){"use strict";var r={remove:function(e){e._reactInternalInstance=void 0},get:function(e){return e._reactInternalInstance},has:function(e){return void 0!==e._reactInternalInstance},set:function(e,t){e._reactInternalInstance=t}};t.exports=r},{}],66:[function(e,t,n){"use strict";var r={currentlyMountingInstance:null,currentlyUnmountingInstance:null};t.exports=r},{}],67:[function(e,t,n){"use strict";var r=e(104),o={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(e){var t=r(e);return e.replace(">"," "+o.CHECKSUM_ATTR_NAME+'="'+t+'">')},canReuseMarkup:function(e,t){var n=t.getAttribute(o.CHECKSUM_ATTR_NAME);n=n&&parseInt(n,10);var i=r(e);return i===n}};t.exports=o},{104:104}],68:[function(e,t,n){"use strict";function r(e,t){for(var n=Math.min(e.length,t.length),r=0;n>r;r++)if(e.charAt(r)!==t.charAt(r))return r;return e.length===t.length?-1:n}function o(e){var t=R(e);return t&&K.getID(t)}function i(e){var t=a(e);if(t)if(L.hasOwnProperty(t)){var n=L[t];n!==e&&(w(!c(n,t)),L[t]=e)}else L[t]=e;return t}function a(e){return e&&e.getAttribute&&e.getAttribute(k)||""}function u(e,t){var n=a(e);n!==t&&delete L[n],e.setAttribute(k,t),L[t]=e}function s(e){return L.hasOwnProperty(e)&&c(L[e],e)||(L[e]=K.findReactNodeByID(e)),L[e]}function l(e){var t=b.get(e)._rootNodeID;return C.isNullComponentID(t)?null:(L.hasOwnProperty(t)&&c(L[t],t)||(L[t]=K.findReactNodeByID(t)),L[t])}function c(e,t){if(e){w(a(e)===t);var n=K.findReactContainerForID(t);if(n&&T(n,e))return!0}return!1}function p(e){delete L[e]}function d(e){var t=L[e];return t&&c(t,e)?void(W=t):!1}function f(e){W=null,E.traverseAncestors(e,d);var t=W;return W=null,t}function h(e,t,n,r,o){var i=D.mountComponent(e,t,r,I);e._isTopLevel=!0,K._mountImageIntoNode(i,n,o)}function m(e,t,n,r){var o=N.ReactReconcileTransaction.getPooled();o.perform(h,null,e,t,n,o,r),N.ReactReconcileTransaction.release(o)}var v=e(10),g=e(30),y=(e(39),e(55)),C=(e(56),e(57)),E=e(64),b=e(65),_=e(67),x=e(73),D=e(79),M=e(84),N=e(85),I=e(113),T=e(107),R=e(127),P=e(132),w=e(133),O=e(144),S=e(147),A=(e(150),E.SEPARATOR),k=v.ID_ATTRIBUTE_NAME,L={},U=1,F=9,B={},V={},j=[],W=null,K={_instancesByReactRootID:B,scrollMonitor:function(e,t){t()},_updateRootComponent:function(e,t,n,r){return K.scrollMonitor(n,function(){M.enqueueElementInternal(e,t),r&&M.enqueueCallbackInternal(e,r)}),e},_registerComponent:function(e,t){w(t&&(t.nodeType===U||t.nodeType===F)),g.ensureScrollValueMonitoring();var n=K.registerContainer(t);return B[n]=e,n},_renderNewRootComponent:function(e,t,n){var r=P(e,null),o=K._registerComponent(r,t);return N.batchedUpdates(m,r,o,t,n),r},render:function(e,t,n){w(y.isValidElement(e));var r=B[o(t)];if(r){var i=r._currentElement;if(S(i,e))return K._updateRootComponent(r,e,t,n).getPublicInstance();K.unmountComponentAtNode(t)}var a=R(t),u=a&&K.isRenderedByReact(a),s=u&&!r,l=K._renderNewRootComponent(e,t,s).getPublicInstance();return n&&n.call(l),l},constructAndRenderComponent:function(e,t,n){var r=y.createElement(e,t);return K.render(r,n)},constructAndRenderComponentByID:function(e,t,n){var r=document.getElementById(n);return w(r),K.constructAndRenderComponent(e,t,r)},registerContainer:function(e){var t=o(e);return t&&(t=E.getReactRootIDFromNodeID(t)),t||(t=E.createReactRootID()),V[t]=e,t},unmountComponentAtNode:function(e){w(e&&(e.nodeType===U||e.nodeType===F));var t=o(e),n=B[t];return n?(K.unmountComponentFromNode(n,e),delete B[t],delete V[t],!0):!1},unmountComponentFromNode:function(e,t){for(D.unmountComponent(e),t.nodeType===F&&(t=t.documentElement);t.lastChild;)t.removeChild(t.lastChild)},findReactContainerForID:function(e){var t=E.getReactRootIDFromNodeID(e),n=V[t];return n},findReactNodeByID:function(e){var t=K.findReactContainerForID(e);return K.findComponentRoot(t,e)},isRenderedByReact:function(e){if(1!==e.nodeType)return!1;var t=K.getID(e);return t?t.charAt(0)===A:!1},getFirstReactDOM:function(e){for(var t=e;t&&t.parentNode!==t;){if(K.isRenderedByReact(t))return t;t=t.parentNode}return null},findComponentRoot:function(e,t){var n=j,r=0,o=f(t)||e;for(n[0]=o.firstChild,n.length=1;r<n.length;){for(var i,a=n[r++];a;){var u=K.getID(a);u?t===u?i=a:E.isAncestorIDOf(u,t)&&(n.length=r=0,n.push(a.firstChild)):n.push(a.firstChild),a=a.nextSibling}if(i)return n.length=0,i}n.length=0,w(!1)},_mountImageIntoNode:function(e,t,n){if(w(t&&(t.nodeType===U||t.nodeType===F)),n){var o=R(t);if(_.canReuseMarkup(e,o))return;var i=o.getAttribute(_.CHECKSUM_ATTR_NAME);o.removeAttribute(_.CHECKSUM_ATTR_NAME);var a=o.outerHTML;o.setAttribute(_.CHECKSUM_ATTR_NAME,i);var u=r(e,a);" (client) "+e.substring(u-20,u+20)+"\n (server) "+a.substring(u-20,u+20),w(t.nodeType!==F)}w(t.nodeType!==F),O(t,e)},getReactRootID:o,getID:i,setID:u,getNode:s,getNodeFromInstance:l,purgeID:p};x.measureMethods(K,"ReactMount",{_renderNewRootComponent:"_renderNewRootComponent",_mountImageIntoNode:"_mountImageIntoNode"}),t.exports=K},{10:10,107:107,113:113,127:127,132:132,133:133,144:144,147:147,150:150,30:30,39:39,55:55,56:56,57:57,64:64,65:65,67:67,73:73,79:79,84:84,85:85}],69:[function(e,t,n){"use strict";function r(e,t,n){h.push({parentID:e,parentNode:null,type:c.INSERT_MARKUP,markupIndex:m.push(t)-1,textContent:null,fromIndex:null,toIndex:n})}function o(e,t,n){h.push({parentID:e,parentNode:null,type:c.MOVE_EXISTING,markupIndex:null,textContent:null,fromIndex:t,toIndex:n})}function i(e,t){h.push({parentID:e,parentNode:null,type:c.REMOVE_NODE,markupIndex:null,textContent:null,fromIndex:t,toIndex:null})}function a(e,t){h.push({parentID:e,parentNode:null,type:c.TEXT_CONTENT,markupIndex:null,textContent:t,fromIndex:null,toIndex:null})}function u(){h.length&&(l.processChildrenUpdates(h,m),s())}function s(){h.length=0,m.length=0}var l=e(36),c=e(70),p=e(79),d=e(31),f=0,h=[],m=[],v={Mixin:{mountChildren:function(e,t,n){var r=d.instantiateChildren(e,t,n);this._renderedChildren=r;var o=[],i=0;for(var a in r)if(r.hasOwnProperty(a)){var u=r[a],s=this._rootNodeID+a,l=p.mountComponent(u,s,t,n);u._mountIndex=i,o.push(l),i++}return o},updateTextContent:function(e){f++;var t=!0;try{var n=this._renderedChildren;d.unmountChildren(n);for(var r in n)n.hasOwnProperty(r)&&this._unmountChildByName(n[r],r);this.setTextContent(e),t=!1}finally{f--,f||(t?s():u())}},updateChildren:function(e,t,n){f++;var r=!0;try{this._updateChildren(e,t,n),r=!1}finally{f--,f||(r?s():u())}},_updateChildren:function(e,t,n){var r=this._renderedChildren,o=d.updateChildren(r,e,t,n);if(this._renderedChildren=o,o||r){var i,a=0,u=0;for(i in o)if(o.hasOwnProperty(i)){var s=r&&r[i],l=o[i];s===l?(this.moveChild(s,u,a),a=Math.max(s._mountIndex,a),s._mountIndex=u):(s&&(a=Math.max(s._mountIndex,a),this._unmountChildByName(s,i)),this._mountChildByNameAtIndex(l,i,u,t,n)),u++}for(i in r)!r.hasOwnProperty(i)||o&&o.hasOwnProperty(i)||this._unmountChildByName(r[i],i)}},unmountChildren:function(){var e=this._renderedChildren;d.unmountChildren(e),this._renderedChildren=null},moveChild:function(e,t,n){e._mountIndex<n&&o(this._rootNodeID,e._mountIndex,t)},createChild:function(e,t){r(this._rootNodeID,t,e._mountIndex)},removeChild:function(e){i(this._rootNodeID,e._mountIndex)},setTextContent:function(e){a(this._rootNodeID,e)},_mountChildByNameAtIndex:function(e,t,n,r,o){var i=this._rootNodeID+t,a=p.mountComponent(e,i,r,o);e._mountIndex=n,this.createChild(e,a)},_unmountChildByName:function(e,t){this.removeChild(e),e._mountIndex=null}}};t.exports=v},{31:31,36:36,70:70,79:79}],70:[function(e,t,n){"use strict";var r=e(138),o=r({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOVE_NODE:null,TEXT_CONTENT:null});t.exports=o},{138:138}],71:[function(e,t,n){"use strict";function r(e){if("function"==typeof e.type)return e.type;var t=e.type,n=p[t];return null==n&&(p[t]=n=l(t)),n}function o(e){return s(c),new c(e.type,e.props)}function i(e){return new d(e)}function a(e){return e instanceof d}var u=e(27),s=e(133),l=null,c=null,p={},d=null,f={injectGenericComponentClass:function(e){c=e},injectTextComponentClass:function(e){d=e},injectComponentClasses:function(e){u(p,e)},injectAutoWrapper:function(e){l=e}},h={getComponentClassForElement:r,createInternalComponent:o,createInstanceForText:i,isTextComponent:a,injection:f};t.exports=h},{133:133,27:27}],72:[function(e,t,n){"use strict";var r=e(133),o={isValidOwner:function(e){return!(!e||"function"!=typeof e.attachRef||"function"!=typeof e.detachRef)},addComponentAsRefTo:function(e,t,n){r(o.isValidOwner(n)),n.attachRef(t,e)},removeComponentAsRefFrom:function(e,t,n){r(o.isValidOwner(n)),n.getPublicInstance().refs[t]===e.getPublicInstance()&&n.detachRef(t)}};t.exports=o},{133:133}],73:[function(e,t,n){"use strict";function r(e,t,n){return n}var o={enableMeasure:!1,storedMeasure:r,measureMethods:function(e,t,n){},measure:function(e,t,n){return n},injection:{injectMeasure:function(e){o.storedMeasure=e}}};t.exports=o},{}],74:[function(e,t,n){"use strict";var r={};t.exports=r},{}],75:[function(e,t,n){"use strict";var r=e(138),o=r({prop:null,context:null,childContext:null});t.exports=o},{138:138}],76:[function(e,t,n){"use strict";function r(e){function t(t,n,r,o,i){if(o=o||b,null==n[r]){var a=C[i];return t?new Error("Required "+a+" `"+r+"` was not specified in "+("`"+o+"`.")):null}return e(n,r,o,i)}var n=t.bind(null,!1);return n.isRequired=t.bind(null,!0),n}function o(e){function t(t,n,r,o){var i=t[n],a=m(i);if(a!==e){var u=C[o],s=v(i);return new Error("Invalid "+u+" `"+n+"` of type `"+s+"` "+("supplied to `"+r+"`, expected `"+e+"`."))}return null}return r(t)}function i(){return r(E.thatReturns(null))}function a(e){function t(t,n,r,o){var i=t[n];if(!Array.isArray(i)){var a=C[o],u=m(i);return new Error("Invalid "+a+" `"+n+"` of type "+("`"+u+"` supplied to `"+r+"`, expected an array."))}for(var s=0;s<i.length;s++){var l=e(i,s,r,o);if(l instanceof Error)return l}return null}return r(t)}function u(){function e(e,t,n,r){if(!g.isValidElement(e[t])){var o=C[r];return new Error("Invalid "+o+" `"+t+"` supplied to "+("`"+n+"`, expected a ReactElement."))}return null}return r(e)}function s(e){function t(t,n,r,o){if(!(t[n]instanceof e)){var i=C[o],a=e.name||b;return new Error("Invalid "+i+" `"+n+"` supplied to "+("`"+r+"`, expected instance of `"+a+"`."))}return null}return r(t)}function l(e){function t(t,n,r,o){for(var i=t[n],a=0;a<e.length;a++)if(i===e[a])return null;var u=C[o],s=JSON.stringify(e);return new Error("Invalid "+u+" `"+n+"` of value `"+i+"` "+("supplied to `"+r+"`, expected one of "+s+"."))}return r(t)}function c(e){function t(t,n,r,o){var i=t[n],a=m(i);if("object"!==a){var u=C[o];return new Error("Invalid "+u+" `"+n+"` of type "+("`"+a+"` supplied to `"+r+"`, expected an object."))}for(var s in i)if(i.hasOwnProperty(s)){var l=e(i,s,r,o);if(l instanceof Error)return l}return null}return r(t)}function p(e){function t(t,n,r,o){for(var i=0;i<e.length;i++){var a=e[i];if(null==a(t,n,r,o))return null}var u=C[o];return new Error("Invalid "+u+" `"+n+"` supplied to "+("`"+r+"`."))}return r(t)}function d(){function e(e,t,n,r){if(!h(e[t])){var o=C[r];return new Error("Invalid "+o+" `"+t+"` supplied to "+("`"+n+"`, expected a ReactNode."))}return null}return r(e)}function f(e){function t(t,n,r,o){var i=t[n],a=m(i);if("object"!==a){var u=C[o];return new Error("Invalid "+u+" `"+n+"` of type `"+a+"` "+("supplied to `"+r+"`, expected `object`."))}for(var s in e){var l=e[s];if(l){var c=l(i,s,r,o);if(c)return c}}return null}return r(t)}function h(e){switch(typeof e){case"number":case"string":case"undefined":return!0;case"boolean":return!e;case"object":if(Array.isArray(e))return e.every(h);if(null===e||g.isValidElement(e))return!0;e=y.extractIfFragment(e);for(var t in e)if(!h(e[t]))return!1;return!0;default:return!1}}function m(e){var t=typeof e;return Array.isArray(e)?"array":e instanceof RegExp?"object":t}function v(e){var t=m(e);if("object"===t){if(e instanceof Date)return"date";if(e instanceof RegExp)return"regexp"}return t}var g=e(55),y=e(61),C=e(74),E=e(112),b="<<anonymous>>",_=u(),x=d(),D={array:o("array"),bool:o("boolean"),func:o("function"),number:o("number"),object:o("object"),string:o("string"),any:i(),arrayOf:a,element:_,instanceOf:s,node:x,objectOf:c,oneOf:l,oneOfType:p,shape:f};t.exports=D},{112:112,55:55,61:61,74:74}],77:[function(e,t,n){"use strict";function r(){this.listenersToPut=[]}var o=e(28),i=e(30),a=e(27);a(r.prototype,{enqueuePutListener:function(e,t,n){this.listenersToPut.push({rootNodeID:e,propKey:t,propValue:n})},putListeners:function(){for(var e=0;e<this.listenersToPut.length;e++){var t=this.listenersToPut[e];i.putListener(t.rootNodeID,t.propKey,t.propValue)}},reset:function(){this.listenersToPut.length=0},destructor:function(){this.reset()}}),o.addPoolingTo(r),t.exports=r},{27:27,28:28,30:30}],78:[function(e,t,n){"use strict";function r(){this.reinitializeTransaction(),this.renderToStaticMarkup=!1,this.reactMountReady=o.getPooled(null),this.putListenerQueue=s.getPooled()}var o=e(6),i=e(28),a=e(30),u=e(63),s=e(77),l=e(101),c=e(27),p={initialize:u.getSelectionInformation,close:u.restoreSelection},d={initialize:function(){var e=a.isEnabled();return a.setEnabled(!1),e},close:function(e){a.setEnabled(e)}},f={initialize:function(){this.reactMountReady.reset()},close:function(){this.reactMountReady.notifyAll()}},h={initialize:function(){this.putListenerQueue.reset()},close:function(){this.putListenerQueue.putListeners()}},m=[h,p,d,f],v={getTransactionWrappers:function(){return m},getReactMountReady:function(){return this.reactMountReady},getPutListenerQueue:function(){return this.putListenerQueue},destructor:function(){o.release(this.reactMountReady),this.reactMountReady=null,s.release(this.putListenerQueue),this.putListenerQueue=null}};c(r.prototype,l.Mixin,v),i.addPoolingTo(r),t.exports=r},{101:101,27:27,28:28,30:30,6:6,63:63,77:77}],79:[function(e,t,n){"use strict";function r(){o.attachRefs(this,this._currentElement)}var o=e(80),i=(e(56),{mountComponent:function(e,t,n,o){var i=e.mountComponent(t,n,o);return n.getReactMountReady().enqueue(r,e),i},unmountComponent:function(e){o.detachRefs(e,e._currentElement),e.unmountComponent()},receiveComponent:function(e,t,n,i){var a=e._currentElement;if(t!==a||null==t._owner){var u=o.shouldUpdateRefs(a,t);u&&o.detachRefs(e,a),e.receiveComponent(t,n,i),u&&n.getReactMountReady().enqueue(r,e)}},performUpdateIfNecessary:function(e,t){e.performUpdateIfNecessary(t)}});t.exports=i},{56:56,80:80}],80:[function(e,t,n){"use strict";function r(e,t,n){"function"==typeof e?e(t.getPublicInstance()):i.addComponentAsRefTo(t,e,n)}function o(e,t,n){"function"==typeof e?e(null):i.removeComponentAsRefFrom(t,e,n)}var i=e(72),a={};a.attachRefs=function(e,t){var n=t.ref;null!=n&&r(n,e,t._owner)},a.shouldUpdateRefs=function(e,t){return t._owner!==e._owner||t.ref!==e.ref},a.detachRefs=function(e,t){var n=t.ref;null!=n&&o(n,e,t._owner)},t.exports=a},{72:72}],81:[function(e,t,n){"use strict";var r={injectCreateReactRootIndex:function(e){o.createReactRootIndex=e}},o={createReactRootIndex:null,injection:r};t.exports=o},{}],82:[function(e,t,n){"use strict";function r(e){p(i.isValidElement(e));var t;try{var n=a.createReactRootID();return t=s.getPooled(!1),t.perform(function(){var r=c(e,null),o=r.mountComponent(n,t,l);return u.addChecksumToMarkup(o)},null)}finally{s.release(t)}}function o(e){p(i.isValidElement(e));var t;try{var n=a.createReactRootID();return t=s.getPooled(!0),t.perform(function(){var r=c(e,null);return r.mountComponent(n,t,l)},null)}finally{s.release(t)}}var i=e(55),a=e(64),u=e(67),s=e(83),l=e(113),c=e(132),p=e(133);t.exports={renderToString:r,renderToStaticMarkup:o}},{113:113,132:132,133:133,55:55,64:64,67:67,83:83}],83:[function(e,t,n){"use strict";function r(e){this.reinitializeTransaction(),this.renderToStaticMarkup=e,this.reactMountReady=i.getPooled(null),this.putListenerQueue=a.getPooled()}var o=e(28),i=e(6),a=e(77),u=e(101),s=e(27),l=e(112),c={initialize:function(){this.reactMountReady.reset()},close:l},p={initialize:function(){this.putListenerQueue.reset()},close:l},d=[p,c],f={getTransactionWrappers:function(){return d},getReactMountReady:function(){return this.reactMountReady},getPutListenerQueue:function(){return this.putListenerQueue},destructor:function(){i.release(this.reactMountReady),this.reactMountReady=null,a.release(this.putListenerQueue),this.putListenerQueue=null}};s(r.prototype,u.Mixin,f),o.addPoolingTo(r),t.exports=r},{101:101,112:112,27:27,28:28,6:6,77:77}],84:[function(e,t,n){"use strict";function r(e){e!==i.currentlyMountingInstance&&l.enqueueUpdate(e)}function o(e,t){p(null==a.current);var n=s.get(e);return n?n===i.currentlyUnmountingInstance?null:n:null}var i=e(66),a=e(39),u=e(55),s=e(65),l=e(85),c=e(27),p=e(133),d=(e(150),{enqueueCallback:function(e,t){p("function"==typeof t);var n=o(e);return n&&n!==i.currentlyMountingInstance?(n._pendingCallbacks?n._pendingCallbacks.push(t):n._pendingCallbacks=[t],void r(n)):null},enqueueCallbackInternal:function(e,t){p("function"==typeof t),e._pendingCallbacks?e._pendingCallbacks.push(t):e._pendingCallbacks=[t],r(e)},enqueueForceUpdate:function(e){var t=o(e,"forceUpdate");t&&(t._pendingForceUpdate=!0,r(t))},enqueueReplaceState:function(e,t){var n=o(e,"replaceState");n&&(n._pendingStateQueue=[t],n._pendingReplaceState=!0,r(n))},enqueueSetState:function(e,t){var n=o(e,"setState");if(n){var i=n._pendingStateQueue||(n._pendingStateQueue=[]);i.push(t),r(n)}},enqueueSetProps:function(e,t){var n=o(e,"setProps");if(n){p(n._isTopLevel);var i=n._pendingElement||n._currentElement,a=c({},i.props,t);n._pendingElement=u.cloneAndReplaceProps(i,a),r(n)}},enqueueReplaceProps:function(e,t){var n=o(e,"replaceProps");if(n){p(n._isTopLevel);var i=n._pendingElement||n._currentElement;n._pendingElement=u.cloneAndReplaceProps(i,t),r(n)}},enqueueElementInternal:function(e,t){e._pendingElement=t,r(e)}});t.exports=d},{133:133,150:150,27:27,39:39,55:55,65:65,66:66,85:85}],85:[function(e,t,n){"use strict";function r(){v(N.ReactReconcileTransaction&&E)}function o(){this.reinitializeTransaction(),this.dirtyComponentsLength=null,this.callbackQueue=c.getPooled(),this.reconcileTransaction=N.ReactReconcileTransaction.getPooled()}function i(e,t,n,o,i){r(),E.batchedUpdates(e,t,n,o,i)}function a(e,t){return e._mountOrder-t._mountOrder}function u(e){var t=e.dirtyComponentsLength;v(t===g.length),g.sort(a);for(var n=0;t>n;n++){var r=g[n],o=r._pendingCallbacks;if(r._pendingCallbacks=null,f.performUpdateIfNecessary(r,e.reconcileTransaction),o)for(var i=0;i<o.length;i++)e.callbackQueue.enqueue(o[i],r.getPublicInstance())}}function s(e){return r(),E.isBatchingUpdates?void g.push(e):void E.batchedUpdates(s,e)}function l(e,t){v(E.isBatchingUpdates),y.enqueue(e,t),C=!0}var c=e(6),p=e(28),d=(e(39),e(73)),f=e(79),h=e(101),m=e(27),v=e(133),g=(e(150),[]),y=c.getPooled(),C=!1,E=null,b={initialize:function(){this.dirtyComponentsLength=g.length},close:function(){this.dirtyComponentsLength!==g.length?(g.splice(0,this.dirtyComponentsLength),D()):g.length=0}},_={initialize:function(){this.callbackQueue.reset()},close:function(){this.callbackQueue.notifyAll()}},x=[b,_];m(o.prototype,h.Mixin,{getTransactionWrappers:function(){return x},destructor:function(){this.dirtyComponentsLength=null,c.release(this.callbackQueue),this.callbackQueue=null,N.ReactReconcileTransaction.release(this.reconcileTransaction),this.reconcileTransaction=null},perform:function(e,t,n){return h.Mixin.perform.call(this,this.reconcileTransaction.perform,this.reconcileTransaction,e,t,n)}}),p.addPoolingTo(o);var D=function(){for(;g.length||C;){if(g.length){var e=o.getPooled();e.perform(u,null,e),o.release(e)}if(C){C=!1;var t=y;y=c.getPooled(),t.notifyAll(),c.release(t)}}};D=d.measure("ReactUpdates","flushBatchedUpdates",D);var M={injectReconcileTransaction:function(e){v(e),N.ReactReconcileTransaction=e},injectBatchingStrategy:function(e){v(e),v("function"==typeof e.batchedUpdates),v("boolean"==typeof e.isBatchingUpdates),E=e}},N={ReactReconcileTransaction:null,batchedUpdates:i,enqueueUpdate:s,flushBatchedUpdates:D,injection:M,asap:l};t.exports=N},{101:101,133:133,150:150,27:27,28:28,39:39,6:6,73:73,79:79}],86:[function(e,t,n){"use strict";var r=e(10),o=r.injection.MUST_USE_ATTRIBUTE,i={Properties:{cx:o,cy:o,d:o,dx:o,dy:o,fill:o,fillOpacity:o,fontFamily:o,fontSize:o,fx:o,fy:o,gradientTransform:o,gradientUnits:o,markerEnd:o,markerMid:o,markerStart:o,offset:o,opacity:o,patternContentUnits:o,patternUnits:o,points:o,preserveAspectRatio:o,r:o,rx:o,ry:o,spreadMethod:o,stopColor:o,stopOpacity:o,stroke:o,strokeDasharray:o,strokeLinecap:o,strokeOpacity:o,strokeWidth:o,textAnchor:o,transform:o,version:o,viewBox:o,x1:o,x2:o,x:o,y1:o,y2:o,y:o},DOMAttributeNames:{fillOpacity:"fill-opacity",fontFamily:"font-family",fontSize:"font-size",gradientTransform:"gradientTransform",gradientUnits:"gradientUnits",markerEnd:"marker-end",markerMid:"marker-mid",markerStart:"marker-start",patternContentUnits:"patternContentUnits",patternUnits:"patternUnits",preserveAspectRatio:"preserveAspectRatio",spreadMethod:"spreadMethod",stopColor:"stop-color",stopOpacity:"stop-opacity",strokeDasharray:"stroke-dasharray",strokeLinecap:"stroke-linecap",strokeOpacity:"stroke-opacity",strokeWidth:"stroke-width",textAnchor:"text-anchor",viewBox:"viewBox"}};t.exports=i},{10:10}],87:[function(e,t,n){"use strict";function r(e){if("selectionStart"in e&&u.hasSelectionCapabilities(e))return{start:e.selectionStart,end:e.selectionEnd};if(window.getSelection){var t=window.getSelection();return{anchorNode:t.anchorNode,anchorOffset:t.anchorOffset,focusNode:t.focusNode,focusOffset:t.focusOffset}}if(document.selection){var n=document.selection.createRange();return{parentElement:n.parentElement(),text:n.text,top:n.boundingTop,left:n.boundingLeft}}}function o(e){if(y||null==m||m!==l())return null;var t=r(m);if(!g||!d(g,t)){g=t;var n=s.getPooled(h.select,v,e);return n.type="select",n.target=m,a.accumulateTwoPhaseDispatches(n),n}}var i=e(15),a=e(20),u=e(63),s=e(93),l=e(119),c=e(136),p=e(139),d=e(146),f=i.topLevelTypes,h={select:{phasedRegistrationNames:{bubbled:p({onSelect:null}),captured:p({onSelectCapture:null})},dependencies:[f.topBlur,f.topContextMenu,f.topFocus,f.topKeyDown,f.topMouseDown,f.topMouseUp,f.topSelectionChange]}},m=null,v=null,g=null,y=!1,C={eventTypes:h,extractEvents:function(e,t,n,r){switch(e){case f.topFocus:(c(t)||"true"===t.contentEditable)&&(m=t,v=n,g=null);break;case f.topBlur:m=null,v=null,g=null;break;case f.topMouseDown:
-y=!0;break;case f.topContextMenu:case f.topMouseUp:return y=!1,o(r);case f.topSelectionChange:case f.topKeyDown:case f.topKeyUp:return o(r)}}};t.exports=C},{119:119,136:136,139:139,146:146,15:15,20:20,63:63,93:93}],88:[function(e,t,n){"use strict";var r=Math.pow(2,53),o={createReactRootIndex:function(){return Math.ceil(Math.random()*r)}};t.exports=o},{}],89:[function(e,t,n){"use strict";var r=e(15),o=e(19),i=e(20),a=e(90),u=e(93),s=e(94),l=e(96),c=e(97),p=e(92),d=e(98),f=e(99),h=e(100),m=e(120),v=e(133),g=e(139),y=(e(150),r.topLevelTypes),C={blur:{phasedRegistrationNames:{bubbled:g({onBlur:!0}),captured:g({onBlurCapture:!0})}},click:{phasedRegistrationNames:{bubbled:g({onClick:!0}),captured:g({onClickCapture:!0})}},contextMenu:{phasedRegistrationNames:{bubbled:g({onContextMenu:!0}),captured:g({onContextMenuCapture:!0})}},copy:{phasedRegistrationNames:{bubbled:g({onCopy:!0}),captured:g({onCopyCapture:!0})}},cut:{phasedRegistrationNames:{bubbled:g({onCut:!0}),captured:g({onCutCapture:!0})}},doubleClick:{phasedRegistrationNames:{bubbled:g({onDoubleClick:!0}),captured:g({onDoubleClickCapture:!0})}},drag:{phasedRegistrationNames:{bubbled:g({onDrag:!0}),captured:g({onDragCapture:!0})}},dragEnd:{phasedRegistrationNames:{bubbled:g({onDragEnd:!0}),captured:g({onDragEndCapture:!0})}},dragEnter:{phasedRegistrationNames:{bubbled:g({onDragEnter:!0}),captured:g({onDragEnterCapture:!0})}},dragExit:{phasedRegistrationNames:{bubbled:g({onDragExit:!0}),captured:g({onDragExitCapture:!0})}},dragLeave:{phasedRegistrationNames:{bubbled:g({onDragLeave:!0}),captured:g({onDragLeaveCapture:!0})}},dragOver:{phasedRegistrationNames:{bubbled:g({onDragOver:!0}),captured:g({onDragOverCapture:!0})}},dragStart:{phasedRegistrationNames:{bubbled:g({onDragStart:!0}),captured:g({onDragStartCapture:!0})}},drop:{phasedRegistrationNames:{bubbled:g({onDrop:!0}),captured:g({onDropCapture:!0})}},focus:{phasedRegistrationNames:{bubbled:g({onFocus:!0}),captured:g({onFocusCapture:!0})}},input:{phasedRegistrationNames:{bubbled:g({onInput:!0}),captured:g({onInputCapture:!0})}},keyDown:{phasedRegistrationNames:{bubbled:g({onKeyDown:!0}),captured:g({onKeyDownCapture:!0})}},keyPress:{phasedRegistrationNames:{bubbled:g({onKeyPress:!0}),captured:g({onKeyPressCapture:!0})}},keyUp:{phasedRegistrationNames:{bubbled:g({onKeyUp:!0}),captured:g({onKeyUpCapture:!0})}},load:{phasedRegistrationNames:{bubbled:g({onLoad:!0}),captured:g({onLoadCapture:!0})}},error:{phasedRegistrationNames:{bubbled:g({onError:!0}),captured:g({onErrorCapture:!0})}},mouseDown:{phasedRegistrationNames:{bubbled:g({onMouseDown:!0}),captured:g({onMouseDownCapture:!0})}},mouseMove:{phasedRegistrationNames:{bubbled:g({onMouseMove:!0}),captured:g({onMouseMoveCapture:!0})}},mouseOut:{phasedRegistrationNames:{bubbled:g({onMouseOut:!0}),captured:g({onMouseOutCapture:!0})}},mouseOver:{phasedRegistrationNames:{bubbled:g({onMouseOver:!0}),captured:g({onMouseOverCapture:!0})}},mouseUp:{phasedRegistrationNames:{bubbled:g({onMouseUp:!0}),captured:g({onMouseUpCapture:!0})}},paste:{phasedRegistrationNames:{bubbled:g({onPaste:!0}),captured:g({onPasteCapture:!0})}},reset:{phasedRegistrationNames:{bubbled:g({onReset:!0}),captured:g({onResetCapture:!0})}},scroll:{phasedRegistrationNames:{bubbled:g({onScroll:!0}),captured:g({onScrollCapture:!0})}},submit:{phasedRegistrationNames:{bubbled:g({onSubmit:!0}),captured:g({onSubmitCapture:!0})}},touchCancel:{phasedRegistrationNames:{bubbled:g({onTouchCancel:!0}),captured:g({onTouchCancelCapture:!0})}},touchEnd:{phasedRegistrationNames:{bubbled:g({onTouchEnd:!0}),captured:g({onTouchEndCapture:!0})}},touchMove:{phasedRegistrationNames:{bubbled:g({onTouchMove:!0}),captured:g({onTouchMoveCapture:!0})}},touchStart:{phasedRegistrationNames:{bubbled:g({onTouchStart:!0}),captured:g({onTouchStartCapture:!0})}},wheel:{phasedRegistrationNames:{bubbled:g({onWheel:!0}),captured:g({onWheelCapture:!0})}}},E={topBlur:C.blur,topClick:C.click,topContextMenu:C.contextMenu,topCopy:C.copy,topCut:C.cut,topDoubleClick:C.doubleClick,topDrag:C.drag,topDragEnd:C.dragEnd,topDragEnter:C.dragEnter,topDragExit:C.dragExit,topDragLeave:C.dragLeave,topDragOver:C.dragOver,topDragStart:C.dragStart,topDrop:C.drop,topError:C.error,topFocus:C.focus,topInput:C.input,topKeyDown:C.keyDown,topKeyPress:C.keyPress,topKeyUp:C.keyUp,topLoad:C.load,topMouseDown:C.mouseDown,topMouseMove:C.mouseMove,topMouseOut:C.mouseOut,topMouseOver:C.mouseOver,topMouseUp:C.mouseUp,topPaste:C.paste,topReset:C.reset,topScroll:C.scroll,topSubmit:C.submit,topTouchCancel:C.touchCancel,topTouchEnd:C.touchEnd,topTouchMove:C.touchMove,topTouchStart:C.touchStart,topWheel:C.wheel};for(var b in E)E[b].dependencies=[b];var _={eventTypes:C,executeDispatch:function(e,t,n){var r=o.executeDispatch(e,t,n);r===!1&&(e.stopPropagation(),e.preventDefault())},extractEvents:function(e,t,n,r){var o=E[e];if(!o)return null;var g;switch(e){case y.topInput:case y.topLoad:case y.topError:case y.topReset:case y.topSubmit:g=u;break;case y.topKeyPress:if(0===m(r))return null;case y.topKeyDown:case y.topKeyUp:g=l;break;case y.topBlur:case y.topFocus:g=s;break;case y.topClick:if(2===r.button)return null;case y.topContextMenu:case y.topDoubleClick:case y.topMouseDown:case y.topMouseMove:case y.topMouseOut:case y.topMouseOver:case y.topMouseUp:g=c;break;case y.topDrag:case y.topDragEnd:case y.topDragEnter:case y.topDragExit:case y.topDragLeave:case y.topDragOver:case y.topDragStart:case y.topDrop:g=p;break;case y.topTouchCancel:case y.topTouchEnd:case y.topTouchMove:case y.topTouchStart:g=d;break;case y.topScroll:g=f;break;case y.topWheel:g=h;break;case y.topCopy:case y.topCut:case y.topPaste:g=a}v(g);var C=g.getPooled(o,n,r);return i.accumulateTwoPhaseDispatches(C),C}};t.exports=_},{100:100,120:120,133:133,139:139,15:15,150:150,19:19,20:20,90:90,92:92,93:93,94:94,96:96,97:97,98:98,99:99}],90:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(93),i={clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}};o.augmentClass(r,i),t.exports=r},{93:93}],91:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(93),i={data:null};o.augmentClass(r,i),t.exports=r},{93:93}],92:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(97),i={dataTransfer:null};o.augmentClass(r,i),t.exports=r},{97:97}],93:[function(e,t,n){"use strict";function r(e,t,n){this.dispatchConfig=e,this.dispatchMarker=t,this.nativeEvent=n;var r=this.constructor.Interface;for(var o in r)if(r.hasOwnProperty(o)){var i=r[o];i?this[o]=i(n):this[o]=n[o]}var u=null!=n.defaultPrevented?n.defaultPrevented:n.returnValue===!1;u?this.isDefaultPrevented=a.thatReturnsTrue:this.isDefaultPrevented=a.thatReturnsFalse,this.isPropagationStopped=a.thatReturnsFalse}var o=e(28),i=e(27),a=e(112),u=e(123),s={type:null,target:u,currentTarget:a.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null};i(r.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e.preventDefault?e.preventDefault():e.returnValue=!1,this.isDefaultPrevented=a.thatReturnsTrue},stopPropagation:function(){var e=this.nativeEvent;e.stopPropagation?e.stopPropagation():e.cancelBubble=!0,this.isPropagationStopped=a.thatReturnsTrue},persist:function(){this.isPersistent=a.thatReturnsTrue},isPersistent:a.thatReturnsFalse,destructor:function(){var e=this.constructor.Interface;for(var t in e)this[t]=null;this.dispatchConfig=null,this.dispatchMarker=null,this.nativeEvent=null}}),r.Interface=s,r.augmentClass=function(e,t){var n=this,r=Object.create(n.prototype);i(r,e.prototype),e.prototype=r,e.prototype.constructor=e,e.Interface=i({},n.Interface,t),e.augmentClass=n.augmentClass,o.addPoolingTo(e,o.threeArgumentPooler)},o.addPoolingTo(r,o.threeArgumentPooler),t.exports=r},{112:112,123:123,27:27,28:28}],94:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(99),i={relatedTarget:null};o.augmentClass(r,i),t.exports=r},{99:99}],95:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(93),i={data:null};o.augmentClass(r,i),t.exports=r},{93:93}],96:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(99),i=e(120),a=e(121),u=e(122),s={key:a,location:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,repeat:null,locale:null,getModifierState:u,charCode:function(e){return"keypress"===e.type?i(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?i(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}};o.augmentClass(r,s),t.exports=r},{120:120,121:121,122:122,99:99}],97:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(99),i=e(102),a=e(122),u={screenX:null,screenY:null,clientX:null,clientY:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,getModifierState:a,button:function(e){var t=e.button;return"which"in e?t:2===t?2:4===t?1:0},buttons:null,relatedTarget:function(e){return e.relatedTarget||(e.fromElement===e.srcElement?e.toElement:e.fromElement)},pageX:function(e){return"pageX"in e?e.pageX:e.clientX+i.currentScrollLeft},pageY:function(e){return"pageY"in e?e.pageY:e.clientY+i.currentScrollTop}};o.augmentClass(r,u),t.exports=r},{102:102,122:122,99:99}],98:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(99),i=e(122),a={touches:null,targetTouches:null,changedTouches:null,altKey:null,metaKey:null,ctrlKey:null,shiftKey:null,getModifierState:i};o.augmentClass(r,a),t.exports=r},{122:122,99:99}],99:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(93),i=e(123),a={view:function(e){if(e.view)return e.view;var t=i(e);if(null!=t&&t.window===t)return t;var n=t.ownerDocument;return n?n.defaultView||n.parentWindow:window},detail:function(e){return e.detail||0}};o.augmentClass(r,a),t.exports=r},{123:123,93:93}],100:[function(e,t,n){"use strict";function r(e,t,n){o.call(this,e,t,n)}var o=e(97),i={deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:null,deltaMode:null};o.augmentClass(r,i),t.exports=r},{97:97}],101:[function(e,t,n){"use strict";var r=e(133),o={reinitializeTransaction:function(){this.transactionWrappers=this.getTransactionWrappers(),this.wrapperInitData?this.wrapperInitData.length=0:this.wrapperInitData=[],this._isInTransaction=!1},_isInTransaction:!1,getTransactionWrappers:null,isInTransaction:function(){return!!this._isInTransaction},perform:function(e,t,n,o,i,a,u,s){r(!this.isInTransaction());var l,c;try{this._isInTransaction=!0,l=!0,this.initializeAll(0),c=e.call(t,n,o,i,a,u,s),l=!1}finally{try{if(l)try{this.closeAll(0)}catch(p){}else this.closeAll(0)}finally{this._isInTransaction=!1}}return c},initializeAll:function(e){for(var t=this.transactionWrappers,n=e;n<t.length;n++){var r=t[n];try{this.wrapperInitData[n]=i.OBSERVED_ERROR,this.wrapperInitData[n]=r.initialize?r.initialize.call(this):null}finally{if(this.wrapperInitData[n]===i.OBSERVED_ERROR)try{this.initializeAll(n+1)}catch(o){}}}},closeAll:function(e){r(this.isInTransaction());for(var t=this.transactionWrappers,n=e;n<t.length;n++){var o,a=t[n],u=this.wrapperInitData[n];try{o=!0,u!==i.OBSERVED_ERROR&&a.close&&a.close.call(this,u),o=!1}finally{if(o)try{this.closeAll(n+1)}catch(s){}}}this.wrapperInitData.length=0}},i={Mixin:o,OBSERVED_ERROR:{}};t.exports=i},{133:133}],102:[function(e,t,n){"use strict";var r={currentScrollLeft:0,currentScrollTop:0,refreshScrollValues:function(e){r.currentScrollLeft=e.x,r.currentScrollTop=e.y}};t.exports=r},{}],103:[function(e,t,n){"use strict";function r(e,t){if(o(null!=t),null==e)return t;var n=Array.isArray(e),r=Array.isArray(t);return n&&r?(e.push.apply(e,t),e):n?(e.push(t),e):r?[e].concat(t):[e,t]}var o=e(133);t.exports=r},{133:133}],104:[function(e,t,n){"use strict";function r(e){for(var t=1,n=0,r=0;r<e.length;r++)t=(t+e.charCodeAt(r))%o,n=(n+t)%o;return t|n<<16}var o=65521;t.exports=r},{}],105:[function(e,t,n){function r(e){return e.replace(o,function(e,t){return t.toUpperCase()})}var o=/-(.)/g;t.exports=r},{}],106:[function(e,t,n){"use strict";function r(e){return o(e.replace(i,"ms-"))}var o=e(105),i=/^-ms-/;t.exports=r},{105:105}],107:[function(e,t,n){function r(e,t){return e&&t?e===t?!0:o(e)?!1:o(t)?r(e,t.parentNode):e.contains?e.contains(t):e.compareDocumentPosition?!!(16&e.compareDocumentPosition(t)):!1:!1}var o=e(137);t.exports=r},{137:137}],108:[function(e,t,n){function r(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"length"in e&&!("setInterval"in e)&&"number"!=typeof e.nodeType&&(Array.isArray(e)||"callee"in e||"item"in e)}function o(e){return r(e)?Array.isArray(e)?e.slice():i(e):[e]}var i=e(148);t.exports=o},{148:148}],109:[function(e,t,n){"use strict";function r(e){var t=i.createFactory(e),n=o.createClass({tagName:e.toUpperCase(),displayName:"ReactFullPageComponent"+e,componentWillUnmount:function(){a(!1)},render:function(){return t(this.props)}});return n}var o=e(33),i=e(55),a=e(133);t.exports=r},{133:133,33:33,55:55}],110:[function(e,t,n){function r(e){var t=e.match(c);return t&&t[1].toLowerCase()}function o(e,t){var n=l;s(!!l);var o=r(e),i=o&&u(o);if(i){n.innerHTML=i[1]+e+i[2];for(var c=i[0];c--;)n=n.lastChild}else n.innerHTML=e;var p=n.getElementsByTagName("script");p.length&&(s(t),a(p).forEach(t));for(var d=a(n.childNodes);n.lastChild;)n.removeChild(n.lastChild);return d}var i=e(21),a=e(108),u=e(125),s=e(133),l=i.canUseDOM?document.createElement("div"):null,c=/^\s*<(\w+)/;t.exports=o},{108:108,125:125,133:133,21:21}],111:[function(e,t,n){"use strict";function r(e,t){var n=null==t||"boolean"==typeof t||""===t;if(n)return"";var r=isNaN(t);return r||0===t||i.hasOwnProperty(e)&&i[e]?""+t:("string"==typeof t&&(t=t.trim()),t+"px")}var o=e(4),i=o.isUnitlessNumber;t.exports=r},{4:4}],112:[function(e,t,n){function r(e){return function(){return e}}function o(){}o.thatReturns=r,o.thatReturnsFalse=r(!1),o.thatReturnsTrue=r(!0),o.thatReturnsNull=r(null),o.thatReturnsThis=function(){return this},o.thatReturnsArgument=function(e){return e},t.exports=o},{}],113:[function(e,t,n){"use strict";var r={};t.exports=r},{}],114:[function(e,t,n){"use strict";function r(e){return i[e]}function o(e){return(""+e).replace(a,r)}var i={"&":"&amp;",">":"&gt;","<":"&lt;",'"':"&quot;","'":"&#x27;"},a=/[&><"']/g;t.exports=o},{}],115:[function(e,t,n){"use strict";function r(e){return null==e?null:u(e)?e:o.has(e)?i.getNodeFromInstance(e):(a(null==e.render||"function"!=typeof e.render),void a(!1))}{var o=(e(39),e(65)),i=e(68),a=e(133),u=e(135);e(150)}t.exports=r},{133:133,135:135,150:150,39:39,65:65,68:68}],116:[function(e,t,n){"use strict";function r(e,t,n){var r=e,o=!r.hasOwnProperty(n);o&&null!=t&&(r[n]=t)}function o(e){if(null==e)return e;var t={};return i(e,r,t),t}{var i=e(149);e(150)}t.exports=o},{149:149,150:150}],117:[function(e,t,n){"use strict";function r(e){try{e.focus()}catch(t){}}t.exports=r},{}],118:[function(e,t,n){"use strict";var r=function(e,t,n){Array.isArray(e)?e.forEach(t,n):e&&t.call(n,e)};t.exports=r},{}],119:[function(e,t,n){function r(){try{return document.activeElement||document.body}catch(e){return document.body}}t.exports=r},{}],120:[function(e,t,n){"use strict";function r(e){var t,n=e.keyCode;return"charCode"in e?(t=e.charCode,0===t&&13===n&&(t=13)):t=n,t>=32||13===t?t:0}t.exports=r},{}],121:[function(e,t,n){"use strict";function r(e){if(e.key){var t=i[e.key]||e.key;if("Unidentified"!==t)return t}if("keypress"===e.type){var n=o(e);return 13===n?"Enter":String.fromCharCode(n)}return"keydown"===e.type||"keyup"===e.type?a[e.keyCode]||"Unidentified":""}var o=e(120),i={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},a={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"};t.exports=r},{120:120}],122:[function(e,t,n){"use strict";function r(e){var t=this,n=t.nativeEvent;if(n.getModifierState)return n.getModifierState(e);var r=i[e];return r?!!n[r]:!1}function o(e){return r}var i={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};t.exports=o},{}],123:[function(e,t,n){"use strict";function r(e){var t=e.target||e.srcElement||window;return 3===t.nodeType?t.parentNode:t}t.exports=r},{}],124:[function(e,t,n){"use strict";function r(e){var t=e&&(o&&e[o]||e[i]);return"function"==typeof t?t:void 0}var o="function"==typeof Symbol&&Symbol.iterator,i="@@iterator";t.exports=r},{}],125:[function(e,t,n){function r(e){return i(!!a),d.hasOwnProperty(e)||(e="*"),u.hasOwnProperty(e)||("*"===e?a.innerHTML="<link />":a.innerHTML="<"+e+"></"+e+">",u[e]=!a.firstChild),u[e]?d[e]:null}var o=e(21),i=e(133),a=o.canUseDOM?document.createElement("div"):null,u={circle:!0,defs:!0,ellipse:!0,g:!0,line:!0,linearGradient:!0,path:!0,polygon:!0,polyline:!0,radialGradient:!0,rect:!0,stop:!0,text:!0},s=[1,'<select multiple="true">',"</select>"],l=[1,"<table>","</table>"],c=[3,"<table><tbody><tr>","</tr></tbody></table>"],p=[1,"<svg>","</svg>"],d={"*":[1,"?<div>","</div>"],area:[1,"<map>","</map>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],legend:[1,"<fieldset>","</fieldset>"],param:[1,"<object>","</object>"],tr:[2,"<table><tbody>","</tbody></table>"],optgroup:s,option:s,caption:l,colgroup:l,tbody:l,tfoot:l,thead:l,td:c,th:c,circle:p,defs:p,ellipse:p,g:p,line:p,linearGradient:p,path:p,polygon:p,polyline:p,radialGradient:p,rect:p,stop:p,text:p};t.exports=r},{133:133,21:21}],126:[function(e,t,n){"use strict";function r(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function o(e){for(;e;){if(e.nextSibling)return e.nextSibling;e=e.parentNode}}function i(e,t){for(var n=r(e),i=0,a=0;n;){if(3===n.nodeType){if(a=i+n.textContent.length,t>=i&&a>=t)return{node:n,offset:t-i};i=a}n=r(o(n))}}t.exports=i},{}],127:[function(e,t,n){"use strict";function r(e){return e?e.nodeType===o?e.documentElement:e.firstChild:null}var o=9;t.exports=r},{}],128:[function(e,t,n){"use strict";function r(){return!i&&o.canUseDOM&&(i="textContent"in document.documentElement?"textContent":"innerText"),i}var o=e(21),i=null;t.exports=r},{21:21}],129:[function(e,t,n){"use strict";function r(e){return e===window?{x:window.pageXOffset||document.documentElement.scrollLeft,y:window.pageYOffset||document.documentElement.scrollTop}:{x:e.scrollLeft,y:e.scrollTop}}t.exports=r},{}],130:[function(e,t,n){function r(e){return e.replace(o,"-$1").toLowerCase()}var o=/([A-Z])/g;t.exports=r},{}],131:[function(e,t,n){"use strict";function r(e){return o(e).replace(i,"-ms-")}var o=e(130),i=/^ms-/;t.exports=r},{130:130}],132:[function(e,t,n){"use strict";function r(e){return"function"==typeof e&&"undefined"!=typeof e.prototype&&"function"==typeof e.prototype.mountComponent&&"function"==typeof e.prototype.receiveComponent}function o(e,t){var n;if((null===e||e===!1)&&(e=a.emptyElement),"object"==typeof e){var o=e;n=t===o.type&&"string"==typeof o.type?u.createInternalComponent(o):r(o.type)?new o.type(o):new c}else"string"==typeof e||"number"==typeof e?n=u.createInstanceForText(e):l(!1);return n.construct(e),n._mountIndex=0,n._mountImage=null,n}var i=e(37),a=e(57),u=e(71),s=e(27),l=e(133),c=(e(150),function(){});s(c.prototype,i.Mixin,{_instantiateReactComponent:o}),t.exports=o},{133:133,150:150,27:27,37:37,57:57,71:71}],133:[function(e,t,n){"use strict";var r=function(e,t,n,r,o,i,a,u){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,i,a,u],c=0;s=new Error("Invariant Violation: "+t.replace(/%s/g,function(){return l[c++]}))}throw s.framesToPop=1,s}};t.exports=r},{}],134:[function(e,t,n){"use strict";function r(e,t){if(!i.canUseDOM||t&&!("addEventListener"in document))return!1;var n="on"+e,r=n in document;if(!r){var a=document.createElement("div");a.setAttribute(n,"return;"),r="function"==typeof a[n]}return!r&&o&&"wheel"===e&&(r=document.implementation.hasFeature("Events.wheel","3.0")),r}var o,i=e(21);i.canUseDOM&&(o=document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("","")!==!0),t.exports=r},{21:21}],135:[function(e,t,n){function r(e){return!(!e||!("function"==typeof Node?e instanceof Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName))}t.exports=r},{}],136:[function(e,t,n){"use strict";function r(e){return e&&("INPUT"===e.nodeName&&o[e.type]||"TEXTAREA"===e.nodeName)}var o={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};t.exports=r},{}],137:[function(e,t,n){function r(e){return o(e)&&3==e.nodeType}var o=e(135);t.exports=r},{135:135}],138:[function(e,t,n){"use strict";var r=e(133),o=function(e){var t,n={};r(e instanceof Object&&!Array.isArray(e));for(t in e)e.hasOwnProperty(t)&&(n[t]=t);return n};t.exports=o},{133:133}],139:[function(e,t,n){var r=function(e){var t;for(t in e)if(e.hasOwnProperty(t))return t;return null};t.exports=r},{}],140:[function(e,t,n){"use strict";function r(e,t,n){if(!e)return null;var r={};for(var i in e)o.call(e,i)&&(r[i]=t.call(n,e[i],i,e));return r}var o=Object.prototype.hasOwnProperty;t.exports=r},{}],141:[function(e,t,n){"use strict";function r(e){var t={};return function(n){return t.hasOwnProperty(n)||(t[n]=e.call(this,n)),t[n]}}t.exports=r},{}],142:[function(e,t,n){"use strict";function r(e){return i(o.isValidElement(e)),e}var o=e(55),i=e(133);t.exports=r},{133:133,55:55}],143:[function(e,t,n){"use strict";function r(e){return'"'+o(e)+'"'}var o=e(114);t.exports=r},{114:114}],144:[function(e,t,n){"use strict";var r=e(21),o=/^[ \r\n\t\f]/,i=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,a=function(e,t){e.innerHTML=t};if("undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction&&(a=function(e,t){MSApp.execUnsafeLocalFunction(function(){e.innerHTML=t})}),r.canUseDOM){var u=document.createElement("div");u.innerHTML=" ",""===u.innerHTML&&(a=function(e,t){if(e.parentNode&&e.parentNode.replaceChild(e,e),o.test(t)||"<"===t[0]&&i.test(t)){e.innerHTML="\ufeff"+t;var n=e.firstChild;1===n.data.length?e.removeChild(n):n.deleteData(0,1)}else e.innerHTML=t})}t.exports=a},{21:21}],145:[function(e,t,n){"use strict";var r=e(21),o=e(114),i=e(144),a=function(e,t){e.textContent=t};r.canUseDOM&&("textContent"in document.documentElement||(a=function(e,t){i(e,o(t))})),t.exports=a},{114:114,144:144,21:21}],146:[function(e,t,n){"use strict";function r(e,t){if(e===t)return!0;var n;for(n in e)if(e.hasOwnProperty(n)&&(!t.hasOwnProperty(n)||e[n]!==t[n]))return!1;for(n in t)if(t.hasOwnProperty(n)&&!e.hasOwnProperty(n))return!1;return!0}t.exports=r},{}],147:[function(e,t,n){"use strict";function r(e,t){if(null!=e&&null!=t){var n=typeof e,r=typeof t;if("string"===n||"number"===n)return"string"===r||"number"===r;if("object"===r&&e.type===t.type&&e.key===t.key){var o=e._owner===t._owner;return o}}return!1}e(150);t.exports=r},{150:150}],148:[function(e,t,n){function r(e){var t=e.length;if(o(!Array.isArray(e)&&("object"==typeof e||"function"==typeof e)),o("number"==typeof t),o(0===t||t-1 in e),e.hasOwnProperty)try{return Array.prototype.slice.call(e)}catch(n){}for(var r=Array(t),i=0;t>i;i++)r[i]=e[i];return r}var o=e(133);t.exports=r},{133:133}],149:[function(e,t,n){"use strict";function r(e){return v[e]}function o(e,t){return e&&null!=e.key?a(e.key):t.toString(36)}function i(e){return(""+e).replace(g,r)}function a(e){return"$"+i(e)}function u(e,t,n,r,i){var s=typeof e;if(("undefined"===s||"boolean"===s)&&(e=null),null===e||"string"===s||"number"===s||l.isValidElement(e))return r(i,e,""===t?h+o(e,0):t,n),1;var p,v,g,y=0;if(Array.isArray(e))for(var C=0;C<e.length;C++)p=e[C],v=(""!==t?t+m:h)+o(p,C),g=n+y,y+=u(p,v,g,r,i);else{var E=d(e);if(E){var b,_=E.call(e);if(E!==e.entries)for(var x=0;!(b=_.next()).done;)p=b.value,v=(""!==t?t+m:h)+o(p,x++),g=n+y,y+=u(p,v,g,r,i);else for(;!(b=_.next()).done;){var D=b.value;D&&(p=D[1],v=(""!==t?t+m:h)+a(D[0])+m+o(p,0),g=n+y,y+=u(p,v,g,r,i))}}else if("object"===s){f(1!==e.nodeType);var M=c.extract(e);for(var N in M)M.hasOwnProperty(N)&&(p=M[N],v=(""!==t?t+m:h)+a(N)+m+o(p,0),g=n+y,y+=u(p,v,g,r,i))}}return y}function s(e,t,n){return null==e?0:u(e,"",0,t,n)}var l=e(55),c=e(61),p=e(64),d=e(124),f=e(133),h=(e(150),p.SEPARATOR),m=":",v={"=":"=0",".":"=1",":":"=2"},g=/[=.:]/g;t.exports=s},{124:124,133:133,150:150,55:55,61:61,64:64}],150:[function(e,t,n){"use strict";var r=e(112),o=r;t.exports=o},{112:112}]},{},[1])(1)}); \ No newline at end of file
diff --git a/ext/installfiles/mac/ui/simpleajax.min.js b/ext/installfiles/mac/ui/simpleajax.min.js
deleted file mode 100644
index bd15dbdd..00000000
--- a/ext/installfiles/mac/ui/simpleajax.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/** SimpleAjax v1.0.1 - MIT license - https://github.com/freelancephp/SimpleAjax */
-(function(window){var SimpleAjax=window.SimpleAjax={xhr:null,settings:{url:"",type:"GET",dataType:"text",async:true,cache:true,data:null,contentType:"application/x-www-form-urlencoded",success:null,error:null,complete:null,accepts:{text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"}},call:function(a){var b=this,c=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP"),d=function(a,b){var c={};for(var d in a)c[d]=typeof b[d]=="undefined"?a[d]:b[d];return c}(this.settings,a),e=function(){if(c.readyState==4){if(c.status>=200&&c.status<300||c.status===304){var a=d.dataType=="xml"?c.responseXML:c.responseText;if(d.dataType=="json")a=b.parseJSON(a);if(b.isFunction(d.success))d.success.call(d,a,c.status,c)}else{if(b.isFunction(d.error))d.error.call(d,c,c.status)}if(b.isFunction(d.complete))d.complete.call(d,c,c.status)}};this.xhr=c;if(!d.cache)d.url+=(d.url.indexOf("?")>-1?"&":"?")+"_nocache="+(new Date).getTime();if(d.data){if(d.type=="GET"){d.url+=(d.url.indexOf("?")>-1?"&":"?")+this.param(d.data);d.data=null}else{d.data=this.param(d.data)}}c.open(d.type,d.url,d.async);c.setRequestHeader("Content-type",d.contentType);if(d.dataType&&d.accepts[d.dataType])c.setRequestHeader("Accept",d.accepts[d.dataType]);if(d.async){c.onreadystatechange=e;c.send(d.data)}else{c.send(d.data);e()}return this},get:function(a,b,c){if(this.isFunction(b)){c=b;b=null}return this.call({url:a,type:"GET",data:b,success:c})},post:function(a,b,c){if(this.isFunction(b)){c=b;b=null}return this.call({url:a,type:"POST",data:b,success:c})},load:function(a,b,c,d){if(typeof a=="string")a=document.getElementById(a);return this.call({url:b,type:c?"POST":"GET",data:c||null,complete:d||null,success:function(b){try{a.innerHTML=b}catch(c){var d=document.createElement("div");d.innerHTML=b;while(a.firstChild)a.removeChild(a.firstChild);for(var e=0,f=d.childNodes.length;e<f;e++)a.appendChild(d.childNodes[e])}}})},param:function(a){var b=[];for(var c in a){b.push(encodeURIComponent(c)+"="+encodeURIComponent(a[c]))}return b.join("&")},parseJSON:function(data){if(typeof data!=="string"||!data)return null;return eval("("+this.trim(data)+")")},trim:function(a){return a.replace(/^\s+/,"").replace(/\s+$/,"")},isFunction:function(a){return Object.prototype.toString.call(a)==="[object Function]"}};if(!window.Ajax){window.Ajax=SimpleAjax}})(window) \ No newline at end of file
diff --git a/ext/installfiles/mac/ui/zerotier.css b/ext/installfiles/mac/ui/zerotier.css
deleted file mode 100644
index 9f72024a..00000000
--- a/ext/installfiles/mac/ui/zerotier.css
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Dark blue-grey: #234447
- * Light blue-grey: #91a2a3
- * Light yellow: #ffffcc
- * Orange: #ffb354 */
-
-html,body {
- font-family: "Helvetica Neue","Lucida Sans Unicode",sans-serif;
- font-size: 12pt;
- margin: 0;
- padding: 0;
- width: 100%;
- height: 100%;
- overflow: hidden;
-}
-
-.zeroTierAddress {
- font-family: monospace;
-}
-
-.zeroTierNode {
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- display: table;
-}
-
-.zeroTierNode > .middle {
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- overflow: hidden;
- display: table-row;
-}
-.zeroTierNode > .middle > .middleCell {
- width: 100%;
- height: 100%;
- display: table-cell;
- border-bottom: 1px solid #cfcfcf;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll {
- display: block;
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- overflow: scroll;
- overflow-x: hidden;
- overflow-y: scroll;
- background: #dddddd;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .networks {
- display: block;
- width: 100%;
- padding: 0 0 0.25rem 0;
- margin: 0;
- border: 0;
- text-align: left;
- border-collapse: collapse;
-}
-.zeroTierNode > .middle > .middleCell > .middleScroll > .networks > .network {
- display: block;
- border-top: 0.12rem solid #dddddd;
- border-bottom: 0.12rem solid #dddddd;
- padding: 0.25rem;
- background: #ffffff;
-}
-
-.zeroTierNode > .bottom {
- font-size: 12pt;
- width: 100%;
- overflow: hidden;
- display: table-row;
- color: #000000;
- background: #dfdfdf;
-}
-.zeroTierNode > .bottom > .left {
- text-align: left;
- white-space: nowrap;
- float: left;
- padding: 0 0 0 0.5rem;
- font-size: 12pt;
- height: 100%;
-}
-.zeroTierNode > .bottom > .left > .statusLine {
- font-family: monospace;
- white-space: nowrap;
- font-size: 11pt;
- height: 100%;
-}
-.zeroTierNode > .bottom > .right {
- text-align: right;
- height: 100%;
- white-space: nowrap;
- float: right;
- font-size: 12pt;
- background: #ffffff;
-}
-.zeroTierNode > .bottom > .right form {
- height: 100%;
-}
-.zeroTierNode > .bottom > .right input {
- font-family: monospace;
- font-size: 12pt;
- background: #ffffff;
- color: #000000;
- outline: none;
- outline-style: none;
- box-shadow: 0;
- border: 0;
- margin: 0;
- padding: 0 0.25rem 0 0.25rem;
- display: inline;
- height: 100%;
-}
-.zeroTierNode > .bottom > .right button {
- display: inline-block;
- font-size: 12pt;
- background: #ffb354;
- border: 1px solid #ffb354;
- color: #000000;
- margin: 0;
- padding: 0.05rem 0.75rem 0.05rem 0.75rem;
- outline: none;
- outline-style: none;
- height: 100%;
-}
-.zeroTierNode > .bottom > .right button:hover {
- cursor: pointer;
- outline: none;
- outline-style: none;
- border: 1px solid #000000;
-}
-
-.zeroTierNetwork {
- padding: 0;
- margin: 0;
- display: inline-block;
- text-align: right;
- width: 100%;
- position: relative;
-}
-.zeroTierNetwork .networkInfo {
- padding: 0 0 0.25rem 0;
- text-align: left;
- font-size: 12pt;
-}
-.zeroTierNetwork .networkInfo .networkId {
- font-size: 11pt;
- font-family: monospace;
- color: #000000;
-}
-.zeroTierNetwork .networkInfo .networkName {
- padding: 0 0 0 1rem;
- float: right;
- font-size: 12pt;
-}
-.zeroTierNetwork .networkProps {
- width: 100%;
- display: table;
- padding: 0;
- margin: 0 auto 0 auto;
- border-top: 1px solid #999999;
- border-bottom: 1px solid #999999;
-}
-.zeroTierNetwork .networkProps > .row {
- display: table-row;
-}
-.zeroTierNetwork .networkProps > .row > .name {
- display: table-cell;
- font-size: 10pt;
- padding: 0.1rem 0.5rem 0.1rem 0.5rem;
-}
-.zeroTierNetwork .networkProps > .row > .value {
- font-size: 10pt;
- display: table-cell;
- padding: 0.1rem 0.5rem 0.1rem 0.5rem;
- background: #eeeeee;
-}
-.zeroTierNetwork .ipList {
-}
-.zeroTierNetwork .ipAddress {
- font-family: monospace;
- font-size: 10pt;
-}
-.zeroTierNetwork .leaveNetworkButton {
- padding: 0.25rem 0.5rem 0.25rem 0.5rem;
- margin: 0.25rem 0 0 0;
- font-size: 9pt;
- background: #ffffff;
- outline: none;
- background: #ffb354;
- border: 1px solid #ffb354;
- cursor: pointer;
-}
-.zeroTierNetwork .leaveNetworkButton:hover {
- border: 1px solid #000000;
-}
diff --git a/ext/installfiles/mac/ui/ztui.min.js b/ext/installfiles/mac/ui/ztui.min.js
deleted file mode 100644
index 17982839..00000000
--- a/ext/installfiles/mac/ui/ztui.min.js
+++ /dev/null
@@ -1 +0,0 @@
-var ZeroTierNetwork=React.createClass({displayName:"ZeroTierNetwork",getInitialState:function(){return{}},leaveNetwork:function(e){Ajax.call({url:"network/"+this.props.nwid+"?auth="+this.props.authToken,cache:!1,type:"DELETE",success:function(e){this.props.onNetworkDeleted&&this.props.onNetworkDeleted(this.props.nwid)}.bind(this),error:function(e){}.bind(this)}),e.preventDefault()},render:function(){return React.createElement("div",{className:"zeroTierNetwork"},React.createElement("div",{className:"networkInfo"},React.createElement("span",{className:"networkId"},this.props.nwid)," ",React.createElement("span",{className:"networkName"},this.props.name)),React.createElement("div",{className:"networkProps"},React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Status"),React.createElement("div",{className:"value"},this.props.status)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Type"),React.createElement("div",{className:"value"},this.props.type)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MAC"),React.createElement("div",{className:"value zeroTierAddress"},this.props.mac)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"MTU"),React.createElement("div",{className:"value"},this.props.mtu)),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Broadcast"),React.createElement("div",{className:"value"},this.props.broadcastEnabled?"ENABLED":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Bridging"),React.createElement("div",{className:"value"},this.props.bridge?"ACTIVE":"DISABLED")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Device"),React.createElement("div",{className:"value"},this.props.portDeviceName?this.props.portDeviceName:"(none)")),React.createElement("div",{className:"row"},React.createElement("div",{className:"name"},"Managed IPs"),React.createElement("div",{className:"value ipList"},this.props.assignedAddresses.map(function(e){return React.createElement("div",{key:e,className:"ipAddress"},e)})))),React.createElement("button",{type:"button",className:"leaveNetworkButton",onClick:this.leaveNetwork},"Leave Network"))}}); var ZeroTierNode=React.createClass({displayName:"ZeroTierNode",getInitialState:function(){return{address:"----------",online:!1,version:"_._._",_networks:[],_peers:[]}},ago:function(e){if(e>0){var t=Math.round((Date.now()-e)/1e3);return t>0?t:0}return 0},updatePeers:function(){Ajax.call({url:"peer?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_peers:t})}}.bind(this),error:function(){}.bind(this)})},updateNetworks:function(){Ajax.call({url:"network?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(e){var t=JSON.parse(e);Array.isArray(t)&&this.setState({_networks:t})}}.bind(this),error:function(){}.bind(this)})},updateAll:function(){Ajax.call({url:"status?auth="+this.props.authToken,cache:!1,type:"GET",success:function(e){if(this.alertedToFailure=!1,e){var t=JSON.parse(e);this.setState(t),document.title="ZeroTier One ["+t.address+"]"}this.updateNetworks(),this.updatePeers()}.bind(this),error:function(){this.setState(this.getInitialState()),this.alertedToFailure||(this.alertedToFailure=!0,alert("Authorization token invalid or ZeroTier One service not running."))}.bind(this)})},joinNetwork:function(e){e.preventDefault(),this.networkToJoin&&16===this.networkToJoin.length?Ajax.call({url:"network/"+this.networkToJoin+"?auth="+this.props.authToken,cache:!1,type:"POST",success:function(e){this.networkToJoin="",this.networkInputElement&&(this.networkInputElement.value=""),this.updateNetworks()}.bind(this),error:function(){}.bind(this)}):alert("To join a network, enter its 16-digit network ID.")},handleNetworkIdEntry:function(e){this.networkInputElement=e.target;var t=this.networkInputElement.value;if(t){t=t.toLowerCase();for(var n="",a=0;a<t.length&&16>a;++a)"0123456789abcdef".indexOf(t.charAt(a))>=0&&(n+=t.charAt(a));this.networkToJoin=n,this.networkInputElement.value=n}else this.networkToJoin="",this.networkInputElement.value=""},handleNetworkDelete:function(e){for(var t=[],n=0;n<this.state._networks.length;++n)this.state._networks[n].nwid!==e&&t.push(this.state._networks[n]);this.setState({_networks:t})},componentDidMount:function(){this.updateAll(),this.updateIntervalId=setInterval(this.updateAll,2500)},componentWillUnmount:function(){clearInterval(this.updateIntervalId)},render:function(){return React.createElement("div",{className:"zeroTierNode"},React.createElement("div",{className:"middle"},React.createElement("div",{className:"middleCell"},React.createElement("div",{className:"middleScroll"},React.createElement("div",{className:"networks",key:"_networks"},this.state._networks.map(function(e){return e.authToken=this.props.authToken,e.onNetworkDeleted=this.handleNetworkDelete,React.createElement("div",{className:"network",key:e.nwid},React.createElement(ZeroTierNetwork,e))}.bind(this)))))),React.createElement("div",{className:"bottom"},React.createElement("div",{className:"left"},React.createElement("span",{className:"statusLine"},React.createElement("span",{className:"zeroTierAddress"},this.state.address),"  ",this.state.online?this.state.tcpFallbackActive?"TUNNELED":"ONLINE":"OFFLINE","  ",this.state.version)),React.createElement("div",{className:"right"},React.createElement("form",{onSubmit:this.joinNetwork},React.createElement("input",{type:"text",maxlength:"16",placeholder:"[ Network ID ]",onChange:this.handleNetworkIdEntry,size:"16"}),React.createElement("button",{type:"button",onClick:this.joinNetwork},"Join")))))}});
diff --git a/ext/installfiles/mac/uninstall.sh b/ext/installfiles/mac/uninstall.sh
index d1effb93..9bf5d6fc 100755
--- a/ext/installfiles/mac/uninstall.sh
+++ b/ext/installfiles/mac/uninstall.sh
@@ -28,13 +28,11 @@ echo "Removing ZeroTier One files..."
rm -rf '/Applications/ZeroTier One.app'
rm -f '/usr/bin/zerotier-one' '/usr/bin/zerotier-idtool' '/usr/bin/zerotier-cli' '/Library/LaunchDaemons/com.zerotier.one.plist'
-mkdir -p /tmp/ZeroTierOne_uninstall_tmp
-cp "/Library/Application Support/ZeroTier/One/*.secret" /tmp/ZeroTierOne_uninstall_tmp
-rm -rf '/Library/Application Support/ZeroTier/One'
-mkdir -p '/Library/Application Support/ZeroTier/One'
-cp "/tmp/ZeroTierOne_uninstall_tmp/*.secret" '/Library/Application Support/ZeroTier/One'
-chmod 0600 "/Library/Application Support/ZeroTier/One/*.secret"
-rm -rf /tmp/ZeroTierOne_uninstall_tmp
+
+cd '/Library/Application Support/ZeroTier/One'
+if [ "`pwd`" = '/Library/Application Support/ZeroTier/One' ]; then
+ rm -rf *.d *.sh *.log *.old *.kext *.conf *.pkg *.dmg *.pid *.port *.save *.bin planet zerotier-* devicemap
+fi
echo 'Uninstall complete.'
echo
diff --git a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip
index a10cb1e5..7ff1a05e 100644
--- a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip
+++ b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x64).aip
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<DOCUMENT Type="Advanced Installer" CreateVersion="12.0" version="12.3.1" Modules="enterprise" RootPath="." Language="en" Id="{4070644B-EC9F-4962-B14A-770B9E309DC3}">
+<DOCUMENT Type="Advanced Installer" CreateVersion="12.0" version="14.5.2" Modules="enterprise" RootPath="." Language="en" Id="{4070644B-EC9F-4962-B14A-770B9E309DC3}">
<COMPONENT cid="caphyon.advinst.msicomp.ProjectOptionsComponent">
- <ROW Name="HiddenItems" Value="UpdaterComponent;SerValComponent;AutorunComponent;MultipleInstancesComponent;MsiJavaComponent;MsiRegsComponent;MsiExtComponent;MsiAssemblyComponent;MsiServInstComponent;AnalyticsComponent;ActSyncAppComponent;MsiMergeModsComponent;MsiThemeComponent;BackgroundImagesComponent;DictionaryComponent;MsiEnvComponent;ScheduledTasksComponent;CPLAppletComponent;GameUxComponent;FirewallExceptionComponent;UserAccountsComponent;MsiClassComponent;WebApplicationsComponent;MsiOdbcDataSrcComponent;SqlConnectionComponent;SharePointSlnComponent;SilverlightSlnComponent;MsiAppSearchComponent"/>
+ <ROW Name="HiddenItems" Value="UpdaterComponent;SerValComponent;AutorunComponent;MultipleInstancesComponent;MsiJavaComponent;MsiRegsComponent;MsiExtComponent;MsiAssemblyComponent;MsiServInstComponent;AnalyticsComponent;ActSyncAppComponent;MsiMergeModsComponent;MsiThemeComponent;BackgroundImagesComponent;DictionaryComponent;MsiEnvComponent;ScheduledTasksComponent;CPLAppletComponent;GameUxComponent;FirewallExceptionComponent;UserAccountsComponent;MsiClassComponent;WebApplicationsComponent;MsiOdbcDataSrcComponent;SqlConnectionComponent;SharePointSlnComponent;SilverlightSlnComponent;MsiAppSearchComponent;AppXAppDetailsComponent;AppXCapabilitiesComponent;AppXDependenciesComponent;AppXProductDetailsComponent;AppXVisualAssetsComponent;AppXAppDeclarationsComponent;AppXUriRulesComponent"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
@@ -15,50 +15,67 @@
<ROW Property="LIMITUI" MultiBuildValue="DefaultBuild:1"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
<ROW Property="Manufacturer" Value="ZeroTier"/>
- <ROW Property="ProductCode" Value="1033:{D7093B7A-71BA-484B-A27C-59ACDAD2206F} " Type="16"/>
+ <ROW Property="ProductCode" Value="1033:{4AFE4740-C680-40FE-B6B0-0C15EB0176F1} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="ZeroTier One Virtual Network Port"/>
<ROW Property="ProductVersion" Value="1.0.0" Type="32"/>
+ <ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{88AA80DE-14CA-4443-B024-6EC13F3EDDAD}"/>
<ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows 2000, Windows 2000 Service Pack 1, Windows 2000 Service Pack 2, Windows 2000 Service Pack 3, Windows 2000 Service Pack 4, Windows XP x86, Windows XP x86 Service Pack 1, Windows XP x86 Service Pack 2, Windows XP x86 Service Pack 3, Windows Server 2003 x86, Windows Server 2003 x86 Service Pack 1, Windows Server 2003 x86 Service Pack 2" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows XP SP3 x86, Windows Server 2003 SP2 x86" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40Display" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP x64, Windows XP x64 Service Pack 1, Windows XP x64 Service Pack 2, Windows Server 2003 x64, Windows Server 2003 x64 Service Pack 1, Windows Server 2003 x64 Service Pack 2" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP x64, Windows Server 2003 x64" ValueLocId="-"/>
- <ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows 2000, Windows XP x86, Windows Server 2003 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT50" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT50Display" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT5X" MultiBuildValue="DefaultBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT5XDisplay" MultiBuildValue="DefaultBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP SP2 x64, Windows Server 2003 SP2 x64" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP SP2 x64, Windows Server 2003 SP2 x64" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows XP SP3 x86, Windows Server 2003 SP2 x86" ValueLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
+ <ROW Directory="TempFolder" Directory_Parent="TARGETDIR" DefaultDir="TEMPFO~1|TempFolder" IsPseudoRoot="1" DirectoryOptions="3"/>
<ROW Directory="zttap300_Dir" Directory_Parent="APPDIR" DefaultDir="zttap300"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="ProductInformation" ComponentId="{FFBF63D7-E03E-4ACA-966A-824C3DF6DEED}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
+ <ROW Component="certutil.exe" ComponentId="{675B9939-A983-4E36-A852-54FB122599B1}" Directory_="zttap300_Dir" Attributes="256" KeyPath="certutil.exe"/>
+ <ROW Component="zttap300.cer" ComponentId="{D72CCDC6-1947-4FE1-9DBA-ECE0A024C1A3}" Directory_="zttap300_Dir" Attributes="0" KeyPath="zttap300.cer" Type="0"/>
+ <ROW Component="zttap300.cer_1" ComponentId="{939B64E0-7725-434B-93FE-B1C30940929E}" Directory_="TempFolder" Attributes="0" KeyPath="zttap300.cer_1" Type="0"/>
<ROW Component="zttap300.inf_2" ComponentId="{CB0C4519-617F-4DB5-9BF5-C6CFC6573F9C}" Directory_="zttap300_Dir" Attributes="256" Condition="VersionNT64" KeyPath="zttap300.inf"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
- <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="ProductInformation"/>
+ <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="ProductInformation certutil.exe zttap300.cer zttap300.cer_1"/>
<ROW Feature="zttap300" Feature_Parent="MainFeature" Title="zttap300" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="zttap300.inf_2"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
- <ROW File="zttap300.cat" Component_="zttap300.inf_2" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.cat" SelfReg="false"/>
+ <ROW File="certutil.exe" Component_="certutil.exe" FileName="certutil.exe" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\certutil.exe" SelfReg="false" NextFile="zttap300.cer_1" DigSign="true"/>
+ <ROW File="zttap300.cat" Component_="zttap300.inf_2" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.cat" SelfReg="false" NextFile="zttap300.cer"/>
+ <ROW File="zttap300.cer" Component_="zttap300.cer" FileName="zttap300.cer" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\zttap300.cer" SelfReg="false" NextFile="certutil.exe"/>
+ <ROW File="zttap300.cer_1" Component_="zttap300.cer_1" FileName="zttap300.cer" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\zttap300.cer" SelfReg="false"/>
<ROW File="zttap300.inf" Component_="zttap300.inf_2" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.inf" SelfReg="false" NextFile="zttap300.sys"/>
<ROW File="zttap300.sys" Component_="zttap300.inf_2" FileName="zttap300.sys" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.sys" SelfReg="false" NextFile="zttap300.cat"/>
</COMPONENT>
+ <COMPONENT cid="caphyon.advinst.custcomp.AiInstallExecuteSequenceAliasComponent">
+ <ROW AliasRowId="certutil.exe" AliasRowOperation="2" Sequence="4001"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent">
+ <ROW BootstrOptKey="GlobalOptions" GeneralOptions="q" DownloadFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\prerequisites"/>
+ </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="1" PackageFolder="..\..\.." PackageFileName="ZeroTierOne_NDIS6_x64" Languages="en" InstallationType="4" UseLargeSchema="true" MsiPackageType="x64"/>
- <ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
<ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DigCertStoreComponent">
- <ROW TimeStampUrl="http://timestamp.verisign.com/scripts/timstamp.dll" SignerDescription="[|ProductName]" SignOptions="7" SignTool="0" Thumbprint="2ad023dc7aa92bf4265b33852a2ed2406d2bee86 Subject: ZeroTier Networks LLC&#10;Issuer: DigiCert High Assurance Code Signing CA-1&#10;Valid from 04/24/2015 to 04/01/2016"/>
+ <ROW TimeStampUrl="http://timestamp.verisign.com/scripts/timstamp.dll" SignerDescription="[|ProductName]" SignOptions="7" SignTool="0" UseSha256="1" Thumbprint="7f01c3746df9e6c8235ea2ae38d3cdfeb185728b Subject: ZeroTier, Inc.&#10;Issuer: DigiCert EV Code Signing CA (SHA2)&#10;Valid from 11/30/2016 to 12/05/2019"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
<ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
@@ -105,10 +122,13 @@
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_DpiContentScale" Type="1" Source="aicustact.dll" Target="DpiContentScale"/>
+ <ROW Action="AI_EnableDebugLog" Type="321" Source="aicustact.dll" Target="EnableDebugLog"/>
<ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
@@ -116,9 +136,10 @@
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFiles64Folder][Manufacturer]\[ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
+ <ROW Action="certutil.exe" Type="3154" Source="certutil.exe" Target="-addstore -f TrustedPublisher [#zttap300.cer_1]"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDriverPackagesComponent">
- <ROW InfFileName="zttap300.inf" Flags="6"/>
+ <ROW InfFileName="zttap300.inf" Flags="15"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="ZeroTierIcon.exe" SourcePath="..\..\..\artwork\ZeroTierIcon.ico" Index="0"/>
@@ -128,19 +149,26 @@
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
<ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1501"/>
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>
- <ROW Action="AI_ResolveKnownFolders" Sequence="51"/>
+ <ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
+ <ROW Action="AI_EnableDebugLog" Sequence="51"/>
+ <ROW Action="certutil.exe" Condition="( NOT Installed )" Sequence="6401"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
- <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
- <ROW Action="AI_DpiContentScale" Sequence="51"/>
+ <ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
+ <ROW Action="AI_DpiContentScale" Sequence="52"/>
+ <ROW Action="AI_EnableDebugLog" Sequence="51"/>
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="101"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
- <ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &gt;= 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 2)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &gt;= 1)))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &lt;&gt; 1)))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &lt;&gt; 2)))) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &gt;= 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 2))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 3))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 4))) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 3))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2) OR (MsiNTProductType = 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 501) OR (ServicePackLevel &lt;&gt; 3)) AND ((VersionNT &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT40Display]" DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="(VersionNT &lt;&gt; 500)" Description="[ProductName] cannot be installed on [WindowsTypeNT50Display]." DescriptionLocId="AI.LaunchCondition.NoNT50" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="(VersionNT64 OR ((VersionNT &lt;&gt; 501) OR (ServicePackLevel = 3))) AND ((VersionNT &lt;&gt; 502) OR (ServicePackLevel = 2))" Description="[ProductName] cannot be installed on [WindowsTypeNT5XDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT5X" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="Privileged" Description="[ProductName] requires administrative privileges to install." DescriptionLocId="AI.LaunchCondition.Privileged" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
diff --git a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip
index 831516d9..ef3d58cc 100644
--- a/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip
+++ b/ext/installfiles/windows/ZeroTier One Virtual Network Port (NDIS6_x86).aip
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<DOCUMENT Type="Advanced Installer" CreateVersion="12.0" version="12.3.1" Modules="enterprise" RootPath="." Language="en" Id="{4070644B-EC9F-4962-B14A-770B9E309DC3}">
+<DOCUMENT Type="Advanced Installer" CreateVersion="12.0" version="14.5.2" Modules="enterprise" RootPath="." Language="en" Id="{4070644B-EC9F-4962-B14A-770B9E309DC3}">
<COMPONENT cid="caphyon.advinst.msicomp.ProjectOptionsComponent">
- <ROW Name="HiddenItems" Value="UpdaterComponent;SerValComponent;AutorunComponent;MultipleInstancesComponent;MsiJavaComponent;MsiRegsComponent;MsiExtComponent;MsiAssemblyComponent;MsiServInstComponent;AnalyticsComponent;ActSyncAppComponent;MsiMergeModsComponent;MsiThemeComponent;BackgroundImagesComponent;DictionaryComponent;MsiEnvComponent;ScheduledTasksComponent;CPLAppletComponent;GameUxComponent;FirewallExceptionComponent;UserAccountsComponent;MsiClassComponent;WebApplicationsComponent;MsiOdbcDataSrcComponent;SqlConnectionComponent;SharePointSlnComponent;SilverlightSlnComponent;MsiAppSearchComponent"/>
+ <ROW Name="HiddenItems" Value="UpdaterComponent;SerValComponent;AutorunComponent;MultipleInstancesComponent;MsiJavaComponent;MsiRegsComponent;MsiExtComponent;MsiAssemblyComponent;MsiServInstComponent;AnalyticsComponent;ActSyncAppComponent;MsiMergeModsComponent;MsiThemeComponent;BackgroundImagesComponent;DictionaryComponent;MsiEnvComponent;ScheduledTasksComponent;CPLAppletComponent;GameUxComponent;FirewallExceptionComponent;UserAccountsComponent;MsiClassComponent;WebApplicationsComponent;MsiOdbcDataSrcComponent;SqlConnectionComponent;SharePointSlnComponent;SilverlightSlnComponent;MsiAppSearchComponent;AppXAppDetailsComponent;AppXCapabilitiesComponent;AppXDependenciesComponent;AppXProductDetailsComponent;AppXVisualAssetsComponent;AppXAppDeclarationsComponent;AppXUriRulesComponent"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
@@ -16,50 +16,67 @@
<ROW Property="LIMITUI" MultiBuildValue="DefaultBuild:1"/>
<ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
<ROW Property="Manufacturer" Value="ZeroTier"/>
- <ROW Property="ProductCode" Value="1033:{6223AB10-D6CD-4580-B357-91CCD7F355D2} " Type="16"/>
+ <ROW Property="ProductCode" Value="1033:{75F0AFE9-A004-428A-89DB-9BB9ACC4489E} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="ZeroTier One Virtual Network Port"/>
<ROW Property="ProductVersion" Value="1.0.0" Type="32"/>
+ <ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
<ROW Property="UpgradeCode" Value="{88AA80DE-14CA-4443-B024-6EC13F3EDDAD}"/>
<ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
<ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows 2000, Windows 2000 Service Pack 1, Windows 2000 Service Pack 2, Windows 2000 Service Pack 3, Windows 2000 Service Pack 4, Windows XP x86, Windows XP x86 Service Pack 1, Windows XP x86 Service Pack 2, Windows XP x86 Service Pack 3, Windows Server 2003 x86, Windows Server 2003 x86 Service Pack 1, Windows Server 2003 x86 Service Pack 2" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows XP SP3 x86, Windows Server 2003 SP2 x86" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
<ROW Property="WindowsTypeNT40Display" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP x64, Windows XP x64 Service Pack 1, Windows XP x64 Service Pack 2, Windows Server 2003 x64, Windows Server 2003 x64 Service Pack 1, Windows Server 2003 x64 Service Pack 2" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP x64, Windows Server 2003 x64" ValueLocId="-"/>
- <ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows 2000, Windows XP x86, Windows Server 2003 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT50" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT50Display" MultiBuildValue="DefaultBuild:Windows 2000" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT5X" MultiBuildValue="DefaultBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT5XDisplay" MultiBuildValue="DefaultBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP SP2 x64, Windows Server 2003 SP2 x64" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP SP2 x64, Windows Server 2003 SP2 x64" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows XP SP3 x86, Windows Server 2003 SP2 x86" ValueLocId="-"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1"/>
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
+ <ROW Directory="TempFolder" Directory_Parent="TARGETDIR" DefaultDir="TEMPFO~1|TempFolder" IsPseudoRoot="1" DirectoryOptions="3"/>
<ROW Directory="zttap300_Dir" Directory_Parent="APPDIR" DefaultDir="zttap300"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="ProductInformation" ComponentId="{FFBF63D7-E03E-4ACA-966A-824C3DF6DEED}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
+ <ROW Component="certutil.exe" ComponentId="{716192EC-038F-4CB7-9E85-689904DFA5A7}" Directory_="zttap300_Dir" Attributes="256" KeyPath="certutil.exe"/>
+ <ROW Component="zttap300.cer" ComponentId="{38822503-75B2-4D81-8F48-76F776CA921D}" Directory_="zttap300_Dir" Attributes="0" KeyPath="zttap300.cer" Type="0"/>
+ <ROW Component="zttap300.cer_1" ComponentId="{E26B4B86-5B0F-45B7-9B07-4AE5D6FF4F13}" Directory_="TempFolder" Attributes="0" KeyPath="zttap300.cer_1" Type="0"/>
<ROW Component="zttap300.inf_1" ComponentId="{07119034-A51F-4871-B503-09D1340FF248}" Directory_="zttap300_Dir" Attributes="0" Condition="(VersionNT &gt;= 500) AND NOT VersionNT64" KeyPath="zttap300.inf"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
- <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="ProductInformation"/>
+ <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="ProductInformation certutil.exe zttap300.cer zttap300.cer_1"/>
<ROW Feature="zttap300" Feature_Parent="MainFeature" Title="zttap300" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="zttap300.inf_1"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
- <ROW File="zttap300.cat" Component_="zttap300.inf_1" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.cat" SelfReg="false"/>
+ <ROW File="certutil.exe" Component_="certutil.exe" FileName="certutil.exe" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\certutil.exe" SelfReg="false" NextFile="zttap300.cer" DigSign="true"/>
+ <ROW File="zttap300.cat" Component_="zttap300.inf_1" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.cat" SelfReg="false" NextFile="certutil.exe"/>
+ <ROW File="zttap300.cer" Component_="zttap300.cer" FileName="zttap300.cer" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\zttap300.cer" SelfReg="false" NextFile="zttap300.cer_1"/>
+ <ROW File="zttap300.cer_1" Component_="zttap300.cer_1" FileName="zttap300.cer" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\zttap300.cer" SelfReg="false"/>
<ROW File="zttap300.inf" Component_="zttap300.inf_1" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.inf" SelfReg="false" NextFile="zttap300.sys"/>
<ROW File="zttap300.sys" Component_="zttap300.inf_1" FileName="zttap300.sys" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.sys" SelfReg="false" NextFile="zttap300.cat"/>
</COMPONENT>
+ <COMPONENT cid="caphyon.advinst.custcomp.AiInstallExecuteSequenceAliasComponent">
+ <ROW AliasRowId="certutil.exe" AliasRowOperation="2" Sequence="4001"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent">
+ <ROW BootstrOptKey="GlobalOptions" GeneralOptions="q" DownloadFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\prerequisites"/>
+ </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="1" PackageFolder="..\..\.." PackageFileName="ZeroTierOne_NDIS6_x86" Languages="en" InstallationType="4" UseLargeSchema="true"/>
- <ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
<ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DigCertStoreComponent">
- <ROW TimeStampUrl="http://timestamp.verisign.com/scripts/timstamp.dll" SignerDescription="[|ProductName]" SignOptions="7" SignTool="0" Thumbprint="2ad023dc7aa92bf4265b33852a2ed2406d2bee86 Subject: ZeroTier Networks LLC&#10;Issuer: DigiCert High Assurance Code Signing CA-1&#10;Valid from 04/24/2015 to 04/01/2016"/>
+ <ROW TimeStampUrl="http://timestamp.verisign.com/scripts/timstamp.dll" SignerDescription="[|ProductName]" SignOptions="7" SignTool="0" UseSha256="1" Thumbprint="7f01c3746df9e6c8235ea2ae38d3cdfeb185728b Subject: ZeroTier, Inc.&#10;Issuer: DigiCert EV Code Signing CA (SHA2)&#10;Valid from 11/30/2016 to 12/05/2019"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
<ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
@@ -106,10 +123,13 @@
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
<ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
<ROW Action="AI_DpiContentScale" Type="1" Source="aicustact.dll" Target="DpiContentScale"/>
+ <ROW Action="AI_EnableDebugLog" Type="321" Source="aicustact.dll" Target="EnableDebugLog"/>
<ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
<ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
@@ -117,9 +137,10 @@
<ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]"/>
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
+ <ROW Action="certutil.exe" Type="3154" Source="certutil.exe" Target="-addstore -f TrustedPublisher [#zttap300.cer_1]"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiDriverPackagesComponent">
- <ROW InfFileName="zttap300.inf" Flags="6"/>
+ <ROW InfFileName="zttap300.inf" Flags="15"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
<ROW Name="ZeroTierIcon.exe" SourcePath="..\..\..\artwork\ZeroTierIcon.ico" Index="0"/>
@@ -129,19 +150,26 @@
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
<ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1501"/>
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>
- <ROW Action="AI_ResolveKnownFolders" Sequence="51"/>
+ <ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
+ <ROW Action="AI_EnableDebugLog" Sequence="51"/>
+ <ROW Action="certutil.exe" Condition="( NOT Installed )" Sequence="6401"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
- <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
- <ROW Action="AI_DpiContentScale" Sequence="51"/>
+ <ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
+ <ROW Action="AI_DpiContentScale" Sequence="52"/>
+ <ROW Action="AI_EnableDebugLog" Sequence="51"/>
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="101"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
- <ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &gt;= 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 2)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &gt;= 1)))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &lt;&gt; 1)))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &lt;&gt; 2)))) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &gt;= 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 2))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 3))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 4))) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 3))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2) OR (MsiNTProductType = 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 501) OR (ServicePackLevel &lt;&gt; 3)) AND ((VersionNT &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT40Display]" DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="(VersionNT &lt;&gt; 500)" Description="[ProductName] cannot be installed on [WindowsTypeNT50Display]." DescriptionLocId="AI.LaunchCondition.NoNT50" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="(VersionNT64 OR ((VersionNT &lt;&gt; 501) OR (ServicePackLevel = 3))) AND ((VersionNT &lt;&gt; 502) OR (ServicePackLevel = 2))" Description="[ProductName] cannot be installed on [WindowsTypeNT5XDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT5X" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="Privileged" Description="[ProductName] requires administrative privileges to install." DescriptionLocId="AI.LaunchCondition.Privileged" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
<ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip
index fdbbeea9..f75edaed 100644
--- a/ext/installfiles/windows/ZeroTier One.aip
+++ b/ext/installfiles/windows/ZeroTier One.aip
@@ -1,386 +1,484 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<DOCUMENT Type="Advanced Installer" CreateVersion="10.9" version="12.5.1" Modules="enterprise" RootPath="." Language="en" Id="{DC564647-6BF0-4550-87F4-89C938D0159C}">
- <COMPONENT cid="caphyon.advinst.msicomp.ProjectOptionsComponent">
- <ROW Name="HiddenItems" Value="UpdaterComponent;SerValComponent;AutorunComponent;MultipleInstancesComponent;MsiJavaComponent;MsiRegsComponent;MsiExtComponent;MsiAssemblyComponent;MsiDriverPackagesComponent;AnalyticsComponent;ActSyncAppComponent;MsiMergeModsComponent;MsiThemeComponent;BackgroundImagesComponent;DictionaryComponent;ScheduledTasksComponent;CPLAppletComponent;GameUxComponent;UserAccountsComponent;MsiClassComponent;WebApplicationsComponent;MsiOdbcDataSrcComponent;SqlConnectionComponent;SharePointSlnComponent;SilverlightSlnComponent;MsiAppSearchComponent"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
- <ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
- <ROW Property="AI_EMBD_MSI_EXTR_PATH" Value="[TempFolder]" ValueLocId="-"/>
- <ROW Property="AI_EXTERNALUIUNINSTALLERNAME" MultiBuildValue="DefaultBuild:aiui"/>
- <ROW Property="AI_PREDEF_LCONDS_PROPS" Value="AI_DETECTED_DOTNET_VERSION"/>
- <ROW Property="AI_PRODUCTNAME_ARP" Value="ZeroTier One"/>
- <ROW Property="AI_REQUIRED_DOTNET_DISPLAY" MultiBuildValue="DefaultBuild:4.5" ValueLocId="-"/>
- <ROW Property="AI_REQUIRED_DOTNET_VERSION" MultiBuildValue="DefaultBuild:4.5" ValueLocId="-"/>
- <ROW Property="AI_UNINSTALLER" Value="msiexec.exe"/>
- <ROW Property="ALLUSERS" Value="1"/>
- <ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]."/>
- <ROW Property="ARPCONTACT" Value="contact@zerotier.com"/>
- <ROW Property="ARPHELPLINK" Value="https://www.zerotier.com/"/>
- <ROW Property="ARPNOMODIFY" MultiBuildValue="DefaultBuild:1"/>
- <ROW Property="ARPNOREPAIR" Value="1"/>
- <ROW Property="ARPPRODUCTICON" Value="ZeroTierIcon.exe" Type="8"/>
- <ROW Property="ARPSYSTEMCOMPONENT" Value="1"/>
- <ROW Property="ARPURLINFOABOUT" Value="https://www.zerotier.com/"/>
- <ROW Property="ARPURLUPDATEINFO" Value="https://www.zerotier.com/"/>
- <ROW Property="AiFeatIcoZeroTierOne" Value="ZeroTierIcon.exe" Type="8"/>
- <ROW Property="CTRLS" Value="2"/>
- <ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
- <ROW Property="Manufacturer" Value="ZeroTier, Inc."/>
- <ROW Property="ProductCode" Value="1033:{856F3AA0-1B20-427F-8509-877EBB751BAA} " Type="16"/>
- <ROW Property="ProductLanguage" Value="1033"/>
- <ROW Property="ProductName" Value="ZeroTier One"/>
- <ROW Property="ProductVersion" Value="1.1.12" Type="32"/>
- <ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
- <ROW Property="RUNAPPLICATION" Value="1" Type="4"/>
- <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND"/>
- <ROW Property="UpgradeCode" Value="{B0E2A5F3-88B6-4E77-B922-CB4739B4C4C8}"/>
- <ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
- <ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows 2000, Windows 2000 Service Pack 1, Windows 2000 Service Pack 2, Windows 2000 Service Pack 3, Windows 2000 Service Pack 4, Windows XP x86, Windows XP x86 Service Pack 1, Windows XP x86 Service Pack 2, Windows XP x86 Service Pack 3, Windows Server 2003 x86, Windows Server 2003 x86 Service Pack 1, Windows Server 2003 x86 Service Pack 2" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT40" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT40Display" MultiBuildValue="DefaultBuild:Windows NT 4.0" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP x64, Windows XP x64 Service Pack 1, Windows XP x64 Service Pack 2, Windows Server 2003 x64, Windows Server 2003 x64 Service Pack 1, Windows Server 2003 x64 Service Pack 2" ValueLocId="-"/>
- <ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP x64, Windows Server 2003 x64" ValueLocId="-"/>
- <ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows 2000, Windows XP x86, Windows Server 2003 x86" ValueLocId="-"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
- <ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1" DirectoryOptions="2"/>
- <ROW Directory="CommonAppDataFolder" Directory_Parent="TARGETDIR" DefaultDir="COMMON~1|CommonAppDataFolder" IsPseudoRoot="1"/>
- <ROW Directory="One_Dir" Directory_Parent="ZeroTier_Dir" DefaultDir="One"/>
- <ROW Directory="ProgramFilesFolder" Directory_Parent="TARGETDIR" DefaultDir="PROGRA~1|ProgramFilesFolder" IsPseudoRoot="1"/>
- <ROW Directory="ProgramMenuFolder" Directory_Parent="TARGETDIR" DefaultDir="PROGRA~2|ProgramMenuFolder" IsPseudoRoot="1"/>
- <ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
- <ROW Directory="ZeroTier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="ZeroTier"/>
- <ROW Directory="networks.d_Dir" Directory_Parent="One_Dir" DefaultDir="networks.d"/>
- <ROW Directory="regid.201001.com.zerotier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="REGID2~1.ZER|regid.2010-01.com.zerotier"/>
- <ROW Directory="tapwindows_Dir" Directory_Parent="One_Dir" DefaultDir="TAP-WI~1|tap-windows"/>
- <ROW Directory="x64_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x64"/>
- <ROW Directory="x86_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x86"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
- <ROW Component="AI_CustomARPName" ComponentId="{B80291A9-8CEC-406C-BB08-611D3CEF1BF6}" Directory_="APPDIR" Attributes="4" KeyPath="DisplayName" Options="1"/>
- <ROW Component="AI_DisableModify" ComponentId="{020DCABD-5D56-49B9-AF48-F07F0B55E590}" Directory_="APPDIR" Attributes="4" KeyPath="NoModify" Options="1"/>
- <ROW Component="Newtonsoft.Json.dll" ComponentId="{0B2F229D-5425-42FB-9E28-F6D25AB2B4B5}" Directory_="APPDIR" Attributes="0" KeyPath="Newtonsoft.Json.dll"/>
- <ROW Component="ProductInformation" ComponentId="{DB078D04-EA8E-4A7C-9001-89BAD932F9D9}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
- <ROW Component="ZeroTierOne.exe" ComponentId="{18B51525-77BF-4FD9-9C18-A10D4CFC25BA}" Directory_="APPDIR" Attributes="0" KeyPath="ZeroTierOne.exe"/>
- <ROW Component="networks.d" ComponentId="{EF54D0DF-889F-41DC-AF5C-4E7F96AB1C8B}" Directory_="networks.d_Dir" Attributes="0"/>
- <ROW Component="regid.201001.com.zerotier" ComponentId="{A39C80FC-6A8F-454F-9052-10DAC3C3B139}" Directory_="regid.201001.com.zerotier_Dir" Attributes="0"/>
- <ROW Component="zerotierone_x64.exe" ComponentId="{DFCFB72D-B055-4E60-B6D8-81FF585C2183}" Directory_="One_Dir" Attributes="256" Condition="VersionNT64" KeyPath="zerotierone_x64.exe"/>
- <ROW Component="zerotierone_x86.exe" ComponentId="{5D2F3366-4FE1-40A4-A81A-66C49FA11F1C}" Directory_="One_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="zerotierone_x86.exe"/>
- <ROW Component="zttap300.cat" ComponentId="{123CD683-FD99-4F0F-8F9B-0222DF409B09}" Directory_="x64_Dir" Attributes="256" Condition="VersionNT64" KeyPath="zttap300.cat_2" Type="0"/>
- <ROW Component="zttap300.cat_1" ComponentId="{9F913E48-095B-4EA3-98DA-EDAB1593F3E3}" Directory_="x86_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="zttap300.cat_3" Type="0"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
- <ROW Feature="ZeroTierOne" Title="MainFeature" Description="ZeroTier One" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="AI_CustomARPName AI_DisableModify Newtonsoft.Json.dll ProductInformation ZeroTierOne.exe networks.d regid.201001.com.zerotier zerotierone_x64.exe zerotierone_x86.exe zttap300.cat zttap300.cat_1"/>
- <ATTRIBUTE name="CurrentFeature" value="ZeroTierOne"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
- <ROW File="Newtonsoft.Json.dll" Component_="Newtonsoft.Json.dll" FileName="NEWTON~1.DLL|Newtonsoft.Json.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\WinUI\bin\Release\Newtonsoft.Json.dll" SelfReg="false" DigSign="true"/>
- <ROW File="ZeroTierOne.exe" Component_="ZeroTierOne.exe" FileName="ZEROTI~1.EXE|ZeroTier One.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\WinUI\bin\Release\ZeroTier One.exe" SelfReg="false" NextFile="zttap300.cat_2" DigSign="true"/>
- <ROW File="zerotierone_x64.exe" Component_="zerotierone_x64.exe" FileName="ZEROTI~2.EXE|zerotier-one_x64.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\Build\x64\Release\zerotier-one_x64.exe" SelfReg="false" NextFile="ZeroTierOne.exe" DigSign="true"/>
- <ROW File="zerotierone_x86.exe" Component_="zerotierone_x86.exe" FileName="ZEROTI~1.EXE|zerotier-one_x86.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\Build\Win32\Release\zerotier-one_x86.exe" SelfReg="false" NextFile="zerotierone_x64.exe" DigSign="true"/>
- <ROW File="zttap300.cat_2" Component_="zttap300.cat" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.cat" SelfReg="false" NextFile="zttap300.sys_2"/>
- <ROW File="zttap300.cat_3" Component_="zttap300.cat_1" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.cat" SelfReg="false" NextFile="zttap300.sys_3"/>
- <ROW File="zttap300.inf" Component_="zttap300.cat" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.inf" SelfReg="false" NextFile="zttap300.cat_3"/>
- <ROW File="zttap300.inf_1" Component_="zttap300.cat_1" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.inf" SelfReg="false" NextFile="Newtonsoft.Json.dll"/>
- <ROW File="zttap300.sys_2" Component_="zttap300.cat" FileName="zttap300.sys" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.sys" SelfReg="false" NextFile="zttap300.inf"/>
- <ROW File="zttap300.sys_3" Component_="zttap300.cat_1" FileName="zttap300.sys" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.sys" SelfReg="false" NextFile="zttap300.inf_1"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
- <ROW BuildKey="DefaultBuild" BuildName="MSI" BuildOrder="1" BuildType="1" PackageFolder="..\..\.." PackageFileName="ZeroTier One" Languages="en" InstallationType="4" ExtUI="true" UseLargeSchema="true"/>
- <ATTRIBUTE name="CurrentBuild" value="DefaultBuild"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.CacheComponent">
- <ATTRIBUTE name="Enable" value="false"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.ChainedPackageComponent">
- <ROW ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Order="1" Options="108" InstallCondition="(VersionNT64)" RemoveCondition="((REMOVE=&quot;ALL&quot;) AND (NOT UPGRADINGPRODUCTCODE) AND (VersionNT64))"/>
- <ROW ChainedPackage="ZeroTierOne_NDIS6_x86.msi" Order="2" Options="108" InstallCondition="(NOT VersionNT64)" RemoveCondition="((REMOVE=&quot;ALL&quot;) AND (NOT UPGRADINGPRODUCTCODE) AND (NOT VersionNT64))"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.ChainedPackageFileComponent">
- <ROW FileId="ZeroTierOne_NDIS6_x64.msi" ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Options="1" TargetPath="ZeroTierOne_NDIS6_x64.msi" Content="..\..\bin\tap-windows-ndis6\x64\ZeroTierOne_NDIS6_x64.msi"/>
- <ROW FileId="ZeroTierOne_NDIS6_x86.msi" ChainedPackage="ZeroTierOne_NDIS6_x86.msi" Options="1" TargetPath="ZeroTierOne_NDIS6_x86.msi" Content="..\..\bin\tap-windows-ndis6\x86\ZeroTierOne_NDIS6_x86.msi"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
- <ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
- <ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.DigCertStoreComponent">
- <ROW TimeStampUrl="http://timestamp.verisign.com/scripts/timstamp.dll" SignerDescription="ZeroTier One" DescriptionUrl="https://www.zerotier.com/" SignOptions="7" SignTool="0" UseSha256="1" Thumbprint="45f6b8ef02b543eeaa08d5f0f08ebe72c2a8a2d5 Subject: ZeroTier, Inc.&#10;Issuer: DigiCert SHA2 High Assurance Code Signing CA&#10;Valid from 03/22/2016 to 05/06/2019"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.FirewallExceptionComponent">
- <ROW FirewallException="ZeroTierOneUDP9993" DisplayName="ZeroTier One UDP/9993" GroupName="ZeroTierOne" Enabled="1" Scope="*" Condition="1" Profiles="7" Port="9993" Protocol="UDP"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
- <ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
- <ROW Fragment="MaintenanceTypeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceTypeDlg.aip"/>
- <ROW Fragment="MaintenanceWelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceWelcomeDlg.aip"/>
- <ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
- <ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
- <ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
- <ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
- <ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
- <ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>
- <ROW Fragment="VerifyRepairDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRepairDlg.aip"/>
- <ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiActionTextComponent">
- <ROW Action="AI_FwConfig" Description="Executing Windows Firewall configurations" Template="Configuring Windows Firewall rule: &quot;[1]&quot;" DescriptionLocId="ActionText.Description.AI_FwConfig" TemplateLocId="ActionText.Template.AI_FwConfig"/>
- <ROW Action="AI_FwInstall" Description="Generating actions to configure Windows Firewall" DescriptionLocId="ActionText.Description.AI_FwInstall"/>
- <ROW Action="AI_FwRemove" Description="Executing Windows Firewall configurations" Template="Configuring Windows Firewall rule: &quot;[1]&quot;" DescriptionLocId="ActionText.Description.AI_FwRemove" TemplateLocId="ActionText.Template.AI_FwRemove"/>
- <ROW Action="AI_FwRollback" Description="Rolling back Windows Firewall configurations." Template="Rolling back Windows Firewall configurations." DescriptionLocId="ActionText.Description.AI_FwRollback" TemplateLocId="ActionText.Template.AI_FwRollback"/>
- <ROW Action="AI_FwUninstall" Description="Generating actions to configure Windows Firewall" DescriptionLocId="ActionText.Description.AI_FwUninstall"/>
- <ROW Action="AI_TxtUpdaterCommit" Description="Commit text file changes. " Template="Commit text file changes." DescriptionLocId="ActionText.Description.AI_TxtUpdaterCommit" TemplateLocId="ActionText.Template.AI_TxtUpdaterCommit"/>
- <ROW Action="AI_TxtUpdaterConfig" Description="Executing text file updates" Template="Updating text file: &quot;[1]&quot;" DescriptionLocId="ActionText.Description.AI_TxtUpdaterConfig" TemplateLocId="ActionText.Template.AI_TxtUpdaterConfig"/>
- <ROW Action="AI_TxtUpdaterInstall" Description="Generating actions to configure text files updates" DescriptionLocId="ActionText.Description.AI_TxtUpdaterInstall"/>
- <ROW Action="AI_TxtUpdaterRollback" Description="Rolling back text file changes. " Template="Rolling back text file changes." DescriptionLocId="ActionText.Description.AI_TxtUpdaterRollback" TemplateLocId="ActionText.Template.AI_TxtUpdaterRollback"/>
- <ROW Action="AI_XmlCommit" Description="Committing XML file configurations." Template="Committing XML file configurations." DescriptionLocId="ActionText.Description.AI_XmlCommit" TemplateLocId="ActionText.Template.AI_XmlCommit"/>
- <ROW Action="AI_XmlConfig" Description="Executing XML file configurations" Template="Configuring XML file: &quot;[1]&quot;" DescriptionLocId="ActionText.Description.AI_XmlConfig" TemplateLocId="ActionText.Template.AI_XmlConfig"/>
- <ROW Action="AI_XmlInstall" Description="Generating actions to configure XML files" DescriptionLocId="ActionText.Description.AI_XmlInstall"/>
- <ROW Action="AI_XmlRemove" Description="Executing XML file configurations" Template="Configuring XML file: &quot;[1]&quot;" DescriptionLocId="ActionText.Description.AI_XmlRemove" TemplateLocId="ActionText.Template.AI_XmlRemove"/>
- <ROW Action="AI_XmlRollback" Description="Rolling back XML file configurations." Template="Rolling back XML file configurations." DescriptionLocId="ActionText.Description.AI_XmlRollback" TemplateLocId="ActionText.Template.AI_XmlRollback"/>
- <ROW Action="AI_XmlUninstall" Description="Generating actions to configure XML files" DescriptionLocId="ActionText.Description.AI_XmlUninstall"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
- <ROW Name="ExternalUICleaner.dll" SourcePath="&lt;AI_CUSTACTS&gt;ExternalUICleaner.dll"/>
- <ROW Name="NetFirewall.dll" SourcePath="&lt;AI_CUSTACTS&gt;NetFirewall.dll"/>
- <ROW Name="ShortcutFlags.dll" SourcePath="&lt;AI_CUSTACTS&gt;ShortcutFlags.dll"/>
- <ROW Name="SoftwareDetector.dll" SourcePath="&lt;AI_CUSTACTS&gt;SoftwareDetector.dll"/>
- <ROW Name="TxtUpdater.dll" SourcePath="&lt;AI_CUSTACTS&gt;TxtUpdater.dll"/>
- <ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
- <ROW Name="chainersupport.dll" SourcePath="&lt;AI_CUSTACTS&gt;chainersupport.dll"/>
- <ROW Name="msichainer.exe" SourcePath="&lt;AI_CUSTACTS&gt;msichainer.exe"/>
- <ROW Name="xmlCfg.dll" SourcePath="&lt;AI_CUSTACTS&gt;xmlCfg.dll"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
- <ROW Dialog_="WelcomeDlg" Control="WelcomeDlgDialogInitializer" Type="DialogInitializer" X="0" Y="0" Width="0" Height="0" Attributes="0" Order="-1" TextLocId="-" HelpLocId="-" ExtDataLocId="-"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
- <ROW Dialog_="WelcomeDlg" Control_="Next" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="1"/>
- <ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>
- <ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>
- <ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>
- <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_MAINT" Ordering="198"/>
- <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="202"/>
- <ROW Dialog_="MaintenanceTypeDlg" Control_="ChangeButton" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="501"/>
- <ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>
- <ROW Dialog_="MaintenanceTypeDlg" Control_="RemoveButton" Event="NewDialog" Argument="VerifyRemoveDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="601"/>
- <ROW Dialog_="VerifyRemoveDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="1"/>
- <ROW Dialog_="MaintenanceTypeDlg" Control_="RepairButton" Event="NewDialog" Argument="VerifyRepairDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="601"/>
- <ROW Dialog_="VerifyRepairDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="1"/>
- <ROW Dialog_="VerifyRepairDlg" Control_="Repair" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="399" Options="1"/>
- <ROW Dialog_="VerifyRemoveDlg" Control_="Remove" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="299" Options="1"/>
- <ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="201"/>
- <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>
- <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>
- <ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>
- <ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfRbDiskDlg" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST=&quot;P&quot; OR NOT PROMPTROLLBACKCOST)" Ordering="2" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="Next" Event="EnableRollback" Argument="False" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST=&quot;D&quot;" Ordering="3" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfDiskDlg" Condition="AI_INSTALL AND ( (OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST=&quot;F&quot;) )" Ordering="4" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[AI_ButtonText_Next_Orig]" Argument="[ButtonText_Next]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[ButtonText_Next]" Argument="[[AI_CommitButton]]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[AI_Text_Next_Orig]" Argument="[Text_Next]" Condition="AI_INSTALL" Ordering="2" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[Text_Next]" Argument="[Text_Install]" Condition="AI_INSTALL" Ordering="3" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="Back" Event="[ButtonText_Next]" Argument="[AI_ButtonText_Next_Orig]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
- <ROW Dialog_="WelcomeDlg" Control_="Back" Event="[Text_Next]" Argument="[AI_Text_Next_Orig]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
- <ROW Directory_="networks.d_Dir" Component_="networks.d" ManualDelete="false"/>
- <ROW Directory_="regid.201001.com.zerotier_Dir" Component_="regid.201001.com.zerotier" ManualDelete="false"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
- <ROW Action="AI_ApplyShortcutFlags" Type="3073" Source="ShortcutFlags.dll" Target="UpdateShortcutFlags" WithoutSeq="true"/>
- <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
- <ROW Action="AI_CommitChainers" Type="11841" Source="chainersupport.dll" Target="CommitChainedPackages" WithoutSeq="true"/>
- <ROW Action="AI_DATA_SETTER" Type="51" Source="CustomActionData" Target="[~]"/>
- <ROW Action="AI_DATA_SETTER_1" Type="51" Source="CustomActionData" Target="[~]"/>
- <ROW Action="AI_DATA_SETTER_2" Type="51" Source="CustomActionData" Target="[~]"/>
- <ROW Action="AI_DATA_SETTER_3" Type="51" Source="CustomActionData" Target="[~]"/>
- <ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
- <ROW Action="AI_DetectSoftware" Type="257" Source="SoftwareDetector.dll" Target="OnDetectSoftware"/>
- <ROW Action="AI_DoRemoveExternalUIStub" Type="3585" Source="ExternalUICleaner.dll" Target="DoRemoveExternalUIStub" WithoutSeq="true"/>
- <ROW Action="AI_DpiContentScale" Type="1" Source="aicustact.dll" Target="DpiContentScale"/>
- <ROW Action="AI_FwConfig" Type="11265" Source="NetFirewall.dll" Target="OnFwConfig" WithoutSeq="true"/>
- <ROW Action="AI_FwInstall" Type="1" Source="NetFirewall.dll" Target="OnFwInstall" AdditionalSeq="AI_DATA_SETTER_2"/>
- <ROW Action="AI_FwRemove" Type="11265" Source="NetFirewall.dll" Target="OnFwRemove" WithoutSeq="true"/>
- <ROW Action="AI_FwRollback" Type="11521" Source="NetFirewall.dll" Target="OnFwRollback" WithoutSeq="true"/>
- <ROW Action="AI_FwUninstall" Type="1" Source="NetFirewall.dll" Target="OnFwUninstall" AdditionalSeq="AI_DATA_SETTER_3"/>
- <ROW Action="AI_GetArpIconPath" Type="1" Source="aicustact.dll" Target="GetArpIconPath"/>
- <ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
- <ROW Action="AI_LaunchApp" Type="1" Source="aicustact.dll" Target="[#ZeroTierOne.exe]"/>
- <ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
- <ROW Action="AI_PinShortcuts" Type="1" Source="ShortcutFlags.dll" Target="PinShortcuts"/>
- <ROW Action="AI_PinToTaskbar" Type="1025" Source="ShortcutFlags.dll" Target="PinToTaskbar" WithoutSeq="true"/>
- <ROW Action="AI_PrepareChainers" Type="1" Source="chainersupport.dll" Target="PrepareChainedPackages"/>
- <ROW Action="AI_PrepareShortcutFlags" Type="1" Source="ShortcutFlags.dll" Target="PrepareActionData"/>
- <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
- <ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
- <ROW Action="AI_RemoveExternalUIStub" Type="1" Source="ExternalUICleaner.dll" Target="RemoveExternalUIStub"/>
- <ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
- <ROW Action="AI_RollbackChainers" Type="11585" Source="chainersupport.dll" Target="RollbackChainedPackages" WithoutSeq="true"/>
- <ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
- <ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
- <ROW Action="AI_TxtUpdaterCommit" Type="11777" Source="TxtUpdater.dll" Target="OnTxtUpdaterCommit" WithoutSeq="true"/>
- <ROW Action="AI_TxtUpdaterConfig" Type="11265" Source="TxtUpdater.dll" Target="OnTxtUpdaterConfig" WithoutSeq="true"/>
- <ROW Action="AI_TxtUpdaterInstall" Type="1" Source="TxtUpdater.dll" Target="OnTxtUpdaterInstall"/>
- <ROW Action="AI_TxtUpdaterRollback" Type="11521" Source="TxtUpdater.dll" Target="OnTxtUpdaterRollback" WithoutSeq="true"/>
- <ROW Action="AI_UnpinFromTaskbar" Type="1025" Source="ShortcutFlags.dll" Target="UnpinFromTaskbar" WithoutSeq="true"/>
- <ROW Action="AI_UnpinShortcuts" Type="1" Source="ShortcutFlags.dll" Target="UnpinShortcuts"/>
- <ROW Action="AI_XmlCommit" Type="11777" Source="xmlCfg.dll" Target="OnXmlCommit" WithoutSeq="true"/>
- <ROW Action="AI_XmlConfig" Type="11265" Source="xmlCfg.dll" Target="OnXmlConfig" WithoutSeq="true"/>
- <ROW Action="AI_XmlInstall" Type="1" Source="xmlCfg.dll" Target="OnXmlInstall" AdditionalSeq="AI_DATA_SETTER"/>
- <ROW Action="AI_XmlRemove" Type="11265" Source="xmlCfg.dll" Target="OnXmlRemove" WithoutSeq="true"/>
- <ROW Action="AI_XmlRollback" Type="11521" Source="xmlCfg.dll" Target="OnXmlRollback" WithoutSeq="true"/>
- <ROW Action="AI_XmlUninstall" Type="1" Source="xmlCfg.dll" Target="OnXmlUninstall" AdditionalSeq="AI_DATA_SETTER_1"/>
- <ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder]ZeroTier\One"/>
- <ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]" MultiBuildTarget="DefaultBuild:[ProgramMenuFolder]"/>
- <ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
- <ROW Action="TapDeviceRemove32" Type="3154" Source="zerotierone_x86.exe" Target="-D"/>
- <ROW Action="TapDeviceRemove64" Type="3154" Source="zerotierone_x64.exe" Target="-D"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiEmbeddedChainerComponent">
- <ROW MsiEmbeddedChainer="msichainer.exe" Condition="VersionMsi &gt;= &quot;4.05&quot;" CommandLine="[AI_CHAINER_CMD_LINE]" Source="msichainer.exe" Type="2"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiEnvComponent">
- <ROW Environment="Path" Name="=-*Path" Value="[~];[APPDIR]" Component_="ZeroTierOne.exe"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
- <ROW Name="ZeroTierIcon.exe" SourcePath="..\..\..\artwork\ZeroTierIcon.ico" Index="0"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
- <ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
- <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
- <ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1502"/>
- <ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>
- <ROW Action="AI_ResolveKnownFolders" Sequence="51"/>
- <ROW Action="AI_PrepareShortcutFlags" Condition="(VersionNT &gt; 501) AND ((NOT Installed) OR (Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;)))" Sequence="4501"/>
- <ROW Action="AI_XmlInstall" Condition="(REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5103"/>
- <ROW Action="AI_DATA_SETTER" Condition="(REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5102"/>
- <ROW Action="AI_XmlUninstall" Condition="(REMOVE)" Sequence="3102"/>
- <ROW Action="AI_DATA_SETTER_1" Condition="(REMOVE)" Sequence="3101"/>
- <ROW Action="InstallFinalize" Sequence="6597" SeqType="0" MsiKey="InstallFinalize"/>
- <ROW Action="AI_RemoveExternalUIStub" Condition="(REMOVE=&quot;ALL&quot;) AND ((VersionNT &gt; 500) OR((VersionNT = 500) AND (ServicePackLevel &gt;= 4)))" Sequence="1501"/>
- <ROW Action="AI_GetArpIconPath" Sequence="1401"/>
- <ROW Action="TapDeviceRemove32" Condition="( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) AND NOT UPGRADINGPRODUCTCODE ) AND ( NOT VersionNT64 )" Sequence="1601"/>
- <ROW Action="TapDeviceRemove64" Condition="( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) AND NOT UPGRADINGPRODUCTCODE ) AND ( VersionNT64 )" Sequence="1602"/>
- <ROW Action="AI_PrepareChainers" Condition="VersionMsi &gt;= &quot;4.05&quot;" Sequence="5851"/>
- <ROW Action="AI_FwInstall" Condition="(VersionNT &gt;= 501) AND (REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5802"/>
- <ROW Action="AI_DATA_SETTER_2" Condition="(VersionNT &gt;= 501) AND (REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5801"/>
- <ROW Action="AI_FwUninstall" Condition="(VersionNT &gt;= 501) AND (REMOVE=&quot;ALL&quot;)" Sequence="1702"/>
- <ROW Action="AI_DATA_SETTER_3" Condition="(VersionNT &gt;= 501) AND (REMOVE=&quot;ALL&quot;)" Sequence="1701"/>
- <ROW Action="AI_DetectSoftware" Sequence="101"/>
- <ROW Action="AI_PinShortcuts" Condition="(VersionNT &gt; 600) AND ((NOT Installed) OR (Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;)))" Sequence="4502"/>
- <ROW Action="AI_UnpinShortcuts" Condition="(VersionNT &gt; 600) AND (REMOVE = &quot;ALL&quot;)" Sequence="3199"/>
- <ROW Action="AI_TxtUpdaterInstall" Sequence="5101"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
- <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
- <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
- <ROW Action="AI_DpiContentScale" Sequence="51"/>
- <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99"/>
- <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="102"/>
- <ROW Action="ExecuteAction" Sequence="1299" SeqType="0" MsiKey="ExecuteAction"/>
- <ROW Action="AI_DetectSoftware" Sequence="101"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
- <ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &gt;= 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 1)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR (((VersionNT64 = 502) AND (ServicePackLevel &lt;&gt; 2)) OR (MsiNTProductType &lt;&gt; 1))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &gt;= 1)))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &lt;&gt; 1)))) AND ((VersionNT64 &lt;&gt; 502) OR ((VersionNT64 = 502) AND ((MsiNTProductType = 1) OR (ServicePackLevel &lt;&gt; 2)))) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &gt;= 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 1))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 2))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 3))) AND ((VersionNT &lt;&gt; 500) OR ((VersionNT = 500) AND (ServicePackLevel &lt;&gt; 4))) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) AND (((VersionNT &lt;&gt; 501) OR ((VersionNT = 501) AND (ServicePackLevel &lt;&gt; 3))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &gt;= 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &lt;&gt; 1))) OR VersionNT64) AND (((VersionNT &lt;&gt; 502) OR ((VersionNT = 502) AND (ServicePackLevel &lt;&gt; 2))) OR VersionNT64) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]" DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT40Display]" DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="AI_DETECTED_DOTNET_VERSION &gt;= AI_REQUIRED_DOTNET_VERSION" Description="[ProductName] cannot be installed on systems with .NET Framework version lower than [AI_REQUIRED_DOTNET_DISPLAY]." DescriptionLocId="AI.LaunchCondition.DotNET" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="Privileged" Description="[ProductName] requires administrative privileges to install." DescriptionLocId="AI.LaunchCondition.Privileged" IsPredefined="true" Builds="DefaultBuild"/>
- <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]" DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
- <ROW Registry="Comments" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Comments" Value="[ARPCOMMENTS]" Component_="AI_CustomARPName"/>
- <ROW Registry="Contact" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Contact" Value="[ARPCONTACT]" Component_="AI_CustomARPName"/>
- <ROW Registry="DisplayIcon" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="DisplayIcon" Value="[ARP_ICON_PATH]" Component_="AI_CustomARPName"/>
- <ROW Registry="DisplayName" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="DisplayName" Value="[AI_PRODUCTNAME_ARP]" Component_="AI_CustomARPName"/>
- <ROW Registry="DisplayVersion" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="DisplayVersion" Value="[ProductVersion]" Component_="AI_CustomARPName"/>
- <ROW Registry="HelpLink" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="HelpLink" Value="[ARPHELPLINK]" Component_="AI_CustomARPName"/>
- <ROW Registry="HelpTelephone" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="HelpTelephone" Value="[ARPHELPTELEPHONE]" Component_="AI_CustomARPName"/>
- <ROW Registry="InstallLocation" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="InstallLocation" Value="[APPDIR]" Component_="AI_CustomARPName"/>
- <ROW Registry="ModifyPath" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="ModifyPath" Value="[AI_UNINSTALLER] /I [ProductCode]" Component_="AI_CustomARPName"/>
- <ROW Registry="NoModify" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="NoModify" Value="#1" Component_="AI_DisableModify"/>
- <ROW Registry="NoRepair" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="NoRepair" Value="#1" Component_="AI_CustomARPName"/>
- <ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
- <ROW Registry="Publisher" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Publisher" Value="[Manufacturer]" Component_="AI_CustomARPName"/>
- <ROW Registry="URLInfoAbout" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="URLInfoAbout" Value="[ARPURLINFOABOUT]" Component_="AI_CustomARPName"/>
- <ROW Registry="URLUpdateInfo" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="URLUpdateInfo" Value="[ARPURLUPDATEINFO]" Component_="AI_CustomARPName"/>
- <ROW Registry="UninstallPath" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="UninstallPath" Value="[AI_UNINSTALLER] /x [ProductCode]" Component_="AI_CustomARPName"/>
- <ROW Registry="UninstallString" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="UninstallString" Value="[AI_UNINSTALLER] /x [ProductCode]" Component_="AI_CustomARPName"/>
- <ROW Registry="Version" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
- <ROW Registry="VersionMajor" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="VersionMajor" Value="#0" Component_="AI_CustomARPName"/>
- <ROW Registry="VersionMinor" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="VersionMinor" Value="#7" Component_="AI_CustomARPName"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiRemoveFileComponent">
- <ROW FileKey="devcon.log" Component_="ProductInformation" FileName="devcon.log" DirProperty="One_Dir" InstallMode="3"/>
- <ROW FileKey="devcon_x64.exe" Component_="ProductInformation" FileName="devcon_x64.exe" DirProperty="One_Dir" InstallMode="3"/>
- <ROW FileKey="devcon_x86.exe" Component_="ProductInformation" FileName="devcon_x86.exe" DirProperty="One_Dir" InstallMode="3"/>
- <ROW FileKey="node.log" Component_="ProductInformation" FileName="node.log" DirProperty="One_Dir" InstallMode="3"/>
- <ROW FileKey="node.log.old" Component_="ProductInformation" FileName="node.log.old" DirProperty="One_Dir" InstallMode="3"/>
- <ROW FileKey="roottopology" Component_="ProductInformation" FileName="root-topology" DirProperty="One_Dir" InstallMode="3"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiServCtrlComponent">
- <ROW ServiceControl="zerotierone_x64.exe" Name="ZeroTierOneService" Event="163" Wait="1" Component_="zerotierone_x64.exe"/>
- <ROW ServiceControl="zerotierone_x86.exe" Name="ZeroTierOneService" Event="163" Wait="1" Component_="zerotierone_x86.exe"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiServInstComponent">
- <ROW ServiceInstall="zerotierone_x64.exe" Name="ZeroTierOneService" DisplayName="ZeroTier One" ServiceType="16" StartType="2" ErrorControl="32769" Component_="zerotierone_x64.exe" Description="Ethernet Virtualization Service"/>
- <ROW ServiceInstall="zerotierone_x86.exe" Name="ZeroTierOneService" DisplayName="ZeroTier One" ServiceType="16" StartType="2" ErrorControl="32769" Component_="zerotierone_x86.exe" Description="Ethernet Virtualization Service"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
- <ROW Shortcut="ZeroTierOne" Directory_="ProgramMenuFolder" Name="ZEROTI~1|ZeroTier One" Component_="ZeroTierOne.exe" Target="[#ZeroTierOne.exe]" Description="Ethernet Virtualization Control Panel" Hotkey="0" Icon_="ZeroTierIcon.exe" IconIndex="0" ShowCmd="1" WkDir="APPDIR" CustomFlags="1"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
- <ATTRIBUTE name="UsedTheme" value="classic"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">
- <ROW UpgradeCode="[|UpgradeCode]" VersionMin="0.0.1" VersionMax="[|ProductVersion]" Attributes="257" ActionProperty="OLDPRODUCTS"/>
- <ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.SoftwareIdentificationComponent">
- <ATTRIBUTE name="LocalFile" value="regid.199509.com.example_ProductName.swidtag"/>
- <ATTRIBUTE name="SystemFile" value="regid.199509.com.example_ProductName.swidtag_1"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.TxtUpdateComponent">
- <ROW Name="Append/Create" TxtUpdateSet="zerotiercli.bat" FindPattern="@ECHO OFF&#13;&#10;if [\[][#zerotierone_x64.exe][\]] == [\[][\]] (&#13;&#10;&#9;[#zerotierone_x86.exe] -q %*&#13;&#10;) else (&#13;&#10;&#9;[#zerotierone_x64.exe] -q %*&#13;&#10;)&#13;&#10;" Options="160" Order="0" FileEncoding="0"/>
- <ROW Name="Replace" TxtUpdateSet="zerotiercli.bat" FindPattern="YourFindText" ReplacePattern="YourReplaceText" Options="2" Order="1" FileEncoding="-1"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.TxtUpdateSetComponent">
- <ROW Key="zerotiercli.bat" Component="zerotierone_x64.exe" FileName="zerotier-cli.bat" Directory="APPDIR" Options="17"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.XmlAttributeComponent">
- <ROW XmlAttribute="xmlnsds" XmlElement="swidsoftware_identification_tag" Name="xmlns:ds" Flags="14" Order="0" Value="http://www.w3.org/2000/09/xmldsig#"/>
- <ROW XmlAttribute="xmlnsswid" XmlElement="swidsoftware_identification_tag" Name="xmlns:swid" Flags="14" Order="1" Value="http://standards.iso.org/iso/19770/-2/2008/schema.xsd"/>
- <ROW XmlAttribute="xmlnsxsi" XmlElement="swidsoftware_identification_tag" Name="xmlns:xsi" Flags="14" Order="2" Value="http://www.w3.org/2001/XMLSchema-instance"/>
- <ROW XmlAttribute="xsischemaLocation" XmlElement="swidsoftware_identification_tag" Name="xsi:schemaLocation" Flags="14" Order="3" Value="http://standards.iso.org/iso/19770/-2/2008/schema.xsd software_identification_tag.xsd"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.XmlElementComponent">
- <ROW XmlElement="swidbuild" ParentElement="swidnumeric" Name="swid:build" Condition="1" Order="2" Flags="14" Text="12"/>
- <ROW XmlElement="swidentitlement_required_indicator" ParentElement="swidsoftware_identification_tag" Name="swid:entitlement_required_indicator" Condition="1" Order="0" Flags="14" Text="false"/>
- <ROW XmlElement="swidmajor" ParentElement="swidnumeric" Name="swid:major" Condition="1" Order="0" Flags="14" Text="1"/>
- <ROW XmlElement="swidminor" ParentElement="swidnumeric" Name="swid:minor" Condition="1" Order="1" Flags="14" Text="1"/>
- <ROW XmlElement="swidname" ParentElement="swidproduct_version" Name="swid:name" Condition="1" Order="0" Flags="14" Text="[ProductVersion]"/>
- <ROW XmlElement="swidname_1" ParentElement="swidsoftware_creator" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc."/>
- <ROW XmlElement="swidname_2" ParentElement="swidsoftware_licensor" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc."/>
- <ROW XmlElement="swidname_3" ParentElement="swidtag_creator" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc."/>
- <ROW XmlElement="swidnumeric" ParentElement="swidproduct_version" Name="swid:numeric" Condition="1" Order="1" Flags="14"/>
- <ROW XmlElement="swidproduct_title" ParentElement="swidsoftware_identification_tag" Name="swid:product_title" Condition="1" Order="1" Flags="14" Text="[ProductName]"/>
- <ROW XmlElement="swidproduct_version" ParentElement="swidsoftware_identification_tag" Name="swid:product_version" Condition="1" Order="2" Flags="14"/>
- <ROW XmlElement="swidregid" ParentElement="swidsoftware_creator" Name="swid:regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
- <ROW XmlElement="swidregid_1" ParentElement="swidsoftware_licensor" Name="swid:regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
- <ROW XmlElement="swidregid_2" ParentElement="swidtag_creator" Name="swid:regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
- <ROW XmlElement="swidreview" ParentElement="swidnumeric" Name="swid:review" Condition="1" Order="3" Flags="14" Text="0"/>
- <ROW XmlElement="swidsoftware_creator" ParentElement="swidsoftware_identification_tag" Name="swid:software_creator" Condition="1" Order="3" Flags="14"/>
- <ROW XmlElement="swidsoftware_id" ParentElement="swidsoftware_identification_tag" Name="swid:software_id" Condition="1" Order="5" Flags="14"/>
- <ROW XmlElement="swidsoftware_identification_tag" Name="swid:software_identification_tag" Condition="1" Order="0" Flags="14"/>
- <ROW XmlElement="swidsoftware_licensor" ParentElement="swidsoftware_identification_tag" Name="swid:software_licensor" Condition="1" Order="4" Flags="14"/>
- <ROW XmlElement="swidtag_creator" ParentElement="swidsoftware_identification_tag" Name="swid:tag_creator" Condition="1" Order="6" Flags="14"/>
- <ROW XmlElement="swidtag_creator_regid" ParentElement="swidsoftware_id" Name="swid:tag_creator_regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
- <ROW XmlElement="swidunique_id" ParentElement="swidsoftware_id" Name="swid:unique_id" Condition="1" Order="0" Flags="14" Text="ZeroTierOne"/>
- </COMPONENT>
- <COMPONENT cid="caphyon.advinst.msicomp.XmlFileComponent">
- <ROW XmlFile="regid.199509.com.example_ProductName.swidtag" FileName="REGID2~1.SWI|regid.2010-01.com.zerotier_ZeroTierOne.swidtag" DirProperty="APPDIR" Component="ProductInformation" RootElement="swidsoftware_identification_tag" Flags="25" Version="1.0" Encoding="UTF-8" IndentUnits="2"/>
- <ROW XmlFile="regid.199509.com.example_ProductName.swidtag_1" FileName="REGID2~1.SWI|regid.2010-01.com.zerotier_ZeroTierOne.swidtag" DirProperty="regid.201001.com.zerotier_Dir" Component="ProductInformation" RootElement="swidsoftware_identification_tag" Flags="25" Version="1.0" Encoding="UTF-8" IndentUnits="2"/>
- </COMPONENT>
-</DOCUMENT>
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<DOCUMENT Type="Advanced Installer" CreateVersion="10.9" version="14.5.2" Modules="enterprise" RootPath="." Language="en" Id="{DC564647-6BF0-4550-87F4-89C938D0159C}">
+ <COMPONENT cid="caphyon.advinst.msicomp.ProjectOptionsComponent">
+ <ROW Name="HiddenItems" Value="UpdaterComponent;SerValComponent;AutorunComponent;MultipleInstancesComponent;AppXProductDetailsComponent;AppXDependenciesComponent;AppXAppDetailsComponent;AppXVisualAssetsComponent;AppXCapabilitiesComponent;AppXAppDeclarationsComponent;AppXUriRulesComponent;MsiJavaComponent;MsiRegsComponent;MsiExtComponent;MsiAssemblyComponent;AnalyticsComponent;ActSyncAppComponent;MsiMergeModsComponent;MsiThemeComponent;BackgroundImagesComponent;DictionaryComponent;ScheduledTasksComponent;CPLAppletComponent;GameUxComponent;UserAccountsComponent;MsiClassComponent;WebApplicationsComponent;MsiOdbcDataSrcComponent;SqlConnectionComponent;SharePointSlnComponent;SilverlightSlnComponent"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
+ <ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
+ <ROW Property="AI_EMBD_MSI_EXTR_PATH" Value="[TempFolder]" ValueLocId="-"/>
+ <ROW Property="AI_EXTERNALUIUNINSTALLERNAME" MultiBuildValue="DefaultBuild:aiui"/>
+ <ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
+ <ROW Property="AI_PREDEF_LCONDS_PROPS" Value="AI_DETECTED_DOTNET_VERSION"/>
+ <ROW Property="AI_PRODUCTNAME_ARP" Value="ZeroTier One"/>
+ <ROW Property="AI_REQUIRED_DOTNET_DISPLAY" MultiBuildValue="DefaultBuild:4.5" ValueLocId="-"/>
+ <ROW Property="AI_REQUIRED_DOTNET_VERSION" MultiBuildValue="DefaultBuild:4.5" ValueLocId="-"/>
+ <ROW Property="AI_UNINSTALLER" Value="msiexec.exe"/>
+ <ROW Property="ALLUSERS" Value="1"/>
+ <ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]."/>
+ <ROW Property="ARPCONTACT" Value="contact@zerotier.com"/>
+ <ROW Property="ARPHELPLINK" Value="https://www.zerotier.com/"/>
+ <ROW Property="ARPNOMODIFY" MultiBuildValue="DefaultBuild:1"/>
+ <ROW Property="ARPNOREPAIR" Value="1" MultiBuildValue="ExeBuild:1"/>
+ <ROW Property="ARPPRODUCTICON" Value="ZeroTierIcon.exe" Type="8"/>
+ <ROW Property="ARPSYSTEMCOMPONENT" Value="1"/>
+ <ROW Property="ARPURLINFOABOUT" Value="https://www.zerotier.com/"/>
+ <ROW Property="ARPURLUPDATEINFO" Value="https://www.zerotier.com/"/>
+ <ROW Property="AiFeatIcoZeroTierOne" Value="ZeroTierIcon.exe" Type="8"/>
+ <ROW Property="CTRLS" Value="2"/>
+ <ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
+ <ROW Property="Manufacturer" Value="ZeroTier, Inc."/>
+ <ROW Property="ProductCode" Value="1033:{BCCDCFD7-34FA-473E-9E50-20314D1017F6} " Type="16"/>
+ <ROW Property="ProductLanguage" Value="1033"/>
+ <ROW Property="ProductName" Value="ZeroTier One"/>
+ <ROW Property="ProductVersion" Value="1.2.6" Type="32"/>
+ <ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
+ <ROW Property="RUNAPPLICATION" Value="1" Type="4"/>
+ <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
+ <ROW Property="UpgradeCode" Value="{B0E2A5F3-88B6-4E77-B922-CB4739B4C4C8}"/>
+ <ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME#ExeBuild:Windows 9x/ME" ValueLocId="-"/>
+ <ROW Property="WindowsType9XDisplay" MultiBuildValue="DefaultBuild:Windows 9x/ME#ExeBuild:Windows 9x/ME" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT" MultiBuildValue="DefaultBuild:Windows XP SP3 x86, Windows Server 2003 SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT40" MultiBuildValue="DefaultBuild:Windows NT 4.0#ExeBuild:Windows NT 4.0" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT40Display" MultiBuildValue="DefaultBuild:Windows NT 4.0#ExeBuild:Windows NT 4.0" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT50" MultiBuildValue="DefaultBuild:Windows 2000#ExeBuild:Windows 2000" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT50Display" MultiBuildValue="DefaultBuild:Windows 2000#ExeBuild:Windows 2000" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT5X" MultiBuildValue="DefaultBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86#ExeBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT5XDisplay" MultiBuildValue="DefaultBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86#ExeBuild:Windows XP/2003 RTM, Windows XP/2003 SP1, Windows XP SP2 x86" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT64" MultiBuildValue="DefaultBuild:Windows XP SP2 x64, Windows Server 2003 SP2 x64" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNT64Display" MultiBuildValue="DefaultBuild:Windows XP SP2 x64, Windows Server 2003 SP2 x64" ValueLocId="-"/>
+ <ROW Property="WindowsTypeNTDisplay" MultiBuildValue="DefaultBuild:Windows XP SP3 x86, Windows Server 2003 SP2 x86" ValueLocId="-"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
+ <ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1" DirectoryOptions="2"/>
+ <ROW Directory="CommonAppDataFolder" Directory_Parent="TARGETDIR" DefaultDir="COMMON~1|CommonAppDataFolder" IsPseudoRoot="1"/>
+ <ROW Directory="FontsFolder" Directory_Parent="TARGETDIR" DefaultDir="FONTSF~1|FontsFolder" IsPseudoRoot="1"/>
+ <ROW Directory="One_Dir" Directory_Parent="ZeroTier_Dir" DefaultDir="One"/>
+ <ROW Directory="ProgramFilesFolder" Directory_Parent="TARGETDIR" DefaultDir="PROGRA~1|ProgramFilesFolder" IsPseudoRoot="1"/>
+ <ROW Directory="ProgramMenuFolder" Directory_Parent="TARGETDIR" DefaultDir="PROGRA~2|ProgramMenuFolder" IsPseudoRoot="1"/>
+ <ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
+ <ROW Directory="ZeroTier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="ZeroTier"/>
+ <ROW Directory="networks.d_Dir" Directory_Parent="One_Dir" DefaultDir="networks.d"/>
+ <ROW Directory="regid.201001.com.zerotier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="REGID2~1.ZER|regid.2010-01.com.zerotier"/>
+ <ROW Directory="tapwindows_Dir" Directory_Parent="One_Dir" DefaultDir="TAP-WI~1|tap-windows"/>
+ <ROW Directory="x64_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x64"/>
+ <ROW Directory="x86_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x86"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
+ <ROW Component="AI_CustomARPName" ComponentId="{A4BB4E68-0DD2-4052-BE60-CDCCB9BAC409}" Directory_="APPDIR" Attributes="4" KeyPath="DisplayName" Options="1"/>
+ <ROW Component="AI_DisableModify" ComponentId="{020DCABD-5D56-49B9-AF48-F07F0B55E590}" Directory_="APPDIR" Attributes="4" KeyPath="NoModify" Options="1"/>
+ <ROW Component="AI_ExePath" ComponentId="{8E02B36C-7A19-429B-A93E-77A9261AC918}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
+ <ROW Component="Hardcodet.Wpf.TaskbarNotification.dll" ComponentId="{BEA825AF-2555-44AF-BE40-47FFC16DCBA6}" Directory_="APPDIR" Attributes="0" KeyPath="Hardcodet.Wpf.TaskbarNotification.dll"/>
+ <ROW Component="Newtonsoft.Json.dll" ComponentId="{0B2F229D-5425-42FB-9E28-F6D25AB2B4B5}" Directory_="APPDIR" Attributes="0" KeyPath="Newtonsoft.Json.dll"/>
+ <ROW Component="ProductInformation" ComponentId="{DB078D04-EA8E-4A7C-9001-89BAD932F9D9}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
+ <ROW Component="ZeroTierOne.exe" ComponentId="{18B51525-77BF-4FD9-9C18-A10D4CFC25BA}" Directory_="APPDIR" Attributes="0" KeyPath="ZeroTierOne.exe"/>
+ <ROW Component="copyutil.exe" ComponentId="{9B9E89FB-81CB-4500-978B-11E2FA81B5B4}" Directory_="APPDIR" Attributes="0" KeyPath="copyutil.exe"/>
+ <ROW Component="networks.d" ComponentId="{EF54D0DF-889F-41DC-AF5C-4E7F96AB1C8B}" Directory_="networks.d_Dir" Attributes="0"/>
+ <ROW Component="regid.201001.com.zerotier" ComponentId="{A39C80FC-6A8F-454F-9052-10DAC3C3B139}" Directory_="regid.201001.com.zerotier_Dir" Attributes="0"/>
+ <ROW Component="segoeui.ttf" ComponentId="{9F415308-A118-419F-AD8A-678DEA856B78}" Directory_="FontsFolder" Attributes="144" Type="0"/>
+ <ROW Component="zerotierone_x64.exe" ComponentId="{DFCFB72D-B055-4E60-B6D8-81FF585C2183}" Directory_="One_Dir" Attributes="256" Condition="VersionNT64" KeyPath="zerotierone_x64.exe"/>
+ <ROW Component="zerotierone_x86.exe" ComponentId="{5D2F3366-4FE1-40A4-A81A-66C49FA11F1C}" Directory_="One_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="zerotierone_x86.exe"/>
+ <ROW Component="zttap300.cat_1" ComponentId="{9F913E48-095B-4EA3-98DA-EDAB1593F3E3}" Directory_="x86_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="zttap300.cat_3" Type="0"/>
+ <ROW Component="zttap300.inf" ComponentId="{D4839F5E-FB94-41CB-9B1B-177A97ADC904}" Directory_="x64_Dir" Attributes="256" Condition="VersionNT64" KeyPath="zttap300.inf"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
+ <ROW Feature="ZeroTierOne" Title="MainFeature" Description="ZeroTier One" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="AI_CustomARPName AI_DisableModify AI_ExePath Hardcodet.Wpf.TaskbarNotification.dll Newtonsoft.Json.dll ProductInformation ZeroTierOne.exe copyutil.exe networks.d regid.201001.com.zerotier segoeui.ttf zerotierone_x64.exe zerotierone_x86.exe zttap300.cat_1"/>
+ <ROW Feature="zttap300" Feature_Parent="ZeroTierOne" Title="zttap300" Description="ZeroTier Virtual Network Port Driver" Display="1" Level="1" Directory_="APPDIR" Attributes="16" Components="zttap300.inf"/>
+ <ATTRIBUTE name="CurrentFeature" value="ZeroTierOne"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
+ <ROW File="Hardcodet.Wpf.TaskbarNotification.dll" Component_="Hardcodet.Wpf.TaskbarNotification.dll" FileName="HARDCO~1.DLL|Hardcodet.Wpf.TaskbarNotification.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\WinUI\bin\Release\Hardcodet.Wpf.TaskbarNotification.dll" SelfReg="false" NextFile="segoeui.ttf" DigSign="true"/>
+ <ROW File="Newtonsoft.Json.dll" Component_="Newtonsoft.Json.dll" FileName="NEWTON~1.DLL|Newtonsoft.Json.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\WinUI\bin\Release\Newtonsoft.Json.dll" SelfReg="false" NextFile="copyutil.exe" DigSign="true"/>
+ <ROW File="ZeroTierOne.exe" Component_="ZeroTierOne.exe" FileName="ZEROTI~1.EXE|ZeroTier One.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\WinUI\bin\Release\ZeroTier One.exe" SelfReg="false" NextFile="zttap300.cat_2" DigSign="true"/>
+ <ROW File="copyutil.exe" Component_="copyutil.exe" FileName="copyutil.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\copyutil\bin\Release\copyutil.exe" SelfReg="false" NextFile="Hardcodet.Wpf.TaskbarNotification.dll" DigSign="true"/>
+ <ROW File="segoeui.ttf" Component_="segoeui.ttf" FileName="segoeui.ttf" Attributes="0" SourcePath="..\..\..\windows\WinUI\Fonts\segoeui.ttf" SelfReg="false" NextFile="segoeuib.ttf"/>
+ <ROW File="segoeuib.ttf" Component_="segoeui.ttf" FileName="segoeuib.ttf" Attributes="0" SourcePath="..\..\..\windows\WinUI\Fonts\segoeuib.ttf" SelfReg="false" NextFile="segoeuii.ttf"/>
+ <ROW File="segoeuii.ttf" Component_="segoeui.ttf" FileName="segoeuii.ttf" Attributes="0" SourcePath="..\..\..\windows\WinUI\Fonts\segoeuii.ttf" SelfReg="false" NextFile="segoeuiz.ttf"/>
+ <ROW File="segoeuiz.ttf" Component_="segoeui.ttf" FileName="segoeuiz.ttf" Attributes="0" SourcePath="..\..\..\windows\WinUI\Fonts\segoeuiz.ttf" SelfReg="false"/>
+ <ROW File="zerotierone_x64.exe" Component_="zerotierone_x64.exe" FileName="ZEROTI~2.EXE|zerotier-one_x64.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\Build\x64\Release\zerotier-one_x64.exe" SelfReg="false" NextFile="ZeroTierOne.exe" DigSign="true"/>
+ <ROW File="zerotierone_x86.exe" Component_="zerotierone_x86.exe" FileName="ZEROTI~1.EXE|zerotier-one_x86.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\Build\Win32\Release\zerotier-one_x86.exe" SelfReg="false" NextFile="zerotierone_x64.exe" DigSign="true"/>
+ <ROW File="zttap300.cat_2" Component_="zttap300.inf" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.cat" SelfReg="false" NextFile="zttap300.sys_2"/>
+ <ROW File="zttap300.cat_3" Component_="zttap300.cat_1" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.cat" SelfReg="false" NextFile="zttap300.sys_3"/>
+ <ROW File="zttap300.inf" Component_="zttap300.inf" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.inf" SelfReg="false" NextFile="zttap300.cat_3"/>
+ <ROW File="zttap300.inf_1" Component_="zttap300.cat_1" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.inf" SelfReg="false" NextFile="Newtonsoft.Json.dll"/>
+ <ROW File="zttap300.sys_2" Component_="zttap300.inf" FileName="zttap300.sys" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.sys" SelfReg="false" NextFile="zttap300.inf"/>
+ <ROW File="zttap300.sys_3" Component_="zttap300.cat_1" FileName="zttap300.sys" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.sys" SelfReg="false" NextFile="zttap300.inf_1"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.AiPersistentDataComponent">
+ <ROW PersistentRow="segoeui.ttf" Type="0" Condition="1"/>
+ <ROW PersistentRow="segoeuib.ttf" Type="0" Condition="1"/>
+ <ROW PersistentRow="segoeuii.ttf" Type="0" Condition="1"/>
+ <ROW PersistentRow="segoeuiz.ttf" Type="0" Condition="1"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent">
+ <ROW BootstrOptKey="GlobalOptions" GeneralOptions="qh" DownloadFolder="[AppDataFolder][|Manufacturer]\[|ProductName]\prerequisites"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.BootstrapperUISequenceComponent">
+ <ROW Action="AI_DetectSoftware" Sequence="101"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
+ <ROW BuildKey="DefaultBuild" BuildName="MSI" BuildOrder="1" BuildType="1" PackageFolder="..\..\.." PackageFileName="ZeroTier One" Languages="en" InstallationType="4" ExtUI="true" UseLargeSchema="true"/>
+ <ROW BuildKey="ExeBuild" BuildName="update" BuildOrder="2" BuildType="1" PackageFolder="..\..\.." PackageFileName="ZeroTier One" Languages="en" InstallationType="2" CabsLocation="1" CompressCabs="false" UseLzma="true" LzmaMethod="2" LzmaCompressionLevel="4" PackageType="1" FilesInsideExe="true" ExeIconPath="..\..\..\artwork\ZeroTierIcon.ico" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" MsiCmdLine="/qn" ExtUI="true" UseLargeSchema="true" ExeName="zt1_update_2_1,2_[|ProductVersion]_0"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.CacheComponent">
+ <ATTRIBUTE name="Enable" value="false"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.ChainedPackageComponent">
+ <ROW ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Order="1" Options="110" InstallCondition="(NOT Installed) AND VersionNT64" MaintenanceCondition="FALSE" RemoveCondition="REMOVE=&quot;ALL&quot; AND VersionNT64"/>
+ <ROW ChainedPackage="ZeroTierOne_NDIS6_x86.msi" Order="2" Options="110" InstallCondition="(NOT Installed) AND (NOT VersionNT64)" MaintenanceCondition="FALSE" RemoveCondition="REMOVE=&quot;ALL&quot; AND (NOT VersionNT64)"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.ChainedPackageFileComponent">
+ <ROW FileId="ZeroTierOne_NDIS6_x64.msi" ChainedPackage="ZeroTierOne_NDIS6_x64.msi" Options="1" TargetPath="ZeroTierOne_NDIS6_x64.msi" Content="..\..\bin\tap-windows-ndis6\x64\ZeroTierOne_NDIS6_x64.msi"/>
+ <ROW FileId="ZeroTierOne_NDIS6_x86.msi" ChainedPackage="ZeroTierOne_NDIS6_x86.msi" Options="1" TargetPath="ZeroTierOne_NDIS6_x86.msi" Content="..\..\bin\tap-windows-ndis6\x86\ZeroTierOne_NDIS6_x86.msi"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
+ <ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
+ <ROW Path="&lt;AI_DICTS&gt;ui_en.ail"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.DigCertStoreComponent">
+ <ROW TimeStampUrl="http://timestamp.verisign.com/scripts/timstamp.dll" SignerDescription="ZeroTier One" DescriptionUrl="https://www.zerotier.com/" SignOptions="7" SignTool="0" UseSha256="1" Thumbprint="7f01c3746df9e6c8235ea2ae38d3cdfeb185728b Subject: ZeroTier, Inc.&#10;Issuer: DigiCert EV Code Signing CA (SHA2)&#10;Valid from 11/30/2016 to 12/05/2019"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.FirewallExceptionComponent">
+ <ROW FirewallException="ZeroTierOneControl" DisplayName="ZeroTier One TCP/9993" GroupName="ZeroTierOne" Enabled="1" Scope="*" Condition="1" Profiles="7" Port="9993" Protocol="TCP"/>
+ <ROW FirewallException="ZeroTierOneUDP9993" DisplayName="ZeroTier One UDP/9993" GroupName="ZeroTierOne" Enabled="1" Scope="*" Condition="1" Profiles="7" Port="9993" Protocol="UDP"/>
+ <ROW FirewallException="ZeroTierOnex64Binary" DisplayName="ZeroTier One x64 Binary" Enabled="1" Scope="*" Condition="((?zerotierone_x64.exe=2) AND ($zerotierone_x64.exe=3))" Profiles="0" AppPath="[#zerotierone_x64.exe]" Port="*" Protocol="ANY"/>
+ <ROW FirewallException="ZeroTierOnex86Binary" DisplayName="ZeroTier One x86 Binary" Enabled="1" Scope="*" Condition="((?zerotierone_x86.exe=2) AND ($zerotierone_x86.exe=3))" Profiles="0" AppPath="[#zerotierone_x86.exe]" Port="*" Protocol="ANY"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.FragmentComponent">
+ <ROW Fragment="CommonUI.aip" Path="&lt;AI_FRAGS&gt;CommonUI.aip"/>
+ <ROW Fragment="MaintenanceTypeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceTypeDlg.aip"/>
+ <ROW Fragment="MaintenanceWelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\MaintenanceWelcomeDlg.aip"/>
+ <ROW Fragment="SequenceDialogs.aip" Path="&lt;AI_THEMES&gt;classic\fragments\SequenceDialogs.aip"/>
+ <ROW Fragment="Sequences.aip" Path="&lt;AI_FRAGS&gt;Sequences.aip"/>
+ <ROW Fragment="StaticUIStrings.aip" Path="&lt;AI_FRAGS&gt;StaticUIStrings.aip"/>
+ <ROW Fragment="UI.aip" Path="&lt;AI_THEMES&gt;classic\fragments\UI.aip"/>
+ <ROW Fragment="Validation.aip" Path="&lt;AI_FRAGS&gt;Validation.aip"/>
+ <ROW Fragment="VerifyRemoveDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRemoveDlg.aip"/>
+ <ROW Fragment="VerifyRepairDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\VerifyRepairDlg.aip"/>
+ <ROW Fragment="WelcomeDlg.aip" Path="&lt;AI_THEMES&gt;classic\fragments\WelcomeDlg.aip"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiActionTextComponent">
+ <ROW Action="AI_AiBackupImmediate" Description="Preparing backup operation" DescriptionLocId="ActionText.Description.AI_AiBackupImmediate" Template="Path: [1]" TemplateLocId="ActionText.Template.AI_AiBackupImmediate"/>
+ <ROW Action="AI_AiBackupRollback" Description="Rollback backup" DescriptionLocId="ActionText.Description.AI_AiBackupRollback" Template="Path: [1]" TemplateLocId="ActionText.Template.AI_AiBackupRollback"/>
+ <ROW Action="AI_AiRestoreDeferred" Description="Executing restore operation" DescriptionLocId="ActionText.Description.AI_AiRestoreDeferred" Template="Path: [1]" TemplateLocId="ActionText.Template.AI_AiRestoreDeferred"/>
+ <ROW Action="AI_AiRestoreDeferredImpersonate" Description="Executing restore operation" DescriptionLocId="ActionText.Description.AI_AiRestoreDeferred" Template="Path: [1]" TemplateLocId="ActionText.Template.AI_AiRestoreDeferred"/>
+ <ROW Action="AI_AiRestoreRollback" Description="Rollback restore" DescriptionLocId="ActionText.Description.AI_AiRestoreRollback" Template="Path: [1]" TemplateLocId="ActionText.Template.AI_AiRestoreRollback"/>
+ <ROW Action="AI_DeleteLzma" Description="Deleting files extracted from archive" DescriptionLocId="ActionText.Description.AI_DeleteLzma" TemplateLocId="-"/>
+ <ROW Action="AI_DeleteRLzma" Description="Deleting files extracted from archive" DescriptionLocId="ActionText.Description.AI_DeleteLzma" TemplateLocId="-"/>
+ <ROW Action="AI_ExtractFiles" Description="Extracting files from archive" DescriptionLocId="ActionText.Description.AI_ExtractLzma" TemplateLocId="-"/>
+ <ROW Action="AI_ExtractLzma" Description="Extracting files from archive" DescriptionLocId="ActionText.Description.AI_ExtractLzma" TemplateLocId="-"/>
+ <ROW Action="AI_FwConfig" Description="Executing Windows Firewall configurations" DescriptionLocId="ActionText.Description.AI_FwConfig" Template="Configuring Windows Firewall rule: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_FwConfig"/>
+ <ROW Action="AI_FwInstall" Description="Generating actions to configure Windows Firewall" DescriptionLocId="ActionText.Description.AI_FwInstall"/>
+ <ROW Action="AI_FwRemove" Description="Executing Windows Firewall configurations" DescriptionLocId="ActionText.Description.AI_FwRemove" Template="Configuring Windows Firewall rule: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_FwRemove"/>
+ <ROW Action="AI_FwRollback" Description="Rolling back Windows Firewall configurations." DescriptionLocId="ActionText.Description.AI_FwRollback" Template="Rolling back Windows Firewall configurations." TemplateLocId="ActionText.Template.AI_FwRollback"/>
+ <ROW Action="AI_FwUninstall" Description="Generating actions to configure Windows Firewall" DescriptionLocId="ActionText.Description.AI_FwUninstall"/>
+ <ROW Action="AI_TxtUpdaterCommit" Description="Commit text file changes. " DescriptionLocId="ActionText.Description.AI_TxtUpdaterCommit" Template="Commit text file changes." TemplateLocId="ActionText.Template.AI_TxtUpdaterCommit"/>
+ <ROW Action="AI_TxtUpdaterConfig" Description="Executing text file updates" DescriptionLocId="ActionText.Description.AI_TxtUpdaterConfig" Template="Updating text file: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_TxtUpdaterConfig"/>
+ <ROW Action="AI_TxtUpdaterInstall" Description="Generating actions to configure text files updates" DescriptionLocId="ActionText.Description.AI_TxtUpdaterInstall"/>
+ <ROW Action="AI_TxtUpdaterRollback" Description="Rolling back text file changes. " DescriptionLocId="ActionText.Description.AI_TxtUpdaterRollback" Template="Rolling back text file changes." TemplateLocId="ActionText.Template.AI_TxtUpdaterRollback"/>
+ <ROW Action="AI_XmlCommit" Description="Committing XML file configurations." DescriptionLocId="ActionText.Description.AI_XmlCommit" Template="Committing XML file configurations." TemplateLocId="ActionText.Template.AI_XmlCommit"/>
+ <ROW Action="AI_XmlConfig" Description="Executing XML file configurations" DescriptionLocId="ActionText.Description.AI_XmlConfig" Template="Configuring XML file: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_XmlConfig"/>
+ <ROW Action="AI_XmlInstall" Description="Generating actions to configure XML files" DescriptionLocId="ActionText.Description.AI_XmlInstall"/>
+ <ROW Action="AI_XmlRemove" Description="Executing XML file configurations" DescriptionLocId="ActionText.Description.AI_XmlRemove" Template="Configuring XML file: &quot;[1]&quot;" TemplateLocId="ActionText.Template.AI_XmlRemove"/>
+ <ROW Action="AI_XmlRollback" Description="Rolling back XML file configurations." DescriptionLocId="ActionText.Description.AI_XmlRollback" Template="Rolling back XML file configurations." TemplateLocId="ActionText.Template.AI_XmlRollback"/>
+ <ROW Action="AI_XmlUninstall" Description="Generating actions to configure XML files" DescriptionLocId="ActionText.Description.AI_XmlUninstall"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiAppSearchComponent">
+ <ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_CU" Builds="ExeBuild"/>
+ <ROW Property="AI_SETUPEXEPATH" Signature_="AI_EXE_PATH_LM" Builds="ExeBuild"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiBinaryComponent">
+ <ROW Name="ExternalUICleaner.dll" SourcePath="&lt;AI_CUSTACTS&gt;ExternalUICleaner.dll"/>
+ <ROW Name="NetFirewall.dll" SourcePath="&lt;AI_CUSTACTS&gt;NetFirewall.dll"/>
+ <ROW Name="Prereq.dll" SourcePath="&lt;AI_CUSTACTS&gt;Prereq.dll"/>
+ <ROW Name="ResourceCleaner.dll" SourcePath="&lt;AI_CUSTACTS&gt;ResourceCleaner.dll"/>
+ <ROW Name="SoftwareDetector.dll" SourcePath="&lt;AI_CUSTACTS&gt;SoftwareDetector.dll"/>
+ <ROW Name="TxtUpdater.dll" SourcePath="&lt;AI_CUSTACTS&gt;TxtUpdater.dll"/>
+ <ROW Name="aicustact.dll" SourcePath="&lt;AI_CUSTACTS&gt;aicustact.dll"/>
+ <ROW Name="chainersupport.dll" SourcePath="&lt;AI_CUSTACTS&gt;chainersupport.dll"/>
+ <ROW Name="lzmaextractor.dll" SourcePath="&lt;AI_CUSTACTS&gt;lzmaextractor.dll"/>
+ <ROW Name="msichainer.exe" SourcePath="&lt;AI_CUSTACTS&gt;msichainer.exe"/>
+ <ROW Name="xmlCfg.dll" SourcePath="&lt;AI_CUSTACTS&gt;xmlCfg.dll"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiConditionComponent">
+ <ROW Feature_="zttap300" Level="0" Condition="((VersionNT &lt; 500) OR (NOT VersionNT))"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiControlComponent">
+ <ROW Dialog_="WelcomeDlg" Control="WelcomeDlgDialogInitializer" Type="DialogInitializer" X="0" Y="0" Width="0" Height="0" Attributes="0" Order="-1" TextLocId="-" HelpLocId="-" ExtDataLocId="-"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiControlEventComponent">
+ <ROW Dialog_="WelcomeDlg" Control_="Next" Event="EndDialog" Argument="Return" Condition="AI_INSTALL" Ordering="1"/>
+ <ROW Dialog_="MaintenanceWelcomeDlg" Control_="Next" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="99"/>
+ <ROW Dialog_="CustomizeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_MAINT" Ordering="101"/>
+ <ROW Dialog_="CustomizeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT" Ordering="1"/>
+ <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_MAINT" Ordering="198"/>
+ <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="202"/>
+ <ROW Dialog_="MaintenanceTypeDlg" Control_="ChangeButton" Event="NewDialog" Argument="CustomizeDlg" Condition="AI_MAINT" Ordering="501"/>
+ <ROW Dialog_="MaintenanceTypeDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceWelcomeDlg" Condition="AI_MAINT" Ordering="1"/>
+ <ROW Dialog_="MaintenanceTypeDlg" Control_="RemoveButton" Event="NewDialog" Argument="VerifyRemoveDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="601"/>
+ <ROW Dialog_="VerifyRemoveDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="1"/>
+ <ROW Dialog_="MaintenanceTypeDlg" Control_="RepairButton" Event="NewDialog" Argument="VerifyRepairDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="601"/>
+ <ROW Dialog_="VerifyRepairDlg" Control_="Back" Event="NewDialog" Argument="MaintenanceTypeDlg" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="1"/>
+ <ROW Dialog_="VerifyRepairDlg" Control_="Repair" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Repair&quot;" Ordering="399" Options="1"/>
+ <ROW Dialog_="VerifyRemoveDlg" Control_="Remove" Event="EndDialog" Argument="Return" Condition="AI_MAINT AND InstallMode=&quot;Remove&quot;" Ordering="299" Options="1"/>
+ <ROW Dialog_="PatchWelcomeDlg" Control_="Next" Event="NewDialog" Argument="VerifyReadyDlg" Condition="AI_PATCH" Ordering="201"/>
+ <ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>
+ <ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>
+ <ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>
+ <ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfRbDiskDlg" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST=&quot;P&quot; OR NOT PROMPTROLLBACKCOST)" Ordering="2" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="Next" Event="EnableRollback" Argument="False" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST=&quot;D&quot;" Ordering="3" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfDiskDlg" Condition="AI_INSTALL AND ( (OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST=&quot;F&quot;) )" Ordering="4" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[AI_ButtonText_Next_Orig]" Argument="[ButtonText_Next]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[ButtonText_Next]" Argument="[[AI_CommitButton]]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[AI_Text_Next_Orig]" Argument="[Text_Next]" Condition="AI_INSTALL" Ordering="2" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="WelcomeDlgDialogInitializer" Event="[Text_Next]" Argument="[Text_Install]" Condition="AI_INSTALL" Ordering="3" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="Back" Event="[ButtonText_Next]" Argument="[AI_ButtonText_Next_Orig]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
+ <ROW Dialog_="WelcomeDlg" Control_="Back" Event="[Text_Next]" Argument="[AI_Text_Next_Orig]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
+ <ROW Dialog_="FatalError" Control_="Finish" Event="DoAction" Argument="AI_AiBackupCleanup" Condition="1" Ordering="102"/>
+ <ROW Dialog_="UserExit" Control_="Finish" Event="DoAction" Argument="AI_AiBackupCleanup" Condition="1" Ordering="101"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
+ <ROW Directory_="networks.d_Dir" Component_="networks.d" ManualDelete="false"/>
+ <ROW Directory_="regid.201001.com.zerotier_Dir" Component_="regid.201001.com.zerotier" ManualDelete="false"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
+ <ROW Action="AI_AiBackupCleanup" Type="1" Source="ResourceCleaner.dll" Target="OnAiBackupCleanup" WithoutSeq="true"/>
+ <ROW Action="AI_AiBackupImmediate" Type="1" Source="ResourceCleaner.dll" Target="OnAiBackupImmediate"/>
+ <ROW Action="AI_AiBackupRollback" Type="11521" Source="ResourceCleaner.dll" Target="OnAiBackupRollback"/>
+ <ROW Action="AI_AiRestoreDeferred" Type="11265" Source="ResourceCleaner.dll" Target="OnAiRestoreDeferred"/>
+ <ROW Action="AI_AiRestoreDeferredImpersonate" Type="9217" Source="ResourceCleaner.dll" Target="OnAiRestoreDeferredImpersonate"/>
+ <ROW Action="AI_AiRestoreRollback" Type="11521" Source="ResourceCleaner.dll" Target="OnAiRestoreRollback" WithoutSeq="true"/>
+ <ROW Action="AI_AppSearchEx" Type="1" Source="Prereq.dll" Target="DoAppSearchEx"/>
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH_ORIGINAL" Target="[AI_SETUPEXEPATH]"/>
+ <ROW Action="AI_CommitChainers" Type="11841" Source="chainersupport.dll" Target="CommitChainedPackages" WithoutSeq="true"/>
+ <ROW Action="AI_DATA_SETTER" Type="51" Source="CustomActionData" Target="[~]"/>
+ <ROW Action="AI_DATA_SETTER_1" Type="51" Source="CustomActionData" Target="[~]"/>
+ <ROW Action="AI_DATA_SETTER_2" Type="51" Source="CustomActionData" Target="[~]"/>
+ <ROW Action="AI_DATA_SETTER_3" Type="51" Source="CustomActionData" Target="[~]"/>
+ <ROW Action="AI_DATA_SETTER_4" Type="51" Source="AI_ExtractFiles" Target="[AI_SETUPEXEPATH]"/>
+ <ROW Action="AI_DATA_SETTER_6" Type="51" Source="CustomActionData" Target="ZeroTier One.exe"/>
+ <ROW Action="AI_DOWNGRADE" Type="19" Target="4010"/>
+ <ROW Action="AI_DeleteCadLzma" Type="51" Source="AI_DeleteLzma" Target="[AI_SETUPEXEPATH]"/>
+ <ROW Action="AI_DeleteLzma" Type="1025" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
+ <ROW Action="AI_DeleteRCadLzma" Type="51" Source="AI_DeleteRLzma" Target="[AI_SETUPEXEPATH]"/>
+ <ROW Action="AI_DeleteRLzma" Type="1281" Source="lzmaextractor.dll" Target="DeleteLZMAFiles"/>
+ <ROW Action="AI_DetectSoftware" Type="257" Source="SoftwareDetector.dll" Target="OnDetectSoftware"/>
+ <ROW Action="AI_DoRemoveExternalUIStub" Type="3585" Source="ExternalUICleaner.dll" Target="DoRemoveExternalUIStub" WithoutSeq="true"/>
+ <ROW Action="AI_DpiContentScale" Type="1" Source="aicustact.dll" Target="DpiContentScale"/>
+ <ROW Action="AI_EnableDebugLog" Type="321" Source="aicustact.dll" Target="EnableDebugLog"/>
+ <ROW Action="AI_EstimateExtractFiles" Type="1" Source="Prereq.dll" Target="EstimateExtractFiles"/>
+ <ROW Action="AI_ExtractCadLzma" Type="51" Source="AI_ExtractLzma" Target="[AI_SETUPEXEPATH]"/>
+ <ROW Action="AI_ExtractFiles" Type="1025" Source="Prereq.dll" Target="ExtractSourceFiles" AdditionalSeq="AI_DATA_SETTER_4"/>
+ <ROW Action="AI_ExtractLzma" Type="1025" Source="lzmaextractor.dll" Target="ExtractLZMAFiles"/>
+ <ROW Action="AI_FindExeLzma" Type="1" Source="lzmaextractor.dll" Target="FindEXE"/>
+ <ROW Action="AI_FwConfig" Type="11265" Source="NetFirewall.dll" Target="OnFwConfig" WithoutSeq="true"/>
+ <ROW Action="AI_FwInstall" Type="1" Source="NetFirewall.dll" Target="OnFwInstall" AdditionalSeq="AI_DATA_SETTER_2"/>
+ <ROW Action="AI_FwRemove" Type="11265" Source="NetFirewall.dll" Target="OnFwRemove" WithoutSeq="true"/>
+ <ROW Action="AI_FwRollback" Type="11521" Source="NetFirewall.dll" Target="OnFwRollback" WithoutSeq="true"/>
+ <ROW Action="AI_FwUninstall" Type="1" Source="NetFirewall.dll" Target="OnFwUninstall" AdditionalSeq="AI_DATA_SETTER_3"/>
+ <ROW Action="AI_GetArpIconPath" Type="1" Source="aicustact.dll" Target="GetArpIconPath"/>
+ <ROW Action="AI_InstallModeCheck" Type="1" Source="aicustact.dll" Target="UpdateInstallMode" WithoutSeq="true"/>
+ <ROW Action="AI_LaunchApp" Type="1" Source="aicustact.dll" Target="[#ZeroTierOne.exe]"/>
+ <ROW Action="AI_PREPARE_UPGRADE" Type="65" Source="aicustact.dll" Target="PrepareUpgrade"/>
+ <ROW Action="AI_PrepareChainers" Type="1" Source="chainersupport.dll" Target="PrepareChainedPackages"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Type="51" Source="AI_SETUPEXEPATH" Target="[AI_SETUPEXEPATH_ORIGINAL]"/>
+ <ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
+ <ROW Action="AI_RemoveExternalUIStub" Type="1" Source="ExternalUICleaner.dll" Target="RemoveExternalUIStub"/>
+ <ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
+ <ROW Action="AI_RollbackChainers" Type="11585" Source="chainersupport.dll" Target="RollbackChainedPackages" WithoutSeq="true"/>
+ <ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
+ <ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
+ <ROW Action="AI_TxtUpdaterCommit" Type="11777" Source="TxtUpdater.dll" Target="OnTxtUpdaterCommit" WithoutSeq="true"/>
+ <ROW Action="AI_TxtUpdaterConfig" Type="11265" Source="TxtUpdater.dll" Target="OnTxtUpdaterConfig" WithoutSeq="true"/>
+ <ROW Action="AI_TxtUpdaterInstall" Type="1" Source="TxtUpdater.dll" Target="OnTxtUpdaterInstall"/>
+ <ROW Action="AI_TxtUpdaterRollback" Type="11521" Source="TxtUpdater.dll" Target="OnTxtUpdaterRollback" WithoutSeq="true"/>
+ <ROW Action="AI_XmlCommit" Type="11777" Source="xmlCfg.dll" Target="OnXmlCommit" WithoutSeq="true"/>
+ <ROW Action="AI_XmlConfig" Type="11265" Source="xmlCfg.dll" Target="OnXmlConfig" WithoutSeq="true"/>
+ <ROW Action="AI_XmlInstall" Type="1" Source="xmlCfg.dll" Target="OnXmlInstall" AdditionalSeq="AI_DATA_SETTER"/>
+ <ROW Action="AI_XmlRemove" Type="11265" Source="xmlCfg.dll" Target="OnXmlRemove" WithoutSeq="true"/>
+ <ROW Action="AI_XmlRollback" Type="11521" Source="xmlCfg.dll" Target="OnXmlRollback" WithoutSeq="true"/>
+ <ROW Action="AI_XmlUninstall" Type="1" Source="xmlCfg.dll" Target="OnXmlUninstall" AdditionalSeq="AI_DATA_SETTER_1"/>
+ <ROW Action="SET_APPDIR" Type="307" Source="APPDIR" Target="[ProgramFilesFolder][Manufacturer]\[ProductName]" MultiBuildTarget="DefaultBuild:[ProgramFilesFolder]ZeroTier\One"/>
+ <ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]" MultiBuildTarget="DefaultBuild:[ProgramMenuFolder]"/>
+ <ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
+ <ROW Action="TapDeviceRemove32" Type="3154" Source="zerotierone_x86.exe" Target="-D"/>
+ <ROW Action="TapDeviceRemove64" Type="3154" Source="zerotierone_x64.exe" Target="-D"/>
+ <ROW Action="TerminateUI" Type="65" Source="aicustact.dll" Target="StopProcess" Options="1" AdditionalSeq="AI_DATA_SETTER_6"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiEmbeddedChainerComponent">
+ <ROW MsiEmbeddedChainer="msichainer.exe" Condition="VersionMsi &gt;= &quot;4.05&quot;" CommandLine="[AI_CHAINER_CMD_LINE]" Source="msichainer.exe" Type="2"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiEnvComponent">
+ <ROW Environment="Path" Name="=-*Path" Value="[~];[APPDIR]" Component_="ZeroTierOne.exe"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiFontsComponent">
+ <ROW File_="segoeui.ttf"/>
+ <ROW File_="segoeuib.ttf"/>
+ <ROW File_="segoeuii.ttf"/>
+ <ROW File_="segoeuiz.ttf"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
+ <ROW Name="ZeroTierIcon.exe" SourcePath="..\..\..\artwork\ZeroTierIcon.ico" Index="0"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
+ <ROW Action="AI_DOWNGRADE" Condition="AI_NEWERPRODUCTFOUND AND (UILevel &lt;&gt; 5)" Sequence="210"/>
+ <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
+ <ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1503"/>
+ <ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE=&quot;No&quot; AND (Not Installed)" Sequence="1399"/>
+ <ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
+ <ROW Action="AI_XmlInstall" Condition="(REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5103"/>
+ <ROW Action="AI_DATA_SETTER" Condition="(REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5102"/>
+ <ROW Action="AI_XmlUninstall" Condition="(REMOVE)" Sequence="3102"/>
+ <ROW Action="AI_DATA_SETTER_1" Condition="(REMOVE)" Sequence="3101"/>
+ <ROW Action="InstallFinalize" Sequence="6600" SeqType="0" MsiKey="InstallFinalize"/>
+ <ROW Action="AI_RemoveExternalUIStub" Condition="(REMOVE=&quot;ALL&quot;) AND ((VersionNT &gt; 500) OR((VersionNT = 500) AND (ServicePackLevel &gt;= 4)))" Sequence="1502"/>
+ <ROW Action="AI_GetArpIconPath" Sequence="1402"/>
+ <ROW Action="TapDeviceRemove32" Condition="( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) AND NOT UPGRADINGPRODUCTCODE ) AND ( NOT VersionNT64 )" Sequence="1603"/>
+ <ROW Action="TapDeviceRemove64" Condition="( Installed AND ( REMOVE = &quot;ALL&quot; OR AI_INSTALL_MODE = &quot;Remove&quot; ) AND NOT UPGRADINGPRODUCTCODE ) AND ( VersionNT64 )" Sequence="1604"/>
+ <ROW Action="AI_FwInstall" Condition="(VersionNT &gt;= 501) AND (REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5802"/>
+ <ROW Action="AI_DATA_SETTER_2" Condition="(VersionNT &gt;= 501) AND (REMOVE &lt;&gt; &quot;ALL&quot;)" Sequence="5801"/>
+ <ROW Action="AI_FwUninstall" Condition="(VersionNT &gt;= 501) AND (REMOVE=&quot;ALL&quot;)" Sequence="1702"/>
+ <ROW Action="AI_DATA_SETTER_3" Condition="(VersionNT &gt;= 501) AND (REMOVE=&quot;ALL&quot;)" Sequence="1701"/>
+ <ROW Action="AI_DetectSoftware" Sequence="103"/>
+ <ROW Action="AI_TxtUpdaterInstall" Sequence="5101"/>
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99" Builds="ExeBuild"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="102" Builds="ExeBuild"/>
+ <ROW Action="AI_DeleteCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="199" Builds="ExeBuild"/>
+ <ROW Action="AI_DeleteRCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="198" Builds="ExeBuild"/>
+ <ROW Action="AI_ExtractCadLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="197" Builds="ExeBuild"/>
+ <ROW Action="AI_FindExeLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="196" Builds="ExeBuild"/>
+ <ROW Action="AI_ExtractLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="1549" Builds="ExeBuild"/>
+ <ROW Action="AI_DeleteRLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="1548" Builds="ExeBuild"/>
+ <ROW Action="AI_DeleteLzma" Condition="SETUPEXEDIR=&quot;&quot; AND Installed AND (REMOVE&lt;&gt;&quot;ALL&quot;) AND (AI_INSTALL_MODE&lt;&gt;&quot;Remove&quot;) AND (NOT PATCH)" Sequence="6594" Builds="ExeBuild"/>
+ <ROW Action="AI_ExtractFiles" Sequence="3998" Builds="ExeBuild"/>
+ <ROW Action="AI_DATA_SETTER_4" Sequence="3997"/>
+ <ROW Action="AI_EstimateExtractFiles" Sequence="3999" Builds="ExeBuild"/>
+ <ROW Action="TerminateUI" Sequence="1602"/>
+ <ROW Action="AI_DATA_SETTER_6" Sequence="1601"/>
+ <ROW Action="AI_AiBackupImmediate" Sequence="1401"/>
+ <ROW Action="AI_AiBackupRollback" Sequence="1501"/>
+ <ROW Action="AI_AiRestoreDeferred" Sequence="6595"/>
+ <ROW Action="AI_EnableDebugLog" Sequence="51"/>
+ <ROW Action="AI_AiRestoreDeferredImpersonate" Sequence="6596"/>
+ <ROW Action="AI_AppSearchEx" Sequence="101"/>
+ <ROW Action="AI_PrepareChainers" Condition="VersionMsi &gt;= &quot;4.05&quot;" Sequence="5851"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
+ <ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=&quot;&quot;" Sequence="749"/>
+ <ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
+ <ROW Action="AI_DpiContentScale" Sequence="52"/>
+ <ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99"/>
+ <ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="103"/>
+ <ROW Action="ExecuteAction" Sequence="1299" SeqType="0" MsiKey="ExecuteAction"/>
+ <ROW Action="AI_DetectSoftware" Sequence="102"/>
+ <ROW Action="AI_EnableDebugLog" Sequence="51"/>
+ <ROW Action="AI_AppSearchEx" Sequence="101"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiLaunchConditionsComponent">
+ <ROW Condition="( Version9X OR ( NOT VersionNT64 ) OR ( VersionNT64 AND ((VersionNT64 &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2) OR (MsiNTProductType &lt;&gt; 1)) AND ((VersionNT64 &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2) OR (MsiNTProductType = 1)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNT64Display]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT64" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="( Version9X OR VersionNT64 OR ( VersionNT AND ((VersionNT &lt;&gt; 501) OR (ServicePackLevel &lt;&gt; 3)) AND ((VersionNT &lt;&gt; 502) OR (ServicePackLevel &lt;&gt; 2)) ) )" Description="[ProductName] cannot be installed on the following Windows versions: [WindowsTypeNTDisplay]." DescriptionLocId="AI.LaunchCondition.NoSpecificNT" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="(VersionNT &lt;&gt; 400)" Description="[ProductName] cannot be installed on [WindowsTypeNT40Display]." DescriptionLocId="AI.LaunchCondition.NoNT40" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
+ <ROW Condition="(VersionNT &lt;&gt; 500)" Description="[ProductName] cannot be installed on [WindowsTypeNT50Display]." DescriptionLocId="AI.LaunchCondition.NoNT50" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
+ <ROW Condition="(VersionNT64 OR ((VersionNT &lt;&gt; 501) OR (ServicePackLevel = 3))) AND ((VersionNT &lt;&gt; 502) OR (ServicePackLevel = 2))" Description="[ProductName] cannot be installed on [WindowsTypeNT5XDisplay]." DescriptionLocId="AI.LaunchCondition.NoNT5X" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
+ <ROW Condition="AI_DETECTED_DOTNET_VERSION &gt;= AI_REQUIRED_DOTNET_VERSION" Description="[ProductName] cannot be installed on systems with .NET Framework version lower than [AI_REQUIRED_DOTNET_DISPLAY]." DescriptionLocId="AI.LaunchCondition.DotNET" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="Privileged" Description="[ProductName] requires administrative privileges to install." DescriptionLocId="AI.LaunchCondition.Privileged" IsPredefined="true" Builds="DefaultBuild"/>
+ <ROW Condition="SETUPEXEDIR OR (REMOVE=&quot;ALL&quot;)" Description="This package can only be run from a bootstrapper." DescriptionLocId="AI.LaunchCondition.RequireBootstrapper" IsPredefined="true" Builds="ExeBuild"/>
+ <ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiRegLocatorComponent">
+ <ROW Signature_="AI_EXE_PATH_CU" Root="1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
+ <ROW Signature_="AI_EXE_PATH_LM" Root="2" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiRegsComponent">
+ <ROW Registry="AI_ExePath" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Value="[AI_SETUPEXEPATH]" Component_="AI_ExePath"/>
+ <ROW Registry="Comments" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Comments" Value="[ARPCOMMENTS]" Component_="AI_CustomARPName"/>
+ <ROW Registry="Contact" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Contact" Value="[ARPCONTACT]" Component_="AI_CustomARPName"/>
+ <ROW Registry="DisplayIcon" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="DisplayIcon" Value="[ARP_ICON_PATH]" Component_="AI_CustomARPName"/>
+ <ROW Registry="DisplayName" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="DisplayName" Value="[AI_PRODUCTNAME_ARP]" Component_="AI_CustomARPName"/>
+ <ROW Registry="DisplayVersion" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="DisplayVersion" Value="[ProductVersion]" Component_="AI_CustomARPName"/>
+ <ROW Registry="HelpLink" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="HelpLink" Value="[ARPHELPLINK]" Component_="AI_CustomARPName"/>
+ <ROW Registry="HelpTelephone" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="HelpTelephone" Value="[ARPHELPTELEPHONE]" Component_="AI_CustomARPName"/>
+ <ROW Registry="InstallLocation" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="InstallLocation" Value="[APPDIR]" Component_="AI_CustomARPName"/>
+ <ROW Registry="ModifyPath" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="ModifyPath" Value="[AI_UNINSTALLER] /I [ProductCode]" Component_="AI_CustomARPName"/>
+ <ROW Registry="NoModify" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="NoModify" Value="#1" Component_="AI_DisableModify"/>
+ <ROW Registry="NoRepair" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="NoRepair" Value="#1" Component_="AI_CustomARPName"/>
+ <ROW Registry="Path" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Path" Value="[APPDIR]" Component_="ProductInformation"/>
+ <ROW Registry="Publisher" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Publisher" Value="[Manufacturer]" Component_="AI_CustomARPName"/>
+ <ROW Registry="URLInfoAbout" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="URLInfoAbout" Value="[ARPURLINFOABOUT]" Component_="AI_CustomARPName"/>
+ <ROW Registry="URLUpdateInfo" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="URLUpdateInfo" Value="[ARPURLUPDATEINFO]" Component_="AI_CustomARPName"/>
+ <ROW Registry="UninstallPath" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="UninstallPath" Value="[AI_UNINSTALLER] /x [ProductCode] AI_UNINSTALLER_CTP=1" Component_="AI_CustomARPName"/>
+ <ROW Registry="UninstallString" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="UninstallString" Value="[AI_UNINSTALLER] /x [ProductCode] AI_UNINSTALLER_CTP=1" Component_="AI_CustomARPName"/>
+ <ROW Registry="Version" Root="-1" Key="Software\[Manufacturer]\[ProductName]" Name="Version" Value="[ProductVersion]" Component_="ProductInformation"/>
+ <ROW Registry="VersionMajor" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="VersionMajor" Value="#0" Component_="AI_CustomARPName"/>
+ <ROW Registry="VersionMinor" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="VersionMinor" Value="#7" Component_="AI_CustomARPName"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiServCtrlComponent">
+ <ROW ServiceControl="zerotierone_x64.exe" Name="ZeroTierOneService" Event="163" Wait="1" Component_="zerotierone_x64.exe"/>
+ <ROW ServiceControl="zerotierone_x86.exe" Name="ZeroTierOneService" Event="163" Wait="1" Component_="zerotierone_x86.exe"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiServInstComponent">
+ <ROW ServiceInstall="zerotierone_x64.exe" Name="ZeroTierOneService" DisplayName="ZeroTier One" ServiceType="16" StartType="2" ErrorControl="32769" Component_="zerotierone_x64.exe" Description="Ethernet Virtualization Service"/>
+ <ROW ServiceInstall="zerotierone_x86.exe" Name="ZeroTierOneService" DisplayName="ZeroTier One" ServiceType="16" StartType="2" ErrorControl="32769" Component_="zerotierone_x86.exe" Description="Ethernet Virtualization Service"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
+ <ROW Shortcut="ZeroTierOne" Directory_="ProgramMenuFolder" Name="ZEROTI~1|ZeroTier One" Component_="ZeroTierOne.exe" Target="[#ZeroTierOne.exe]" Description="Ethernet Virtualization Control Panel" Hotkey="0" Icon_="ZeroTierIcon.exe" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiThemeComponent">
+ <ATTRIBUTE name="UsedTheme" value="classic"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiUpgradeComponent">
+ <ROW UpgradeCode="[|UpgradeCode]" VersionMin="0.0.1" VersionMax="[|ProductVersion]" Attributes="257" ActionProperty="OLDPRODUCTS"/>
+ <ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.PreReqSearchComponent">
+ <ROW SearchKey="UpgradeCode" SearchType="4" SearchString="{88AA80DE-14CA-4443-B024-6EC13F3EDDAD}" Order="2" Property="ZTTAP300_X86_INSTALLED"/>
+ <ROW SearchKey="_" SearchType="4" SearchString="{88AA80DE-14CA-4443-B024-6EC13F3EDDAD}" Order="1" Property="ZTTAP300_X64_INSTALLED"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.SoftwareIdentificationComponent">
+ <ATTRIBUTE name="LocalFile" value="regid.199509.com.example_ProductName.swidtag"/>
+ <ATTRIBUTE name="SystemFile" value="regid.199509.com.example_ProductName.swidtag_1"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.TxtUpdateComponent">
+ <ROW Name="Append/Create" TxtUpdateSet="zerotiercli.bat" FindPattern="@ECHO OFF&#13;&#10;if [\[][#zerotierone_x64.exe][\]] == [\[][\]] (&#13;&#10;&#9;[#zerotierone_x86.exe] -q %*&#13;&#10;) else (&#13;&#10;&#9;[#zerotierone_x64.exe] -q %*&#13;&#10;)&#13;&#10;" Options="160" Order="0" FileEncoding="0"/>
+ <ROW Name="Replace" TxtUpdateSet="zerotiercli.bat" FindPattern="YourFindText" ReplacePattern="YourReplaceText" Options="2" Order="1" FileEncoding="-1"/>
+ <ROW Name="Append/Create" TxtUpdateSet="zerotiercli1.bat" FindPattern="@ECHO OFF&#13;&#10;if [\[][#zerotierone_x64.exe][\]] == [\[][\]] (&#13;&#10;&#9;[#zerotierone_x86.exe] -i %*&#13;&#10;) else (&#13;&#10;&#9;[#zerotierone_x64.exe] -i %*&#13;&#10;)&#13;&#10;" Options="160" Order="0" FileEncoding="0"/>
+ <ROW Name="Replace" TxtUpdateSet="zerotiercli1.bat" FindPattern="YourFindText" ReplacePattern="YourReplaceText" Options="2" Order="1" FileEncoding="-1"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.TxtUpdateSetComponent">
+ <ROW Key="zerotiercli.bat" Component="regid.201001.com.zerotier" FileName="zerotier-cli.bat" Directory="APPDIR" Options="17"/>
+ <ROW Key="zerotiercli1.bat" Component="regid.201001.com.zerotier" FileName="zerotier-idtool.bat" Directory="APPDIR" Options="17"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.XmlAttributeComponent">
+ <ROW XmlAttribute="xmlnsds" XmlElement="swidsoftware_identification_tag" Name="xmlns:ds" Flags="14" Order="0" Value="http://www.w3.org/2000/09/xmldsig#"/>
+ <ROW XmlAttribute="xmlnsswid" XmlElement="swidsoftware_identification_tag" Name="xmlns:swid" Flags="14" Order="1" Value="http://standards.iso.org/iso/19770/-2/2008/schema.xsd"/>
+ <ROW XmlAttribute="xmlnsxsi" XmlElement="swidsoftware_identification_tag" Name="xmlns:xsi" Flags="14" Order="2" Value="http://www.w3.org/2001/XMLSchema-instance"/>
+ <ROW XmlAttribute="xsischemaLocation" XmlElement="swidsoftware_identification_tag" Name="xsi:schemaLocation" Flags="14" Order="3" Value="http://standards.iso.org/iso/19770/-2/2008/schema.xsd software_identification_tag.xsd"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.XmlElementComponent">
+ <ROW XmlElement="swidbuild" ParentElement="swidnumeric" Name="swid:build" Condition="1" Order="2" Flags="14" Text="6"/>
+ <ROW XmlElement="swidentitlement_required_indicator" ParentElement="swidsoftware_identification_tag" Name="swid:entitlement_required_indicator" Condition="1" Order="0" Flags="14" Text="false"/>
+ <ROW XmlElement="swidmajor" ParentElement="swidnumeric" Name="swid:major" Condition="1" Order="0" Flags="14" Text="1"/>
+ <ROW XmlElement="swidminor" ParentElement="swidnumeric" Name="swid:minor" Condition="1" Order="1" Flags="14" Text="2"/>
+ <ROW XmlElement="swidname" ParentElement="swidproduct_version" Name="swid:name" Condition="1" Order="0" Flags="14" Text="[ProductVersion]"/>
+ <ROW XmlElement="swidname_1" ParentElement="swidsoftware_creator" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc."/>
+ <ROW XmlElement="swidname_2" ParentElement="swidsoftware_licensor" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc."/>
+ <ROW XmlElement="swidname_3" ParentElement="swidtag_creator" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc."/>
+ <ROW XmlElement="swidnumeric" ParentElement="swidproduct_version" Name="swid:numeric" Condition="1" Order="1" Flags="14"/>
+ <ROW XmlElement="swidproduct_title" ParentElement="swidsoftware_identification_tag" Name="swid:product_title" Condition="1" Order="1" Flags="14" Text="[ProductName]"/>
+ <ROW XmlElement="swidproduct_version" ParentElement="swidsoftware_identification_tag" Name="swid:product_version" Condition="1" Order="2" Flags="14"/>
+ <ROW XmlElement="swidregid" ParentElement="swidsoftware_creator" Name="swid:regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
+ <ROW XmlElement="swidregid_1" ParentElement="swidsoftware_licensor" Name="swid:regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
+ <ROW XmlElement="swidregid_2" ParentElement="swidtag_creator" Name="swid:regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
+ <ROW XmlElement="swidreview" ParentElement="swidnumeric" Name="swid:review" Condition="1" Order="3" Flags="14" Text="0"/>
+ <ROW XmlElement="swidsoftware_creator" ParentElement="swidsoftware_identification_tag" Name="swid:software_creator" Condition="1" Order="3" Flags="14"/>
+ <ROW XmlElement="swidsoftware_id" ParentElement="swidsoftware_identification_tag" Name="swid:software_id" Condition="1" Order="5" Flags="14"/>
+ <ROW XmlElement="swidsoftware_identification_tag" Name="swid:software_identification_tag" Condition="1" Order="0" Flags="14"/>
+ <ROW XmlElement="swidsoftware_licensor" ParentElement="swidsoftware_identification_tag" Name="swid:software_licensor" Condition="1" Order="4" Flags="14"/>
+ <ROW XmlElement="swidtag_creator" ParentElement="swidsoftware_identification_tag" Name="swid:tag_creator" Condition="1" Order="6" Flags="14"/>
+ <ROW XmlElement="swidtag_creator_regid" ParentElement="swidsoftware_id" Name="swid:tag_creator_regid" Condition="1" Order="1" Flags="14" Text="regid.2010-01.com.zerotier"/>
+ <ROW XmlElement="swidunique_id" ParentElement="swidsoftware_id" Name="swid:unique_id" Condition="1" Order="0" Flags="14" Text="ZeroTierOne"/>
+ </COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.XmlFileComponent">
+ <ROW XmlFile="regid.199509.com.example_ProductName.swidtag" FileName="REGID2~1.SWI|regid.2010-01.com.zerotier_ZeroTierOne.swidtag" DirProperty="APPDIR" Component="ProductInformation" RootElement="swidsoftware_identification_tag" Flags="25" Version="1.0" Encoding="UTF-8" IndentUnits="2"/>
+ <ROW XmlFile="regid.199509.com.example_ProductName.swidtag_1" FileName="REGID2~1.SWI|regid.2010-01.com.zerotier_ZeroTierOne.swidtag" DirProperty="regid.201001.com.zerotier_Dir" Component="ProductInformation" RootElement="swidsoftware_identification_tag" Flags="25" Version="1.0" Encoding="UTF-8" IndentUnits="2"/>
+ </COMPONENT>
+</DOCUMENT>
diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1 b/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1
index b29fd99d..9a0f6bac 100644
--- a/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1
+++ b/ext/installfiles/windows/chocolatey/zerotier-one/tools/chocolateyinstall.ps1
@@ -1,7 +1,7 @@
$packageName = 'zerotier-one'
$installerType = 'msi'
-$url = 'https://download.zerotier.com/RELEASES/1.1.12/dist/ZeroTier%20One.msi'
-$url64 = 'https://download.zerotier.com/RELEASES/1.1.12/dist/ZeroTier%20One.msi'
+$url = 'https://download.zerotier.com/RELEASES/1.2.4/dist/ZeroTier%20One.msi'
+$url64 = 'https://download.zerotier.com/RELEASES/1.2.4/dist/ZeroTier%20One.msi'
$silentArgs = '/quiet'
$validExitCodes = @(0,3010)
diff --git a/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec b/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec
index 473007c8..3d090a7b 100644
--- a/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec
+++ b/ext/installfiles/windows/chocolatey/zerotier-one/zerotier-one.nuspec
@@ -8,8 +8,8 @@
This is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Reference. Chocolatey uses a special version of NuGet.Core that allows us to do more than was initially possible. As such there are certain things to be aware of:
* the package xmlns schema url may cause issues with nuget.exe
-* Any of the following elements can ONLY be used by choco tools - projectSourceUrl, docsUrl, mailingListUrl, bugTrackerUrl, packageSourceUrl, provides, conflicts, replaces
-* nuget.exe can still install packages with those elements but they are ignored. Any authoring tools or commands will error on those elements
+* Any of the following elements can ONLY be used by choco tools - projectSourceUrl, docsUrl, mailingListUrl, bugTrackerUrl, packageSourceUrl, provides, conflicts, replaces
+* nuget.exe can still install packages with those elements but they are ignored. Any authoring tools or commands will error on those elements
-->
<!-- You can embed software files directly into packages, as long as you are not bound by distribution rights. -->
@@ -26,7 +26,7 @@ This is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Refe
<!-- version should MATCH as closely as possible with the underlying software -->
<!-- Is the version a prerelease of a version? https://docs.nuget.org/create/versioning#creating-prerelease-packages -->
<!-- Note that unstable versions like 0.0.1 can be considered a released version, but it's possible that one can release a 0.0.1-beta before you release a 0.0.1 version. If the version number is final, that is considered a released version and not a prerelease. -->
- <version>1.1.12</version>
+ <version>1.2.6</version>
<!-- <packageSourceUrl>Where is this Chocolatey package located (think GitHub)? packageSourceUrl is highly recommended for the community feed</packageSourceUrl>-->
<!-- owners is a poor name for maintainers of the package. It sticks around by this name for compatibility reasons. It basically means you. -->
<!--<owners>ZeroTier, Inc.</owners>-->
@@ -51,7 +51,7 @@ This is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Refe
<summary>ZeroTier One Virtual Network Endpoint for Windows</summary>
<description>ZeroTier is a smart switch for Earth with VLAN capability. See https://www.zerotier.com/ for more information.</description>
<!-- <releaseNotes>__REPLACE_OR_REMOVE__MarkDown_Okay</releaseNotes> -->
- <!-- =============================== -->
+ <!-- =============================== -->
<!-- Specifying dependencies and version ranges? https://docs.nuget.org/create/versioning#specifying-version-ranges-in-.nuspec-files -->
<!--<dependencies>
diff --git a/ext/json-parser/AUTHORS b/ext/json-parser/AUTHORS
deleted file mode 100644
index 6a5c799f..00000000
--- a/ext/json-parser/AUTHORS
+++ /dev/null
@@ -1,20 +0,0 @@
-All contributors arranged by first commit:
-
-James McLaughlin
-Alex Gartrell
-Peter Scott
-Mathias Kaerlev
-Emiel Mols
-Czarek Tomczak
-Nicholas Braden
-Ivan Kozub
-Árpád Goretity
-Igor Gnatenko
-Haïkel Guémar
-Tobias Waldekranz
-Patrick Donnelly
-Wilmer van der Gaast
-Jin Wei
-François Cartegnie
-Matthijs Boelstra
-
diff --git a/ext/json-parser/LICENSE b/ext/json-parser/LICENSE
deleted file mode 100644
index 1aee375e..00000000
--- a/ext/json-parser/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-
- Copyright (C) 2012, 2013 James McLaughlin et al. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
-
diff --git a/ext/json-parser/README.md b/ext/json-parser/README.md
deleted file mode 100644
index e0b70b6d..00000000
--- a/ext/json-parser/README.md
+++ /dev/null
@@ -1,97 +0,0 @@
-Very low footprint JSON parser written in portable ANSI C.
-
-* BSD licensed with no dependencies (i.e. just drop the C file into your project)
-* Never recurses or allocates more memory than it needs
-* Very simple API with operator sugar for C++
-
-[![Build Status](https://secure.travis-ci.org/udp/json-parser.png)](http://travis-ci.org/udp/json-parser)
-
-_Want to serialize? Check out [json-builder](https://github.com/udp/json-builder)!_
-
-Installing
-----------
-
-There is now a makefile which will produce a libjsonparser static and dynamic library. However, this
-is _not_ required to build json-parser, and the source files (`json.c` and `json.h`) should be happy
-in any build system you already have in place.
-
-
-API
----
-
- json_value * json_parse (const json_char * json,
- size_t length);
-
- json_value * json_parse_ex (json_settings * settings,
- const json_char * json,
- size_t length,
- char * error);
-
- void json_value_free (json_value *);
-
-The `type` field of `json_value` is one of:
-
-* `json_object` (see `u.object.length`, `u.object.values[x].name`, `u.object.values[x].value`)
-* `json_array` (see `u.array.length`, `u.array.values`)
-* `json_integer` (see `u.integer`)
-* `json_double` (see `u.dbl`)
-* `json_string` (see `u.string.ptr`, `u.string.length`)
-* `json_boolean` (see `u.boolean`)
-* `json_null`
-
-
-Compile-Time Options
---------------------
-
- -DJSON_TRACK_SOURCE
-
-Stores the source location (line and column number) inside each `json_value`.
-
-This is useful for application-level error reporting.
-
-
-Runtime Options
----------------
-
- settings |= json_enable_comments;
-
-Enables C-style `// line` and `/* block */` comments.
-
- size_t value_extra
-
-The amount of space (if any) to allocate at the end of each `json_value`, in
-order to give the application space to add metadata.
-
- void * (* mem_alloc) (size_t, int zero, void * user_data);
- void (* mem_free) (void *, void * user_data);
-
-Custom allocator routines. If NULL, the default `malloc` and `free` will be used.
-
-The `user_data` pointer will be forwarded from `json_settings` to allow application
-context to be passed.
-
-
-Changes in version 1.1.0
-------------------------
-
-* UTF-8 byte order marks are now skipped if present
-
-* Allows cross-compilation by honoring --host if given (@wkz)
-
-* Maximum size for error buffer is now exposed in header (@LB--)
-
-* GCC warning for `static` after `const` fixed (@batrick)
-
-* Optional support for C-style line and block comments added (@Jin-W-FS)
-
-* `name_length` field added to object values
-
-* It is now possible to retrieve the source line/column number of a parsed `json_value` when `JSON_TRACK_SOURCE` is enabled
-
-* The application may now extend `json_value` using the `value_extra` setting
-
-* Un-ambiguate pow call in the case of C++ overloaded pow (@fcartegnie)
-
-* Fix null pointer de-reference when a non-existing array is closed and no root value is present
-
-
diff --git a/ext/json-parser/json.c b/ext/json-parser/json.c
deleted file mode 100644
index 166cdcb6..00000000
--- a/ext/json-parser/json.c
+++ /dev/null
@@ -1,1012 +0,0 @@
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
- *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
- * https://github.com/udp/json-parser
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "json.h"
-
-#ifdef _MSC_VER
- #ifndef _CRT_SECURE_NO_WARNINGS
- #define _CRT_SECURE_NO_WARNINGS
- #endif
- #pragma warning(disable:4996)
-#endif
-
-const struct _json_value json_value_none;
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-
-typedef unsigned int json_uchar;
-
-static unsigned char hex_value (json_char c)
-{
- if (isdigit(c))
- return c - '0';
-
- switch (c) {
- case 'a': case 'A': return 0x0A;
- case 'b': case 'B': return 0x0B;
- case 'c': case 'C': return 0x0C;
- case 'd': case 'D': return 0x0D;
- case 'e': case 'E': return 0x0E;
- case 'f': case 'F': return 0x0F;
- default: return 0xFF;
- }
-}
-
-typedef struct
-{
- unsigned long used_memory;
-
- unsigned int uint_max;
- unsigned long ulong_max;
-
- json_settings settings;
- int first_pass;
-
- const json_char * ptr;
- unsigned int cur_line, cur_col;
-
-} json_state;
-
-static void * default_alloc (size_t size, int zero, void * user_data)
-{
- return zero ? calloc (1, size) : malloc (size);
-}
-
-static void default_free (void * ptr, void * user_data)
-{
- free (ptr);
-}
-
-static void * json_alloc (json_state * state, unsigned long size, int zero)
-{
- if ((state->ulong_max - state->used_memory) < size)
- return 0;
-
- if (state->settings.max_memory
- && (state->used_memory += size) > state->settings.max_memory)
- {
- return 0;
- }
-
- return state->settings.mem_alloc (size, zero, state->settings.user_data);
-}
-
-static int new_value (json_state * state,
- json_value ** top, json_value ** root, json_value ** alloc,
- json_type type)
-{
- json_value * value;
- int values_size;
-
- if (!state->first_pass)
- {
- value = *top = *alloc;
- *alloc = (*alloc)->_reserved.next_alloc;
-
- if (!*root)
- *root = value;
-
- switch (value->type)
- {
- case json_array:
-
- if (value->u.array.length == 0)
- break;
-
- if (! (value->u.array.values = (json_value **) json_alloc
- (state, value->u.array.length * sizeof (json_value *), 0)) )
- {
- return 0;
- }
-
- value->u.array.length = 0;
- break;
-
- case json_object:
-
- if (value->u.object.length == 0)
- break;
-
- values_size = sizeof (*value->u.object.values) * value->u.object.length;
-
- if (! (value->u.object.values = (json_object_entry *) json_alloc
- (state, values_size + ((unsigned long) value->u.object.values), 0)) )
- {
- return 0;
- }
-
- value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
-
- value->u.object.length = 0;
- break;
-
- case json_string:
-
- if (! (value->u.string.ptr = (json_char *) json_alloc
- (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
- {
- return 0;
- }
-
- value->u.string.length = 0;
- break;
-
- default:
- break;
- };
-
- return 1;
- }
-
- if (! (value = (json_value *) json_alloc
- (state, sizeof (json_value) + state->settings.value_extra, 1)))
- {
- return 0;
- }
-
- if (!*root)
- *root = value;
-
- value->type = type;
- value->parent = *top;
-
- #ifdef JSON_TRACK_SOURCE
- value->line = state->cur_line;
- value->col = state->cur_col;
- #endif
-
- if (*alloc)
- (*alloc)->_reserved.next_alloc = value;
-
- *alloc = *top = value;
-
- return 1;
-}
-
-#define whitespace \
- case '\n': ++ state.cur_line; state.cur_col = 0; \
- case ' ': case '\t': case '\r'
-
-#define string_add(b) \
- do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
-
-#define line_and_col \
- state.cur_line, state.cur_col
-
-static const long
- flag_next = 1 << 0,
- flag_reproc = 1 << 1,
- flag_need_comma = 1 << 2,
- flag_seek_value = 1 << 3,
- flag_escaped = 1 << 4,
- flag_string = 1 << 5,
- flag_need_colon = 1 << 6,
- flag_done = 1 << 7,
- flag_num_negative = 1 << 8,
- flag_num_zero = 1 << 9,
- flag_num_e = 1 << 10,
- flag_num_e_got_sign = 1 << 11,
- flag_num_e_negative = 1 << 12,
- flag_line_comment = 1 << 13,
- flag_block_comment = 1 << 14;
-
-json_value * json_parse_ex (json_settings * settings,
- const json_char * json,
- size_t length,
- char * error_buf)
-{
- json_char error [json_error_max];
- const json_char * end;
- json_value * top, * root, * alloc = 0;
- json_state state = { 0 };
- long flags;
- long num_digits = 0, num_e = 0;
- json_int_t num_fraction = 0;
-
- /* Skip UTF-8 BOM
- */
- if (length >= 3 && ((unsigned char) json [0]) == 0xEF
- && ((unsigned char) json [1]) == 0xBB
- && ((unsigned char) json [2]) == 0xBF)
- {
- json += 3;
- length -= 3;
- }
-
- error[0] = '\0';
- end = (json + length);
-
- memcpy (&state.settings, settings, sizeof (json_settings));
-
- if (!state.settings.mem_alloc)
- state.settings.mem_alloc = default_alloc;
-
- if (!state.settings.mem_free)
- state.settings.mem_free = default_free;
-
- memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
- memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
-
- state.uint_max -= 8; /* limit of how much can be added before next check */
- state.ulong_max -= 8;
-
- for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
- {
- json_uchar uchar;
- unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
- json_char * string = 0;
- unsigned int string_length = 0;
-
- top = root = 0;
- flags = flag_seek_value;
-
- state.cur_line = 1;
-
- for (state.ptr = json ;; ++ state.ptr)
- {
- json_char b = (state.ptr == end ? 0 : *state.ptr);
-
- if (flags & flag_string)
- {
- if (!b)
- { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
- goto e_failed;
- }
-
- if (string_length > state.uint_max)
- goto e_overflow;
-
- if (flags & flag_escaped)
- {
- flags &= ~ flag_escaped;
-
- switch (b)
- {
- case 'b': string_add ('\b'); break;
- case 'f': string_add ('\f'); break;
- case 'n': string_add ('\n'); break;
- case 'r': string_add ('\r'); break;
- case 't': string_add ('\t'); break;
- case 'u':
-
- if (end - state.ptr < 4 ||
- (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
- {
- sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
- goto e_failed;
- }
-
- uc_b1 = (uc_b1 << 4) | uc_b2;
- uc_b2 = (uc_b3 << 4) | uc_b4;
- uchar = (uc_b1 << 8) | uc_b2;
-
- if ((uchar & 0xF800) == 0xD800) {
- json_uchar uchar2;
-
- if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
- (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
- (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
- {
- sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
- goto e_failed;
- }
-
- uc_b1 = (uc_b1 << 4) | uc_b2;
- uc_b2 = (uc_b3 << 4) | uc_b4;
- uchar2 = (uc_b1 << 8) | uc_b2;
-
- uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
- }
-
- if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
- {
- string_add ((json_char) uchar);
- break;
- }
-
- if (uchar <= 0x7FF)
- {
- if (state.first_pass)
- string_length += 2;
- else
- { string [string_length ++] = 0xC0 | (uchar >> 6);
- string [string_length ++] = 0x80 | (uchar & 0x3F);
- }
-
- break;
- }
-
- if (uchar <= 0xFFFF) {
- if (state.first_pass)
- string_length += 3;
- else
- { string [string_length ++] = 0xE0 | (uchar >> 12);
- string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
- string [string_length ++] = 0x80 | (uchar & 0x3F);
- }
-
- break;
- }
-
- if (state.first_pass)
- string_length += 4;
- else
- { string [string_length ++] = 0xF0 | (uchar >> 18);
- string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
- string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
- string [string_length ++] = 0x80 | (uchar & 0x3F);
- }
-
- break;
-
- default:
- string_add (b);
- };
-
- continue;
- }
-
- if (b == '\\')
- {
- flags |= flag_escaped;
- continue;
- }
-
- if (b == '"')
- {
- if (!state.first_pass)
- string [string_length] = 0;
-
- flags &= ~ flag_string;
- string = 0;
-
- switch (top->type)
- {
- case json_string:
-
- top->u.string.length = string_length;
- flags |= flag_next;
-
- break;
-
- case json_object:
-
- if (state.first_pass)
- (*(json_char **) &top->u.object.values) += string_length + 1;
- else
- {
- top->u.object.values [top->u.object.length].name
- = (json_char *) top->_reserved.object_mem;
-
- top->u.object.values [top->u.object.length].name_length
- = string_length;
-
- (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
- }
-
- flags |= flag_seek_value | flag_need_colon;
- continue;
-
- default:
- break;
- };
- }
- else
- {
- string_add (b);
- continue;
- }
- }
-
- if (state.settings.settings & json_enable_comments)
- {
- if (flags & (flag_line_comment | flag_block_comment))
- {
- if (flags & flag_line_comment)
- {
- if (b == '\r' || b == '\n' || !b)
- {
- flags &= ~ flag_line_comment;
- -- state.ptr; /* so null can be reproc'd */
- }
-
- continue;
- }
-
- if (flags & flag_block_comment)
- {
- if (!b)
- { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
- goto e_failed;
- }
-
- if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
- {
- flags &= ~ flag_block_comment;
- ++ state.ptr; /* skip closing sequence */
- }
-
- continue;
- }
- }
- else if (b == '/')
- {
- if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
- { sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
- goto e_failed;
- }
-
- if (++ state.ptr == end)
- { sprintf (error, "%d:%d: EOF unexpected", line_and_col);
- goto e_failed;
- }
-
- switch (b = *state.ptr)
- {
- case '/':
- flags |= flag_line_comment;
- continue;
-
- case '*':
- flags |= flag_block_comment;
- continue;
-
- default:
- sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
- goto e_failed;
- };
- }
- }
-
- if (flags & flag_done)
- {
- if (!b)
- break;
-
- switch (b)
- {
- whitespace:
- continue;
-
- default:
-
- sprintf (error, "%d:%d: Trailing garbage: `%c`",
- state.cur_line, state.cur_col, b);
-
- goto e_failed;
- };
- }
-
- if (flags & flag_seek_value)
- {
- switch (b)
- {
- whitespace:
- continue;
-
- case ']':
-
- if (top && top->type == json_array)
- flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
- else
- { sprintf (error, "%d:%d: Unexpected ]", line_and_col);
- goto e_failed;
- }
-
- break;
-
- default:
-
- if (flags & flag_need_comma)
- {
- if (b == ',')
- { flags &= ~ flag_need_comma;
- continue;
- }
- else
- {
- sprintf (error, "%d:%d: Expected , before %c",
- state.cur_line, state.cur_col, b);
-
- goto e_failed;
- }
- }
-
- if (flags & flag_need_colon)
- {
- if (b == ':')
- { flags &= ~ flag_need_colon;
- continue;
- }
- else
- {
- sprintf (error, "%d:%d: Expected : before %c",
- state.cur_line, state.cur_col, b);
-
- goto e_failed;
- }
- }
-
- flags &= ~ flag_seek_value;
-
- switch (b)
- {
- case '{':
-
- if (!new_value (&state, &top, &root, &alloc, json_object))
- goto e_alloc_failure;
-
- continue;
-
- case '[':
-
- if (!new_value (&state, &top, &root, &alloc, json_array))
- goto e_alloc_failure;
-
- flags |= flag_seek_value;
- continue;
-
- case '"':
-
- if (!new_value (&state, &top, &root, &alloc, json_string))
- goto e_alloc_failure;
-
- flags |= flag_string;
-
- string = top->u.string.ptr;
- string_length = 0;
-
- continue;
-
- case 't':
-
- if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
- *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
- {
- goto e_unknown_value;
- }
-
- if (!new_value (&state, &top, &root, &alloc, json_boolean))
- goto e_alloc_failure;
-
- top->u.boolean = 1;
-
- flags |= flag_next;
- break;
-
- case 'f':
-
- if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
- *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
- *(++ state.ptr) != 'e')
- {
- goto e_unknown_value;
- }
-
- if (!new_value (&state, &top, &root, &alloc, json_boolean))
- goto e_alloc_failure;
-
- flags |= flag_next;
- break;
-
- case 'n':
-
- if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
- *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
- {
- goto e_unknown_value;
- }
-
- if (!new_value (&state, &top, &root, &alloc, json_null))
- goto e_alloc_failure;
-
- flags |= flag_next;
- break;
-
- default:
-
- if (isdigit (b) || b == '-')
- {
- if (!new_value (&state, &top, &root, &alloc, json_integer))
- goto e_alloc_failure;
-
- if (!state.first_pass)
- {
- while (isdigit (b) || b == '+' || b == '-'
- || b == 'e' || b == 'E' || b == '.')
- {
- if ( (++ state.ptr) == end)
- {
- b = 0;
- break;
- }
-
- b = *state.ptr;
- }
-
- flags |= flag_next | flag_reproc;
- break;
- }
-
- flags &= ~ (flag_num_negative | flag_num_e |
- flag_num_e_got_sign | flag_num_e_negative |
- flag_num_zero);
-
- num_digits = 0;
- num_fraction = 0;
- num_e = 0;
-
- if (b != '-')
- {
- flags |= flag_reproc;
- break;
- }
-
- flags |= flag_num_negative;
- continue;
- }
- else
- { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
- goto e_failed;
- }
- };
- };
- }
- else
- {
- switch (top->type)
- {
- case json_object:
-
- switch (b)
- {
- whitespace:
- continue;
-
- case '"':
-
- if (flags & flag_need_comma)
- { sprintf (error, "%d:%d: Expected , before \"", line_and_col);
- goto e_failed;
- }
-
- flags |= flag_string;
-
- string = (json_char *) top->_reserved.object_mem;
- string_length = 0;
-
- break;
-
- case '}':
-
- flags = (flags & ~ flag_need_comma) | flag_next;
- break;
-
- case ',':
-
- if (flags & flag_need_comma)
- {
- flags &= ~ flag_need_comma;
- break;
- }
-
- default:
- sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
- goto e_failed;
- };
-
- break;
-
- case json_integer:
- case json_double:
-
- if (isdigit (b))
- {
- ++ num_digits;
-
- if (top->type == json_integer || flags & flag_num_e)
- {
- if (! (flags & flag_num_e))
- {
- if (flags & flag_num_zero)
- { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
- goto e_failed;
- }
-
- if (num_digits == 1 && b == '0')
- flags |= flag_num_zero;
- }
- else
- {
- flags |= flag_num_e_got_sign;
- num_e = (num_e * 10) + (b - '0');
- continue;
- }
-
- top->u.integer = (top->u.integer * 10) + (b - '0');
- continue;
- }
-
- num_fraction = (num_fraction * 10) + (b - '0');
- continue;
- }
-
- if (b == '+' || b == '-')
- {
- if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
- {
- flags |= flag_num_e_got_sign;
-
- if (b == '-')
- flags |= flag_num_e_negative;
-
- continue;
- }
- }
- else if (b == '.' && top->type == json_integer)
- {
- if (!num_digits)
- { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
- goto e_failed;
- }
-
- top->type = json_double;
- top->u.dbl = (double) top->u.integer;
-
- num_digits = 0;
- continue;
- }
-
- if (! (flags & flag_num_e))
- {
- if (top->type == json_double)
- {
- if (!num_digits)
- { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
- goto e_failed;
- }
-
- top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));
- }
-
- if (b == 'e' || b == 'E')
- {
- flags |= flag_num_e;
-
- if (top->type == json_integer)
- {
- top->type = json_double;
- top->u.dbl = (double) top->u.integer;
- }
-
- num_digits = 0;
- flags &= ~ flag_num_zero;
-
- continue;
- }
- }
- else
- {
- if (!num_digits)
- { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
- goto e_failed;
- }
-
- top->u.dbl *= pow (10.0, (double)
- (flags & flag_num_e_negative ? - num_e : num_e));
- }
-
- if (flags & flag_num_negative)
- {
- if (top->type == json_integer)
- top->u.integer = - top->u.integer;
- else
- top->u.dbl = - top->u.dbl;
- }
-
- flags |= flag_next | flag_reproc;
- break;
-
- default:
- break;
- };
- }
-
- if (flags & flag_reproc)
- {
- flags &= ~ flag_reproc;
- -- state.ptr;
- }
-
- if (flags & flag_next)
- {
- flags = (flags & ~ flag_next) | flag_need_comma;
-
- if (!top->parent)
- {
- /* root value done */
-
- flags |= flag_done;
- continue;
- }
-
- if (top->parent->type == json_array)
- flags |= flag_seek_value;
-
- if (!state.first_pass)
- {
- json_value * parent = top->parent;
-
- switch (parent->type)
- {
- case json_object:
-
- parent->u.object.values
- [parent->u.object.length].value = top;
-
- break;
-
- case json_array:
-
- parent->u.array.values
- [parent->u.array.length] = top;
-
- break;
-
- default:
- break;
- };
- }
-
- if ( (++ top->parent->u.array.length) > state.uint_max)
- goto e_overflow;
-
- top = top->parent;
-
- continue;
- }
- }
-
- alloc = root;
- }
-
- return root;
-
-e_unknown_value:
-
- sprintf (error, "%d:%d: Unknown value", line_and_col);
- goto e_failed;
-
-e_alloc_failure:
-
- strcpy (error, "Memory allocation failure");
- goto e_failed;
-
-e_overflow:
-
- sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
- goto e_failed;
-
-e_failed:
-
- if (error_buf)
- {
- if (*error)
- strcpy (error_buf, error);
- else
- strcpy (error_buf, "Unknown error");
- }
-
- if (state.first_pass)
- alloc = root;
-
- while (alloc)
- {
- top = alloc->_reserved.next_alloc;
- state.settings.mem_free (alloc, state.settings.user_data);
- alloc = top;
- }
-
- if (!state.first_pass)
- json_value_free_ex (&state.settings, root);
-
- return 0;
-}
-
-json_value * json_parse (const json_char * json, size_t length)
-{
- json_settings settings = { 0 };
- return json_parse_ex (&settings, json, length, 0);
-}
-
-void json_value_free_ex (json_settings * settings, json_value * value)
-{
- json_value * cur_value;
-
- if (!value)
- return;
-
- value->parent = 0;
-
- while (value)
- {
- switch (value->type)
- {
- case json_array:
-
- if (!value->u.array.length)
- {
- settings->mem_free (value->u.array.values, settings->user_data);
- break;
- }
-
- value = value->u.array.values [-- value->u.array.length];
- continue;
-
- case json_object:
-
- if (!value->u.object.length)
- {
- settings->mem_free (value->u.object.values, settings->user_data);
- break;
- }
-
- value = value->u.object.values [-- value->u.object.length].value;
- continue;
-
- case json_string:
-
- settings->mem_free (value->u.string.ptr, settings->user_data);
- break;
-
- default:
- break;
- };
-
- cur_value = value;
- value = value->parent;
- settings->mem_free (cur_value, settings->user_data);
- }
-}
-
-void json_value_free (json_value * value)
-{
- json_settings settings = { 0 };
- settings.mem_free = default_free;
- json_value_free_ex (&settings, value);
-}
-
diff --git a/ext/json-parser/json.h b/ext/json-parser/json.h
deleted file mode 100644
index f6549ec4..00000000
--- a/ext/json-parser/json.h
+++ /dev/null
@@ -1,283 +0,0 @@
-
-/* vim: set et ts=3 sw=3 sts=3 ft=c:
- *
- * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
- * https://github.com/udp/json-parser
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _JSON_H
-#define _JSON_H
-
-#ifndef json_char
- #define json_char char
-#endif
-
-#ifndef json_int_t
- #ifndef _MSC_VER
- #include <inttypes.h>
- #define json_int_t int64_t
- #else
- #define json_int_t __int64
- #endif
-#endif
-
-#include <stdlib.h>
-
-#ifdef __cplusplus
-
- #include <string.h>
-
- extern "C"
- {
-
-#endif
-
-typedef struct
-{
- unsigned long max_memory;
- int settings;
-
- /* Custom allocator support (leave null to use malloc/free)
- */
-
- void * (* mem_alloc) (size_t, int zero, void * user_data);
- void (* mem_free) (void *, void * user_data);
-
- void * user_data; /* will be passed to mem_alloc and mem_free */
-
- size_t value_extra; /* how much extra space to allocate for values? */
-
-} json_settings;
-
-#define json_enable_comments 0x01
-
-typedef enum
-{
- json_none,
- json_object,
- json_array,
- json_integer,
- json_double,
- json_string,
- json_boolean,
- json_null
-
-} json_type;
-
-extern const struct _json_value json_value_none;
-
-typedef struct _json_object_entry
-{
- json_char * name;
- unsigned int name_length;
-
- struct _json_value * value;
-
-} json_object_entry;
-
-typedef struct _json_value
-{
- struct _json_value * parent;
-
- json_type type;
-
- union
- {
- int boolean;
- json_int_t integer;
- double dbl;
-
- struct
- {
- unsigned int length;
- json_char * ptr; /* null terminated */
-
- } string;
-
- struct
- {
- unsigned int length;
-
- json_object_entry * values;
-
- #if defined(__cplusplus) && __cplusplus >= 201103L
- decltype(values) begin () const
- { return values;
- }
- decltype(values) end () const
- { return values + length;
- }
- #endif
-
- } object;
-
- struct
- {
- unsigned int length;
- struct _json_value ** values;
-
- #if defined(__cplusplus) && __cplusplus >= 201103L
- decltype(values) begin () const
- { return values;
- }
- decltype(values) end () const
- { return values + length;
- }
- #endif
-
- } array;
-
- } u;
-
- union
- {
- struct _json_value * next_alloc;
- void * object_mem;
-
- } _reserved;
-
- #ifdef JSON_TRACK_SOURCE
-
- /* Location of the value in the source JSON
- */
- unsigned int line, col;
-
- #endif
-
-
- /* Some C++ operator sugar */
-
- #ifdef __cplusplus
-
- public:
-
- inline _json_value ()
- { memset (this, 0, sizeof (_json_value));
- }
-
- inline const struct _json_value &operator [] (int index) const
- {
- if (type != json_array || index < 0
- || ((unsigned int) index) >= u.array.length)
- {
- return json_value_none;
- }
-
- return *u.array.values [index];
- }
-
- inline const struct _json_value &operator [] (const char * index) const
- {
- if (type != json_object)
- return json_value_none;
-
- for (unsigned int i = 0; i < u.object.length; ++ i)
- if (!strcmp (u.object.values [i].name, index))
- return *u.object.values [i].value;
-
- return json_value_none;
- }
-
- inline operator const char * () const
- {
- switch (type)
- {
- case json_string:
- return u.string.ptr;
-
- default:
- return "";
- };
- }
-
- inline operator json_int_t () const
- {
- switch (type)
- {
- case json_integer:
- return u.integer;
-
- case json_double:
- return (json_int_t) u.dbl;
-
- default:
- return 0;
- };
- }
-
- inline operator bool () const
- {
- if (type != json_boolean)
- return false;
-
- return u.boolean != 0;
- }
-
- inline operator double () const
- {
- switch (type)
- {
- case json_integer:
- return (double) u.integer;
-
- case json_double:
- return u.dbl;
-
- default:
- return 0;
- };
- }
-
- #endif
-
-} json_value;
-
-json_value * json_parse (const json_char * json,
- size_t length);
-
-#define json_error_max 128
-json_value * json_parse_ex (json_settings * settings,
- const json_char * json,
- size_t length,
- char * error);
-
-void json_value_free (json_value *);
-
-
-/* Not usually necessary, unless you used a custom mem_alloc and now want to
- * use a custom mem_free.
- */
-void json_value_free_ex (json_settings * settings,
- json_value *);
-
-
-#ifdef __cplusplus
- } /* extern "C" */
-#endif
-
-#endif
-
-
diff --git a/ext/json/LICENSE.MIT b/ext/json/LICENSE.MIT
index e2ac4891..00599afe 100644
--- a/ext/json/LICENSE.MIT
+++ b/ext/json/LICENSE.MIT
@@ -1,14 +1,13 @@
-The library is licensed under the MIT License
-<http://opensource.org/licenses/MIT>:
+MIT License
-Copyright (c) 2013-2016 Niels Lohmann
+Copyright (c) 2013-2017 Niels Lohmann
-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:
+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.
diff --git a/ext/json/README.md b/ext/json/README.md
index cb05d744..256409e3 100644
--- a/ext/json/README.md
+++ b/ext/json/README.md
@@ -1,30 +1,53 @@
-![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)
+[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases)
[![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json)
-[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
+[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
-[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/wuiuqYiYqRTdI3rG)
+[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=nlohmann/json&amp;utm_campaign=Badge_Grade)
+[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/Op57X0V7fTf2tdwl)
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
[![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
[![Github Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues)
+[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/nlohmann/json.svg)](http://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue")
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289)
+
+- [Design goals](#design-goals)
+- [Integration](#integration)
+- [Examples](#examples)
+ - [JSON as first-class data type](#json-as-first-class-data-type)
+ - [Serialization / Deserialization](#serialization--deserialization)
+ - [STL-like access](#stl-like-access)
+ - [Conversion from STL containers](#conversion-from-stl-containers)
+ - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch)
+ - [Implicit conversions](#implicit-conversions)
+ - [Conversions to/from arbitrary types](#arbitrary-types-conversions)
+ - [Binary formats (CBOR and MessagePack)](#binary-formats-cbor-and-messagepack)
+- [Supported compilers](#supported-compilers)
+- [License](#license)
+- [Contact](#contact)
+- [Thanks](#thanks)
+- [Used third-party tools](#used-third-party-tools)
+- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c)
+- [Notes](#notes)
+- [Execute unit tests](#execute-unit-tests)
## Design goals
There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:
-- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean.
+- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you'll know what I mean.
- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/src/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
-- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/src/unit.cpp) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks.
+- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/src/unit.cpp) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289).
Other aspects were not so important to us:
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs.
-- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder).
+- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set.
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
@@ -44,9 +67,21 @@ to the files you want to use JSON objects. That's it. Do not forget to set the n
:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`.
+If you are using the [Meson Build System](http://mesonbuild.com), then you can wrap this repo as a subproject.
+
+If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `jsonformoderncpp/x.y.z@vthiery/stable` to your `conanfile.py`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/vthiery/conan-jsonformoderncpp/issues) if you experience problems with the packages.
+
+If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging.
+
+If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can use the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json). Please see the vcpkg project for any issues regarding the packaging.
+
## Examples
+Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a602f275f0359ab181221384989810604.html#a602f275f0359ab181221384989810604)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
+
+### JSON as first-class data type
+
Here are some examples to give you an idea how to use the class.
Assume you want to create the JSON object
@@ -123,12 +158,14 @@ json empty_object_implicit = json({});
json empty_object_explicit = json::object();
// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
-json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) };
+json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
```
### Serialization / Deserialization
+#### To/from strings
+
You can create an object (deserialization) by appending `_json` to a string literal:
```cpp
@@ -142,8 +179,14 @@ auto j2 = R"(
"pi": 3.141
}
)"_json;
+```
+
+Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object.
-// or explicitly
+The above example can also be expressed explicitly using `json::parse()`:
+
+```cpp
+// parse explicitly
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
```
@@ -162,6 +205,31 @@ std::cout << j.dump(4) << std::endl;
// }
```
+Note the difference between serialization and assignment:
+
+```cpp
+// store a string in a JSON value
+json j_string = "this is a string";
+
+// retrieve the string value (implicit JSON to std::string conversion)
+std::string cpp_string = j_string;
+// retrieve the string value (explicit JSON to std::string conversion)
+auto cpp_string2 = j_string.get<std::string>();
+
+// retrieve the serialized value (explicit JSON serialization)
+std::string serialized_string = j_string.dump();
+
+// output of original string
+std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
+// output of serialized value
+std::cout << j_string << " == " << serialized_string << std::endl;
+```
+
+`.dump()` always returns the serialized value, and `.get<std::string>()` returns the originally stored string value.
+
+
+#### To/from streams (e.g. files, string streams)
+
You can also use streams to serialize and deserialize:
```cpp
@@ -176,10 +244,37 @@ std::cout << j;
std::cout << std::setw(4) << j << std::endl;
```
-These operators work for any subclasses of `std::istream` or `std::ostream`.
+These operators work for any subclasses of `std::istream` or `std::ostream`. Here is the same example with files:
+
+```cpp
+// read a JSON file
+std::ifstream i("file.json");
+json j;
+i >> j;
+
+// write prettified JSON to another file
+std::ofstream o("pretty.json");
+o << std::setw(4) << j << std::endl;
+```
Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use.
+#### Read from iterator range
+
+You can also read JSON from an iterator range; that is, from any container accessible by iterators whose content is stored as contiguous byte sequence, for instance a `std::vector<std::uint8_t>`:
+
+```cpp
+std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
+json j = json::parse(v.begin(), v.end());
+```
+
+You may leave the iterators for the range [begin, end):
+
+```cpp
+std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
+json j = json::parse(v);
+```
+
### STL-like access
@@ -192,6 +287,9 @@ j.push_back("foo");
j.push_back(1);
j.push_back(true);
+// also use emplace_back
+j.emplace_back(1.78);
+
// iterate the array
for (json::iterator it = j.begin(); it != j.end(); ++it) {
std::cout << *it << '\n';
@@ -207,6 +305,9 @@ const std::string tmp = j[0];
j[1] = 42;
bool foo = j.at(2);
+// comparison
+j == "[\"foo\", 1, true]"_json; // true
+
// other stuff
j.size(); // 3 entries
j.empty(); // false
@@ -221,15 +322,15 @@ j.is_object();
j.is_array();
j.is_string();
-// comparison
-j == "[\"foo\", 1, true]"_json; // true
-
// create an object
json o;
o["foo"] = 23;
o["bar"] = false;
o["baz"] = 3.141;
+// also use emplace
+o.emplace("weather", "sunny");
+
// special iterator member functions for objects
for (json::iterator it = o.begin(); it != o.end(); ++it) {
std::cout << it.key() << " : " << it.value() << "\n";
@@ -251,7 +352,7 @@ o.erase("foo");
### Conversion from STL containers
-Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON types (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends how the elements are ordered in the respective STL container.
+Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON types (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends on how the elements are ordered in the respective STL container.
```cpp
std::vector<int> c_vector {1, 2, 3, 4};
@@ -283,15 +384,15 @@ json j_uset(c_uset); // only one entry for "one" is used
// maybe ["two", "three", "four", "one"]
std::multiset<std::string> c_mset {"one", "two", "one", "four"};
-json j_mset(c_mset); // only one entry for "one" is used
-// maybe ["one", "two", "four"]
+json j_mset(c_mset); // both entries for "one" are used
+// maybe ["one", "two", "one", "four"]
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
json j_umset(c_umset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"]
```
-Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys are can construct an `std::string` and whose values can be used to construct JSON types (see examples above) can be used to to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container.
+Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON types (see examples above) can be used to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container.
```cpp
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
@@ -323,7 +424,7 @@ json j_original = R"({
})"_json;
// access members with a JSON pointer (RFC 6901)
-j_original["/baz/2"_json_pointer];
+j_original["/baz/1"_json_pointer];
// "two"
// a JSON patch (RFC 6902)
@@ -344,8 +445,8 @@ json j_result = j_original.patch(j_patch);
json::diff(j_result, j_original);
// [
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
-// { "op":"remove","path":"/hello" },
-// { "op":"add","path":"/foo","value":"bar" }
+// { "op": "remove","path": "/hello" },
+// { "op": "add", "path": "/foo", "value": "bar" }
// ]
```
@@ -383,14 +484,266 @@ int vi = jn.get<int>();
// etc.
```
+### Arbitrary types conversions
+
+Every type can be serialized in JSON, not just STL-containers and scalar types. Usually, you would do something along those lines:
+
+```cpp
+namespace ns {
+ // a simple struct to model a person
+ struct person {
+ std::string name;
+ std::string address;
+ int age;
+ };
+}
+
+ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
+
+// convert to JSON: copy each value into the JSON object
+json j;
+j["name"] = p.name;
+j["address"] = p.address;
+j["age"] = p.age;
+
+// ...
+
+// convert from JSON: copy each value from the JSON object
+ns::person p {
+ j["name"].get<std::string>(),
+ j["address"].get<std::string>(),
+ j["age"].get<int>()
+};
+```
+
+It works, but that's quite a lot of boilerplate... Fortunately, there's a better way:
+
+```cpp
+// create a person
+ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};
+
+// conversion: person -> json
+json j = p;
+
+std::cout << j << std::endl;
+// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
+
+// conversion: json -> person
+ns::person p2 = j;
+
+// that's it
+assert(p == p2);
+```
+
+#### Basic usage
+
+To make this work with one of your types, you only need to provide two functions:
+
+```cpp
+using nlohmann::json;
+
+namespace ns {
+ void to_json(json& j, const person& p) {
+ j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};
+ }
+
+ void from_json(const json& j, person& p) {
+ p.name = j.at("name").get<std::string>();
+ p.address = j.at("address").get<std::string>();
+ p.age = j.at("age").get<int>();
+ }
+} // namespace ns
+```
+
+That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called.
+Likewise, when calling `get<your_type>()`, the `from_json` method will be called.
+
+Some important things:
+
+* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
+* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). (There is a way to bypass this requirement described later.)
+* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
+* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get<decltype your_variable>();` instead.
+* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
+* Be careful with the definition order of the `from_json`/`to_json` functions: If a type `B` has a member of type `A`, you **MUST** define `to_json(A)` before `to_json(B)`. Look at [issue 561](https://github.com/nlohmann/json/issues/561) for more details.
+
+
+#### How do I convert third-party types?
+
+This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
+
+The library uses **JSON Serializers** to convert types to json.
+The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](http://en.cppreference.com/w/cpp/language/adl)).
+
+It is implemented like this (simplified):
+
+```cpp
+template <typename T>
+struct adl_serializer {
+ static void to_json(json& j, const T& value) {
+ // calls the "to_json" method in T's namespace
+ }
+
+ static void from_json(const json& j, T& value) {
+ // same thing, but with the "from_json" method
+ }
+};
+```
+
+This serializer works fine when you have control over the type's namespace. However, what about `boost::optional`, or `std::filesystem::path` (C++17)? Hijacking the `boost` namespace is pretty bad, and it's illegal to add something other than template specializations to `std`...
+
+To solve this, you need to add a specialization of `adl_serializer` to the `nlohmann` namespace, here's an example:
+
+```cpp
+// partial specialization (full specialization works too)
+namespace nlohmann {
+ template <typename T>
+ struct adl_serializer<boost::optional<T>> {
+ static void to_json(json& j, const boost::optional<T>& opt) {
+ if (opt == boost::none) {
+ j = nullptr;
+ } else {
+ j = *opt; // this will call adl_serializer<T>::to_json which will
+ // find the free function to_json in T's namespace!
+ }
+ }
+
+ static void from_json(const json& j, boost::optional<T>& opt) {
+ if (j.is_null()) {
+ opt = boost::none;
+ } else {
+ opt = j.get<T>(); // same as above, but with
+ // adl_serializer<T>::from_json
+ }
+ }
+ };
+}
+```
+
+#### How can I use `get()` for non-default constructible/non-copyable types?
+
+There is a way, if your type is [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
+
+```cpp
+struct move_only_type {
+ move_only_type() = delete;
+ move_only_type(int ii): i(ii) {}
+ move_only_type(const move_only_type&) = delete;
+ move_only_type(move_only_type&&) = default;
+
+ int i;
+};
+
+namespace nlohmann {
+ template <>
+ struct adl_serializer<move_only_type> {
+ // note: the return type is no longer 'void', and the method only takes
+ // one argument
+ static move_only_type from_json(const json& j) {
+ return {j.get<int>()};
+ }
+
+ // Here's the catch! You must provide a to_json method! Otherwise you
+ // will not be able to convert move_only_type to json, since you fully
+ // specialized adl_serializer on that type
+ static void to_json(json& j, move_only_type t) {
+ j = t.i;
+ }
+ };
+}
+```
+
+#### Can I write my own serializer? (Advanced use)
+
+Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples.
+
+If you write your own serializer, you'll need to do a few things:
+
+* use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`)
+* use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods
+* use `nlohmann::to_json` and `nlohmann::from_json` when you need ADL
+
+Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL.
+
+```cpp
+// You should use void as a second template argument
+// if you don't need compile-time checks on T
+template<typename T, typename SFINAE = typename std::enable_if<sizeof(T) <= 32>::type>
+struct less_than_32_serializer {
+ template <typename BasicJsonType>
+ static void to_json(BasicJsonType& j, T value) {
+ // we want to use ADL, and call the correct to_json overload
+ using nlohmann::to_json; // this method is called by adl_serializer,
+ // this is where the magic happens
+ to_json(j, value);
+ }
+
+ template <typename BasicJsonType>
+ static void from_json(const BasicJsonType& j, T& value) {
+ // same thing here
+ using nlohmann::from_json;
+ from_json(j, value);
+ }
+};
+```
+
+Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention:
+
+```cpp
+template <typename T, void>
+struct bad_serializer
+{
+ template <typename BasicJsonType>
+ static void to_json(BasicJsonType& j, const T& value) {
+ // this calls BasicJsonType::json_serializer<T>::to_json(j, value);
+ // if BasicJsonType::json_serializer == bad_serializer ... oops!
+ j = value;
+ }
+
+ template <typename BasicJsonType>
+ static void to_json(const BasicJsonType& j, T& value) {
+ // this calls BasicJsonType::json_serializer<T>::from_json(j, value);
+ // if BasicJsonType::json_serializer == bad_serializer ... oops!
+ value = j.template get<T>(); // oops!
+ }
+};
+```
+
+### Binary formats (CBOR and MessagePack)
+
+Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [CBOR](http://cbor.io) (Concise Binary Object Representation) and [MessagePack](http://msgpack.org) to efficiently encode JSON values to byte vectors and to decode such vectors.
+
+```cpp
+// create a JSON value
+json j = R"({"compact": true, "schema": 0})"_json;
+
+// serialize to CBOR
+std::vector<std::uint8_t> v_cbor = json::to_cbor(j);
+
+// 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00
+
+// roundtrip
+json j_from_cbor = json::from_cbor(v_cbor);
+
+// serialize to MessagePack
+std::vector<std::uint8_t> v_msgpack = json::to_msgpack(j);
+
+// 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00
+
+// roundtrip
+json j_from_msgpack = json::from_msgpack(v_msgpack);
+```
+
## Supported compilers
-Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
+Though it's 2017 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
-- GCC 4.9 - 6.0 (and possibly later)
-- Clang 3.4 - 3.9 (and possibly later)
-- Microsoft Visual C++ 2015 / 14.0 (and possibly later)
+- GCC 4.9 - 7.2 (and possibly later)
+- Clang 3.4 - 5.0 (and possibly later)
+- Intel C++ Compiler 17.0.2 (and possibly later)
+- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
+- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
I would be happy to learn about other compilers/versions.
@@ -413,20 +766,28 @@ The following compilers are currently used in continuous integration at [Travis]
| Compiler | Operating System | Version String |
|-----------------|------------------------------|----------------|
-| GCC 4.9.3 | Ubuntu 14.04.4 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 |
-| GCC 5.3.0 | Ubuntu 14.04.4 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 |
-| GCC 6.1.1 | Ubuntu 14.04.4 LTS | g++-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511 |
-| Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) |
-| Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) |
-| Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) |
-| Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) |
+| GCC 4.9.4 | Ubuntu 14.04.5 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 |
+| GCC 5.4.1 | Ubuntu 14.04.5 LTS | g++-5 (Ubuntu 5.4.1-2ubuntu1~14.04) 5.4.1 20160904 |
+| GCC 6.3.0 | Ubuntu 14.04.5 LTS | g++-6 (Ubuntu/Linaro 6.3.0-18ubuntu2~14.04) 6.3.0 20170519 |
+| GCC 7.1.0 | Ubuntu 14.04.5 LTS | g++-7 (Ubuntu 7.1.0-5ubuntu2~14.04) 7.1.0
+| Clang 3.5.0 | Ubuntu 14.04.5 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) |
+| Clang 3.6.2 | Ubuntu 14.04.5 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) |
+| Clang 3.7.1 | Ubuntu 14.04.5 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) |
+| Clang 3.8.0 | Ubuntu 14.04.5 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) |
+| Clang 3.9.1 | Ubuntu 14.04.5 LTS | clang version 3.9.1-4ubuntu3~14.04.2 (tags/RELEASE_391/rc2) |
+| Clang 4.0.1 | Ubuntu 14.04.5 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
+| Clang 5.0.0 | Ubuntu 14.04.5 LTS | clang version 5.0.0-svn310902-1~exp1 (branches/release_50) |
| Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
-| Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) |
-| Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) |
| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) |
-| Clang Xcode 8.0 | Darwin Kernel Version 15.5.0 (OSX 10.11.5) | Apple LLVM version 8.0.0 (clang-800.0.24.1) |
-| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 |
-
+| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 | Apple LLVM version 8.0.0 (clang-800.0.38) |
+| Clang Xcode 8.1 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
+| Clang Xcode 8.2 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
+| Clang Xcode 8.3 | Darwin Kernel Version 16.5.0 (macOS 10.12.4) | Apple LLVM version 8.1.0 (clang-802.0.38) |
+| Clang Xcode 9.0 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.37) |
+| Clang Xcode 9.1 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.38) |
+| Clang Xcode 9.2 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 8.1.0 (clang-900.0.39.2) |
+| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 |
+| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.5.180.51428, MSVC 19.12.25830.2 |
## License
@@ -434,7 +795,7 @@ The following compilers are currently used in continuous integration at [Travis]
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
-Copyright &copy; 2013-2016 [Niels Lohmann](http://nlohmann.me)
+Copyright &copy; 2013-2017 [Niels Lohmann](http://nlohmann.me)
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:
@@ -442,11 +803,23 @@ The above copyright notice and this permission notice shall be included in all c
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.
+* * *
+
+The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright &copy; 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) <bjoern@hoehrmann.de>
+
+## Contact
+
+If you have questions regarding the library, I would like to invite you to [open an issue at Github](https://github.com/nlohmann/json/issues/new). Please describe your request, problem, or question as detailed as possible, and also mention the version of the library you are using as well as the version of your compiler and operating system. Opening an issue at Github allows other users and contributors to this library to collaborate. For instance, I have little experience with MSVC, and most issues in this regard have been solved by a growing community. If you have a look at the [closed issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+is%3Aclosed), you will see that we react quite timely in most cases.
+
+Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please use [this key](https://keybase.io/nlohmann/pgp_keys.asc).
+
## Thanks
I deeply appreciate the help of the following people.
+![Contributors](https://raw.githubusercontent.com/nlohmann/json/develop/doc/avatars.png)
+
- [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization.
- [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes.
- [kirkshoop](https://github.com/kirkshoop) made the iterators of the class composable to other libraries.
@@ -459,7 +832,7 @@ I deeply appreciate the help of the following people.
- [Eric Cornelius](https://github.com/EricMCornelius) pointed out a bug in the handling with NaN and infinity values. He also improved the performance of the string escaping.
- [易思龙](https://github.com/likebeta) implemented a conversion from anonymous enums.
- [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual studio.
-- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements.
+- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types.
- [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling.
- [dariomt](https://github.com/dariomt) fixed some typos in the examples.
- [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation.
@@ -483,14 +856,117 @@ I deeply appreciate the help of the following people.
- [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake.
- [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files.
- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal).
-
-Thanks a lot for helping out!
+- [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
+- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
+- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
+- [Thomas Braun](https://github.com/t-b) fixed a warning in a test case.
+- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types.
+- [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation.
+- [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`.
+- [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
+- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
+- [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
+- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
+- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing.
+- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
+- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning.
+- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
+- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
+- [Daniel599](https://github.com/Daniel599) helped to get Travis execute the tests with Clang's sanitizers.
+- [Jonathan Lee](https://github.com/vjon) fixed an example in the README file.
+- [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types.
+- [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio.
+- [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types.
+- [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example.
+- [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite.
+- [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section.
+- [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README.
+- [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s.
+- [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation.
+- [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings.
+- [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible.
+- [ftillier](https://github.com/ftillier) fixed a compiler warning.
+- [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped.
+- [Fytch](https://github.com/Fytch) found a bug in the documentation.
+- [Jay Sistar](https://github.com/Type1J) implemented a Meson build description.
+- [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation.
+- [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager.
+- [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`.
+- [Mike Tzou](https://github.com/Chocobo1) fixed some typos.
+- [amrcode](https://github.com/amrcode) noted a missleading documentation about comparison of floats.
+- [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`.
+- [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library.
+- [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists.
+- [Greg Hurrell](https://github.com/wincent) fixed a typo.
+- [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo.
+- [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler.
+- [Markus Werle](https://github.com/daixtrose) fixed a typo.
+- [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check.
+- [Alex](https://github.com/leha-bot) noted an error in a code sample.
+- [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped fixing them.
+- [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams.
+- [Sonu Lohani](https://github.com/sonulohani) fixed a small compilation error.
+- [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings.
+- [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file.
+- [pvleuven](https://github.com/pvleuven) helped fixing a warning in ICC.
+- [Pavel](https://github.com/crea7or) helped fixing some warnings in MSVC.
+- [Jamie Seward](https://github.com/jseward) avoided unneccessary string copies in `find()` and `count()`.
+- [Mitja](https://github.com/Itja) fixed some typos.
+- [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links.
+- [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view.
+- [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings.
+- [Eren Okka](https://github.com/erengy) fixed some MSVC warnings.
+
+
+Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
+
+
+## Used third-party tools
+
+The library itself contains of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot!
+
+- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing
+- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows
+- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code identation
+- [**benchpress**](https://github.com/sbs-ableton/benchpress) to benchmark the code
+- [**Catch**](https://github.com/philsquared/Catch) for the unit tests
+- [**Clang**](http://clang.llvm.org) for compilation with code sanitizers
+- [**Cmake**](https://cmake.org) for build automation
+- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json)
+- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json)
+- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json)
+- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis
+- [**cxxopts**](https://github.com/jarro2783/cxxopts) to let benchpress parse command-line parameters
+- [**Doxygen**](http://www.stack.nl/~dimitri/doxygen/) to generate [documentation](https://nlohmann.github.io/json/)
+- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages
+- [**Github Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md)
+- [**libFuzzer**](http://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz
+- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library
+- [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments.
+- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](http://melpon.org/wandbox)
+- [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS
+- [**Valgrind**](http://valgrind.org) to check for correct memory management
+- [**Wandbox**](http://melpon.org/wandbox) for [online examples](https://wandbox.org/permlink/Op57X0V7fTf2tdwl)
+
+
+## Projects using JSON for Modern C++
+
+The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices.
## Notes
-- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert).
+- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726).
- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
+- The library supports **Unicode input** as follows:
+ - Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 7159](http://rfc7159.net/rfc7159#rfc.section.8.1).
+ - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse or serialization errors.
+ - [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library.
+ - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
+ - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
+- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag.
+- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by an `abort()` call.
+- By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc7159.html) defines objects as "an unordered collection of zero or more name/value pairs". If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
## Execute unit tests
@@ -498,11 +974,11 @@ Thanks a lot for helping out!
To compile and run the tests, you need to execute
```sh
-$ make
-$ ./json_unit "*"
-
-===============================================================================
-All tests passed (5568721 assertions in 32 test cases)
+$ mkdir build
+$ cd build
+$ cmake ..
+$ cmake --build .
+$ ctest --output-on-failure
```
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
diff --git a/ext/json/json.hpp b/ext/json/json.hpp
index 9d6687dd..5b0b0ea5 100644
--- a/ext/json/json.hpp
+++ b/ext/json/json.hpp
@@ -1,11 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 2.0.0
+| | |__ | | | | | | version 3.0.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
-Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
+Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -29,29 +29,44 @@ SOFTWARE.
#ifndef NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP
-#include <algorithm>
-#include <array>
-#include <cassert>
-#include <cerrno>
-#include <ciso646>
-#include <cmath>
-#include <cstddef>
-#include <cstdio>
-#include <cstdlib>
-#include <functional>
-#include <initializer_list>
-#include <iomanip>
-#include <iostream>
-#include <iterator>
-#include <limits>
-#include <map>
-#include <memory>
-#include <sstream>
-#include <stdexcept>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
+#include <algorithm> // all_of, copy, fill, find, for_each, generate_n, none_of, remove, reverse, transform
+#include <array> // array
+#include <cassert> // assert
+#include <ciso646> // and, not, or
+#include <clocale> // lconv, localeconv
+#include <cmath> // isfinite, labs, ldexp, signbit
+#include <cstddef> // nullptr_t, ptrdiff_t, size_t
+#include <cstdint> // int64_t, uint64_t
+#include <cstdlib> // abort, strtod, strtof, strtold, strtoul, strtoll, strtoull
+#include <cstring> // memcpy, strlen
+#include <forward_list> // forward_list
+#include <functional> // function, hash, less
+#include <initializer_list> // initializer_list
+#include <iomanip> // hex
+#include <iosfwd> // istream, ostream
+#include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
+#include <limits> // numeric_limits
+#include <locale> // locale
+#include <map> // map
+#include <memory> // addressof, allocator, allocator_traits, unique_ptr
+#include <numeric> // accumulate
+#include <sstream> // stringstream
+#include <string> // getline, stoi, string, to_string
+#include <type_traits> // add_pointer, conditional, decay, enable_if, false_type, integral_constant, is_arithmetic, is_base_of, is_const, is_constructible, is_convertible, is_default_constructible, is_enum, is_floating_point, is_integral, is_nothrow_move_assignable, is_nothrow_move_constructible, is_pointer, is_reference, is_same, is_scalar, is_signed, remove_const, remove_cv, remove_pointer, remove_reference, true_type, underlying_type
+#include <utility> // declval, forward, make_pair, move, pair, swap
+#include <valarray> // valarray
+#include <vector> // vector
+
+// exclude unsupported compilers
+#if defined(__clang__)
+ #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
+ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+#endif
// disable float-equal warnings on GCC/clang
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
@@ -59,6 +74,49 @@ SOFTWARE.
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+// disable documentation warnings on clang
+#if defined(__clang__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdocumentation"
+#endif
+
+// allow for portable deprecation warnings
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+ #define JSON_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+ #define JSON_DEPRECATED __declspec(deprecated)
+#else
+ #define JSON_DEPRECATED
+#endif
+
+// allow to disable exceptions
+#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION)
+ #define JSON_THROW(exception) throw exception
+ #define JSON_TRY try
+ #define JSON_CATCH(exception) catch(exception)
+#else
+ #define JSON_THROW(exception) std::abort()
+ #define JSON_TRY if(true)
+ #define JSON_CATCH(exception) if(false)
+#endif
+
+// manual branch prediction
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+ #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
+ #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+ #define JSON_LIKELY(x) x
+ #define JSON_UNLIKELY(x) x
+#endif
+
+// C++ language standard detection
+#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+ #define JSON_HAS_CPP_17
+ #define JSON_HAS_CPP_14
+#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+ #define JSON_HAS_CPP_14
+#endif
+
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@@ -66,43 +124,7163 @@ SOFTWARE.
*/
namespace nlohmann
{
+template<typename = void, typename = void>
+struct adl_serializer;
+
+// forward declaration of basic_json (required to split the class)
+template<template<typename, typename, typename...> class ObjectType = std::map,
+ template<typename, typename...> class ArrayType = std::vector,
+ class StringType = std::string, class BooleanType = bool,
+ class NumberIntegerType = std::int64_t,
+ class NumberUnsignedType = std::uint64_t,
+ class NumberFloatType = double,
+ template<typename> class AllocatorType = std::allocator,
+ template<typename, typename = void> class JSONSerializer = adl_serializer>
+class basic_json;
+
+// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
+// may be removed in the future once the class is split.
+
+#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
+ template<template<typename, typename, typename...> class ObjectType, \
+ template<typename, typename...> class ArrayType, \
+ class StringType, class BooleanType, class NumberIntegerType, \
+ class NumberUnsignedType, class NumberFloatType, \
+ template<typename> class AllocatorType, \
+ template<typename, typename = void> class JSONSerializer>
+
+#define NLOHMANN_BASIC_JSON_TPL \
+ basic_json<ObjectType, ArrayType, StringType, BooleanType, \
+ NumberIntegerType, NumberUnsignedType, NumberFloatType, \
+ AllocatorType, JSONSerializer>
/*!
@brief unnamed namespace with internal helper functions
+
+This namespace collects some functions that could not be defined inside the
+@ref basic_json class.
+
+@since version 2.1.0
+*/
+namespace detail
+{
+////////////////
+// exceptions //
+////////////////
+
+/*!
+@brief general exception of the @ref basic_json class
+
+This class is an extension of `std::exception` objects with a member @a id for
+exception ids. It is used as the base class for all exceptions thrown by the
+@ref basic_json class. This class can hence be used as "wildcard" to catch
+exceptions.
+
+Subclasses:
+- @ref parse_error for exceptions indicating a parse error
+- @ref invalid_iterator for exceptions indicating errors with iterators
+- @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+- @ref out_of_range for exceptions indicating access out of the defined range
+- @ref other_error for exceptions indicating other library errors
+
+@internal
+@note To have nothrow-copy-constructible exceptions, we internally use
+ `std::runtime_error` which can cope with arbitrary-length error messages.
+ Intermediate strings are built with static functions and then passed to
+ the actual constructor.
+@endinternal
+
+@liveexample{The following code shows how arbitrary library exceptions can be
+caught.,exception}
+
+@since version 3.0.0
+*/
+class exception : public std::exception
+{
+ public:
+ /// returns the explanatory string
+ const char* what() const noexcept override
+ {
+ return m.what();
+ }
+
+ /// the id of the exception
+ const int id;
+
+ protected:
+ exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
+
+ static std::string name(const std::string& ename, int id_)
+ {
+ return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
+ }
+
+ private:
+ /// an exception object as storage for error messages
+ std::runtime_error m;
+};
+
+/*!
+@brief exception indicating a parse error
+
+This exception is thrown by the library when a parse error occurs. Parse errors
+can occur during the deserialization of JSON text, CBOR, MessagePack, as well
+as when using JSON Patch.
+
+Member @a byte holds the byte index of the last read character in the input
+file.
+
+Exceptions have ids 1xx.
+
+name / id | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
+json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
+json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
+json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
+json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
+json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
+json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
+json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
+json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
+json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
+json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
+json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
+
+@note For an input with n bytes, 1 is the index of the first character and n+1
+ is the index of the terminating null byte or the end of file. This also
+ holds true when reading a byte vector (CBOR or MessagePack).
+
+@liveexample{The following code shows how a `parse_error` exception can be
+caught.,parse_error}
+
+@sa @ref exception for the base class of the library exceptions
+@sa @ref invalid_iterator for exceptions indicating errors with iterators
+@sa @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa @ref out_of_range for exceptions indicating access out of the defined range
+@sa @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class parse_error : public exception
+{
+ public:
+ /*!
+ @brief create a parse error exception
+ @param[in] id_ the id of the exception
+ @param[in] byte_ the byte index where the error occurred (or 0 if the
+ position cannot be determined)
+ @param[in] what_arg the explanatory string
+ @return parse_error object
+ */
+ static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
+ {
+ std::string w = exception::name("parse_error", id_) + "parse error" +
+ (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
+ ": " + what_arg;
+ return parse_error(id_, byte_, w.c_str());
+ }
+
+ /*!
+ @brief byte index of the parse error
+
+ The byte index of the last read character in the input file.
+
+ @note For an input with n bytes, 1 is the index of the first character and
+ n+1 is the index of the terminating null byte or the end of file.
+ This also holds true when reading a byte vector (CBOR or MessagePack).
+ */
+ const std::size_t byte;
+
+ private:
+ parse_error(int id_, std::size_t byte_, const char* what_arg)
+ : exception(id_, what_arg), byte(byte_) {}
+};
+
+/*!
+@brief exception indicating errors with iterators
+
+This exception is thrown if iterators passed to a library function do not match
+the expected semantics.
+
+Exceptions have ids 2xx.
+
+name / id | example message | description
+----------------------------------- | --------------- | -------------------------
+json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
+json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
+json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
+json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
+json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
+json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
+json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
+json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
+json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
+json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
+
+@liveexample{The following code shows how an `invalid_iterator` exception can be
+caught.,invalid_iterator}
+
+@sa @ref exception for the base class of the library exceptions
+@sa @ref parse_error for exceptions indicating a parse error
+@sa @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa @ref out_of_range for exceptions indicating access out of the defined range
+@sa @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class invalid_iterator : public exception
+{
+ public:
+ static invalid_iterator create(int id_, const std::string& what_arg)
+ {
+ std::string w = exception::name("invalid_iterator", id_) + what_arg;
+ return invalid_iterator(id_, w.c_str());
+ }
+
+ private:
+ invalid_iterator(int id_, const char* what_arg)
+ : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating executing a member function with a wrong type
+
+This exception is thrown in case of a type error; that is, a library function is
+executed on a JSON value whose type does not match the expected semantics.
+
+Exceptions have ids 3xx.
+
+name / id | example message | description
+----------------------------- | --------------- | -------------------------
+json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
+json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
+json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
+json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
+json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
+json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
+json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
+json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
+json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
+json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
+json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
+json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
+json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
+json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
+json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
+json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
+
+@liveexample{The following code shows how a `type_error` exception can be
+caught.,type_error}
+
+@sa @ref exception for the base class of the library exceptions
+@sa @ref parse_error for exceptions indicating a parse error
+@sa @ref invalid_iterator for exceptions indicating errors with iterators
+@sa @ref out_of_range for exceptions indicating access out of the defined range
+@sa @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class type_error : public exception
+{
+ public:
+ static type_error create(int id_, const std::string& what_arg)
+ {
+ std::string w = exception::name("type_error", id_) + what_arg;
+ return type_error(id_, w.c_str());
+ }
+
+ private:
+ type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating access out of the defined range
+
+This exception is thrown in case a library function is called on an input
+parameter that exceeds the expected range, for instance in case of array
+indices or nonexisting object keys.
+
+Exceptions have ids 4xx.
+
+name / id | example message | description
+------------------------------- | --------------- | -------------------------
+json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
+json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
+json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
+json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
+json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
+json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
+
+@liveexample{The following code shows how an `out_of_range` exception can be
+caught.,out_of_range}
+
+@sa @ref exception for the base class of the library exceptions
+@sa @ref parse_error for exceptions indicating a parse error
+@sa @ref invalid_iterator for exceptions indicating errors with iterators
+@sa @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class out_of_range : public exception
+{
+ public:
+ static out_of_range create(int id_, const std::string& what_arg)
+ {
+ std::string w = exception::name("out_of_range", id_) + what_arg;
+ return out_of_range(id_, w.c_str());
+ }
+
+ private:
+ out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating other library errors
+
+This exception is thrown in case of errors that cannot be classified with the
+other exception types.
+
+Exceptions have ids 5xx.
+
+name / id | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
+
+@sa @ref exception for the base class of the library exceptions
+@sa @ref parse_error for exceptions indicating a parse error
+@sa @ref invalid_iterator for exceptions indicating errors with iterators
+@sa @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa @ref out_of_range for exceptions indicating access out of the defined range
+
+@liveexample{The following code shows how an `other_error` exception can be
+caught.,other_error}
+
+@since version 3.0.0
+*/
+class other_error : public exception
+{
+ public:
+ static other_error create(int id_, const std::string& what_arg)
+ {
+ std::string w = exception::name("other_error", id_) + what_arg;
+ return other_error(id_, w.c_str());
+ }
+
+ private:
+ other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+
+
+///////////////////////////
+// JSON type enumeration //
+///////////////////////////
+
+/*!
+@brief the JSON type enumeration
+
+This enumeration collects the different JSON types. It is internally used to
+distinguish the stored values, and the functions @ref basic_json::is_null(),
+@ref basic_json::is_object(), @ref basic_json::is_array(),
+@ref basic_json::is_string(), @ref basic_json::is_boolean(),
+@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
+@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
+@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
+@ref basic_json::is_structured() rely on it.
+
+@note There are three enumeration entries (number_integer, number_unsigned, and
+number_float), because the library distinguishes these three types for numbers:
+@ref basic_json::number_unsigned_t is used for unsigned integers,
+@ref basic_json::number_integer_t is used for signed integers, and
+@ref basic_json::number_float_t is used for floating-point numbers or to
+approximate integers which do not fit in the limits of their respective type.
+
+@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
+value with the default value for a given type
+
@since version 1.0.0
*/
-namespace
+enum class value_t : uint8_t
{
+ null, ///< null value
+ object, ///< object (unordered set of name/value pairs)
+ array, ///< array (ordered collection of values)
+ string, ///< string value
+ boolean, ///< boolean value
+ number_integer, ///< number value (signed integer)
+ number_unsigned, ///< number value (unsigned integer)
+ number_float, ///< number value (floating-point)
+ discarded ///< discarded by the the parser callback function
+};
+
+/*!
+@brief comparison operator for JSON types
+
+Returns an ordering that is similar to Python:
+- order: null < boolean < number < object < array < string
+- furthermore, each type is not smaller than itself
+- discarded values are not comparable
+
+@since version 1.0.0
+*/
+inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+{
+ static constexpr std::array<uint8_t, 8> order = {{
+ 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
+ 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
+ }
+ };
+
+ const auto l_index = static_cast<std::size_t>(lhs);
+ const auto r_index = static_cast<std::size_t>(rhs);
+ return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
+}
+
+
+/////////////
+// helpers //
+/////////////
+
+template<typename> struct is_basic_json : std::false_type {};
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+
+// alias templates to reduce boilerplate
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+template<typename T>
+using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+// implementation of C++14 index_sequence and affiliates
+// source: https://stackoverflow.com/a/32223343
+template<std::size_t... Ints>
+struct index_sequence
+{
+ using type = index_sequence;
+ using value_type = std::size_t;
+ static constexpr std::size_t size() noexcept
+ {
+ return sizeof...(Ints);
+ }
+};
+
+template<class Sequence1, class Sequence2>
+struct merge_and_renumber;
+
+template<std::size_t... I1, std::size_t... I2>
+struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
+ : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
+
+template<std::size_t N>
+struct make_index_sequence
+ : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
+ typename make_index_sequence < N - N / 2 >::type > {};
+
+template<> struct make_index_sequence<0> : index_sequence<> {};
+template<> struct make_index_sequence<1> : index_sequence<0> {};
+
+template<typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+/*
+Implementation of two C++17 constructs: conjunction, negation. This is needed
+to avoid evaluating all the traits in a condition
+
+For example: not std::is_same<void, T>::value and has_value_type<T>::value
+will not compile when T = void (on MSVC at least). Whereas
+conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
+stop evaluating if negation<...>::value == false
+
+Please note that those constructs must be used with caution, since symbols can
+become very long quickly (which can slow down compilation and cause MSVC
+internal compiler errors). Only use it when you have to (see example ahead).
+*/
+template<class...> struct conjunction : std::true_type {};
+template<class B1> struct conjunction<B1> : B1 {};
+template<class B1, class... Bn>
+struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+template<class B> struct negation : std::integral_constant<bool, not B::value> {};
+
+// dispatch utility (taken from ranges-v3)
+template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
+template<> struct priority_tag<0> {};
+
+
+//////////////////
+// constructors //
+//////////////////
+
+template<value_t> struct external_constructor;
+
+template<>
+struct external_constructor<value_t::boolean>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
+ {
+ j.m_type = value_t::boolean;
+ j.m_value = b;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::string>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
+ {
+ j.m_type = value_t::string;
+ j.m_value = s;
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+ {
+ j.m_type = value_t::string;
+ j.m_value = std::move(s);
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::number_float>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
+ {
+ j.m_type = value_t::number_float;
+ j.m_value = val;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::number_unsigned>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
+ {
+ j.m_type = value_t::number_unsigned;
+ j.m_value = val;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::number_integer>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
+ {
+ j.m_type = value_t::number_integer;
+ j.m_value = val;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::array>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
+ {
+ j.m_type = value_t::array;
+ j.m_value = arr;
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+ {
+ j.m_type = value_t::array;
+ j.m_value = std::move(arr);
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
+ int> = 0>
+ static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
+ {
+ using std::begin;
+ using std::end;
+ j.m_type = value_t::array;
+ j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const std::vector<bool>& arr)
+ {
+ j.m_type = value_t::array;
+ j.m_value = value_t::array;
+ j.m_value.array->reserve(arr.size());
+ for (const bool x : arr)
+ {
+ j.m_value.array->push_back(x);
+ }
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+ static void construct(BasicJsonType& j, const std::valarray<T>& arr)
+ {
+ j.m_type = value_t::array;
+ j.m_value = value_t::array;
+ j.m_value.array->resize(arr.size());
+ std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::object>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
+ {
+ j.m_type = value_t::object;
+ j.m_value = obj;
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+ {
+ j.m_type = value_t::object;
+ j.m_value = std::move(obj);
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType, typename CompatibleObjectType,
+ enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
+ static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
+ {
+ using std::begin;
+ using std::end;
+
+ j.m_type = value_t::object;
+ j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
+ j.assert_invariant();
+ }
+};
+
+
+////////////////////////
+// has_/is_ functions //
+////////////////////////
+
/*!
@brief Helper to determine whether there's a key_type for T.
+
+This helper is used to tell associative containers apart from other containers
+such as sequence containers. For instance, `std::map` passes the test as it
+contains a `mapped_type`, whereas `std::vector` fails the test.
+
@sa http://stackoverflow.com/a/7728728/266378
+@since version 1.0.0, overworked in version 2.0.6
*/
+#define NLOHMANN_JSON_HAS_HELPER(type) \
+ template<typename T> struct has_##type { \
+ private: \
+ template<typename U, typename = typename U::type> \
+ static int detect(U &&); \
+ static void detect(...); \
+ public: \
+ static constexpr bool value = \
+ std::is_integral<decltype(detect(std::declval<T>()))>::value; \
+ }
+
+NLOHMANN_JSON_HAS_HELPER(mapped_type);
+NLOHMANN_JSON_HAS_HELPER(key_type);
+NLOHMANN_JSON_HAS_HELPER(value_type);
+NLOHMANN_JSON_HAS_HELPER(iterator);
+
+#undef NLOHMANN_JSON_HAS_HELPER
+
+
+template<bool B, class RealType, class CompatibleObjectType>
+struct is_compatible_object_type_impl : std::false_type {};
+
+template<class RealType, class CompatibleObjectType>
+struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
+{
+ static constexpr auto value =
+ std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and
+ std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
+};
+
+template<class BasicJsonType, class CompatibleObjectType>
+struct is_compatible_object_type
+{
+ static auto constexpr value = is_compatible_object_type_impl <
+ conjunction<negation<std::is_same<void, CompatibleObjectType>>,
+ has_mapped_type<CompatibleObjectType>,
+ has_key_type<CompatibleObjectType>>::value,
+ typename BasicJsonType::object_t, CompatibleObjectType >::value;
+};
+
+template<typename BasicJsonType, typename T>
+struct is_basic_json_nested_type
+{
+ static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
+ std::is_same<T, typename BasicJsonType::const_iterator>::value or
+ std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
+ std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
+};
+
+template<class BasicJsonType, class CompatibleArrayType>
+struct is_compatible_array_type
+{
+ static auto constexpr value =
+ conjunction<negation<std::is_same<void, CompatibleArrayType>>,
+ negation<is_compatible_object_type<
+ BasicJsonType, CompatibleArrayType>>,
+ negation<std::is_constructible<typename BasicJsonType::string_t,
+ CompatibleArrayType>>,
+ negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
+ has_value_type<CompatibleArrayType>,
+ has_iterator<CompatibleArrayType>>::value;
+};
+
+template<bool, typename, typename>
+struct is_compatible_integer_type_impl : std::false_type {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
+{
+ // is there an assert somewhere on overflows?
+ using RealLimits = std::numeric_limits<RealIntegerType>;
+ using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
+
+ static constexpr auto value =
+ std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
+ CompatibleLimits::is_integer and
+ RealLimits::is_signed == CompatibleLimits::is_signed;
+};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type
+{
+ static constexpr auto value =
+ is_compatible_integer_type_impl <
+ std::is_integral<CompatibleNumberIntegerType>::value and
+ not std::is_same<bool, CompatibleNumberIntegerType>::value,
+ RealIntegerType, CompatibleNumberIntegerType >::value;
+};
+
+
+// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
+template<typename BasicJsonType, typename T>
+struct has_from_json
+{
+ private:
+ // also check the return type of from_json
+ template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
+ std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
+ static int detect(U&&);
+ static void detect(...);
+
+ public:
+ static constexpr bool value = std::is_integral<decltype(
+ detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
+};
+
+// This trait checks if JSONSerializer<T>::from_json(json const&) exists
+// this overload is used for non-default-constructible user-defined-types
+template<typename BasicJsonType, typename T>
+struct has_non_default_from_json
+{
+ private:
+ template<typename U, typename =
+ enable_if_t<std::is_same<T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value>>
+ static int detect(U&&);
+ static void detect(...);
+
+ public:
+ static constexpr bool value = std::is_integral<decltype(detect(
+ std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
+};
+
+// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
+template<typename BasicJsonType, typename T>
+struct has_to_json
+{
+ private:
+ template<typename U, typename = decltype(uncvref_t<U>::to_json(
+ std::declval<BasicJsonType&>(), std::declval<T>()))>
+ static int detect(U&&);
+ static void detect(...);
+
+ public:
+ static constexpr bool value = std::is_integral<decltype(detect(
+ std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
+};
+
+
+/////////////
+// to_json //
+/////////////
+
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+ external_constructor<value_t::boolean>::construct(j, b);
+}
+
+template<typename BasicJsonType, typename CompatibleString,
+ enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
+void to_json(BasicJsonType& j, const CompatibleString& s)
+{
+ external_constructor<value_t::string>::construct(j, s);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+{
+ external_constructor<value_t::string>::construct(j, std::move(s));
+}
+
+template<typename BasicJsonType, typename FloatType,
+ enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
+void to_json(BasicJsonType& j, FloatType val) noexcept
+{
+ external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
+ enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
+{
+ external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberIntegerType,
+ enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
+{
+ external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
+}
+
+template<typename BasicJsonType, typename EnumType,
+ enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void to_json(BasicJsonType& j, EnumType e) noexcept
+{
+ using underlying_type = typename std::underlying_type<EnumType>::type;
+ external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const std::vector<bool>& e)
+{
+ external_constructor<value_t::array>::construct(j, e);
+}
+
+template<typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
+ std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
+ int> = 0>
+void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
+{
+ external_constructor<value_t::array>::construct(j, arr);
+}
+
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+void to_json(BasicJsonType& j, std::valarray<T> arr)
+{
+ external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+{
+ external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType, typename CompatibleObjectType,
+ enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
+void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
+{
+ external_constructor<value_t::object>::construct(j, obj);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+{
+ external_constructor<value_t::object>::construct(j, std::move(obj));
+}
+
+template<typename BasicJsonType, typename T, std::size_t N,
+ enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0>
+void to_json(BasicJsonType& j, T (&arr)[N])
+{
+ external_constructor<value_t::array>::construct(j, arr);
+}
+
+template<typename BasicJsonType, typename... Args>
+void to_json(BasicJsonType& j, const std::pair<Args...>& p)
+{
+ j = {p.first, p.second};
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
+{
+ j = {std::get<Idx>(t)...};
+}
+
+template<typename BasicJsonType, typename... Args>
+void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
+{
+ to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
+}
+
+///////////////
+// from_json //
+///////////////
+
+// overloads for basic_json template parameters
+template<typename BasicJsonType, typename ArithmeticType,
+ enable_if_t<std::is_arithmetic<ArithmeticType>::value and
+ not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+ int> = 0>
+void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
+{
+ switch (static_cast<value_t>(j))
+ {
+ case value_t::number_unsigned:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+ break;
+ }
+ case value_t::number_integer:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+ break;
+ }
+ case value_t::number_float:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+ break;
+ }
+
+ default:
+ JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
+ }
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
+{
+ if (JSON_UNLIKELY(not j.is_boolean()))
+ {
+ JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
+ }
+ b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
+{
+ if (JSON_UNLIKELY(not j.is_string()))
+ {
+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
+ }
+ s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
+{
+ get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
+{
+ get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
+{
+ get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType, typename EnumType,
+ enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void from_json(const BasicJsonType& j, EnumType& e)
+{
+ typename std::underlying_type<EnumType>::type val;
+ get_arithmetic_value(j, val);
+ e = static_cast<EnumType>(val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
+}
+
+// forward_list doesn't have an insert method
+template<typename BasicJsonType, typename T, typename Allocator,
+ enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ std::transform(j.rbegin(), j.rend(),
+ std::front_inserter(l), [](const BasicJsonType & i)
+ {
+ return i.template get<T>();
+ });
+}
+
+// valarray doesn't have an insert method
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::valarray<T>& l)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ l.resize(j.size());
+ std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
+}
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
+{
+ using std::end;
+
+ std::transform(j.begin(), j.end(),
+ std::inserter(arr, end(arr)), [](const BasicJsonType & i)
+ {
+ // get<BasicJsonType>() returns *this, this won't call a from_json
+ // method when value_type is BasicJsonType
+ return i.template get<typename CompatibleArrayType::value_type>();
+ });
+}
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
+-> decltype(
+ arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
+ void())
+{
+ using std::end;
+
+ arr.reserve(j.size());
+ std::transform(j.begin(), j.end(),
+ std::inserter(arr, end(arr)), [](const BasicJsonType & i)
+ {
+ // get<BasicJsonType>() returns *this, this won't call a from_json
+ // method when value_type is BasicJsonType
+ return i.template get<typename CompatibleArrayType::value_type>();
+ });
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
+{
+ for (std::size_t i = 0; i < N; ++i)
+ {
+ arr[i] = j.at(i).template get<T>();
+ }
+}
+
+template<typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
+ std::is_convertible<BasicJsonType, typename CompatibleArrayType::value_type>::value and
+ not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
+void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+
+ from_json_array_impl(j, arr, priority_tag<2> {});
+}
+
+template<typename BasicJsonType, typename CompatibleObjectType,
+ enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
+void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
+{
+ if (JSON_UNLIKELY(not j.is_object()))
+ {
+ JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
+ }
+
+ auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
+ using value_type = typename CompatibleObjectType::value_type;
+ std::transform(
+ inner_object->begin(), inner_object->end(),
+ std::inserter(obj, obj.begin()),
+ [](typename BasicJsonType::object_t::value_type const & p)
+ {
+ return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
+ });
+}
+
+// overload for arithmetic types, not chosen for basic_json template arguments
+// (BooleanType, etc..); note: Is it really necessary to provide explicit
+// overloads for boolean_t etc. in case of a custom BooleanType which is not
+// an arithmetic type?
+template<typename BasicJsonType, typename ArithmeticType,
+ enable_if_t <
+ std::is_arithmetic<ArithmeticType>::value and
+ not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
+ not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
+ not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
+ not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+ int> = 0>
+void from_json(const BasicJsonType& j, ArithmeticType& val)
+{
+ switch (static_cast<value_t>(j))
+ {
+ case value_t::number_unsigned:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+ break;
+ }
+ case value_t::number_integer:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+ break;
+ }
+ case value_t::number_float:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+ break;
+ }
+ case value_t::boolean:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
+ break;
+ }
+
+ default:
+ JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
+ }
+}
+
+template<typename BasicJsonType, typename A1, typename A2>
+void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
+{
+ p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
+{
+ t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
+}
+
+template<typename BasicJsonType, typename... Args>
+void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
+{
+ from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
+}
+
+struct to_json_fn
+{
+ private:
+ template<typename BasicJsonType, typename T>
+ auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
+ -> decltype(to_json(j, std::forward<T>(val)), void())
+ {
+ return to_json(j, std::forward<T>(val));
+ }
+
+ template<typename BasicJsonType, typename T>
+ void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
+ {
+ static_assert(sizeof(BasicJsonType) == 0,
+ "could not find to_json() method in T's namespace");
+
+#ifdef _MSC_VER
+ // MSVC does not show a stacktrace for the above assert
+ using decayed = uncvref_t<T>;
+ static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
+ "forcing MSVC stacktrace to show which T we're talking about.");
+#endif
+ }
+
+ public:
+ template<typename BasicJsonType, typename T>
+ void operator()(BasicJsonType& j, T&& val) const
+ noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
+ {
+ return call(j, std::forward<T>(val), priority_tag<1> {});
+ }
+};
+
+struct from_json_fn
+{
+ private:
+ template<typename BasicJsonType, typename T>
+ auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const
+ noexcept(noexcept(from_json(j, val)))
+ -> decltype(from_json(j, val), void())
+ {
+ return from_json(j, val);
+ }
+
+ template<typename BasicJsonType, typename T>
+ void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
+ {
+ static_assert(sizeof(BasicJsonType) == 0,
+ "could not find from_json() method in T's namespace");
+#ifdef _MSC_VER
+ // MSVC does not show a stacktrace for the above assert
+ using decayed = uncvref_t<T>;
+ static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
+ "forcing MSVC stacktrace to show which T we're talking about.");
+#endif
+ }
+
+ public:
+ template<typename BasicJsonType, typename T>
+ void operator()(const BasicJsonType& j, T& val) const
+ noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
+ {
+ return call(j, val, priority_tag<1> {});
+ }
+};
+
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+ static constexpr T value{};
+};
+
template<typename T>
-struct has_mapped_type
+constexpr T static_const<T>::value;
+
+////////////////////
+// input adapters //
+////////////////////
+
+/*!
+@brief abstract input adapter interface
+
+Produces a stream of std::char_traits<char>::int_type characters from a
+std::istream, a buffer, or some other input type. Accepts the return of exactly
+one non-EOF character for future input. The int_type characters returned
+consist of all valid char values as positive values (typically unsigned char),
+plus an EOF value outside that range, specified by the value of the function
+std::char_traits<char>::eof(). This value is typically -1, but could be any
+arbitrary value which is not a valid char value.
+*/
+struct input_adapter_protocol
+{
+ /// get a character [0,255] or std::char_traits<char>::eof().
+ virtual std::char_traits<char>::int_type get_character() = 0;
+ /// restore the last non-eof() character to input
+ virtual void unget_character() = 0;
+ virtual ~input_adapter_protocol() = default;
+};
+
+/// a type to simplify interfaces
+using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
+
+/*!
+Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
+beginning of input. Does not support changing the underlying std::streambuf
+in mid-input. Maintains underlying std::istream and std::streambuf to support
+subsequent use of standard std::istream operations to process any input
+characters following those used in parsing the JSON input. Clears the
+std::istream flags; any input errors (e.g., EOF) will be detected by the first
+subsequent call for input from the std::istream.
+*/
+class input_stream_adapter : public input_adapter_protocol
+{
+ public:
+ ~input_stream_adapter() override
+ {
+ // clear stream flags; we use underlying streambuf I/O, do not
+ // maintain ifstream flags
+ is.clear();
+ }
+
+ explicit input_stream_adapter(std::istream& i)
+ : is(i), sb(*i.rdbuf())
+ {
+ // skip byte order mark
+ std::char_traits<char>::int_type c;
+ if ((c = get_character()) == 0xEF)
+ {
+ if ((c = get_character()) == 0xBB)
+ {
+ if ((c = get_character()) == 0xBF)
+ {
+ return; // Ignore BOM
+ }
+ else if (c != std::char_traits<char>::eof())
+ {
+ is.unget();
+ }
+ is.putback('\xBB');
+ }
+ else if (c != std::char_traits<char>::eof())
+ {
+ is.unget();
+ }
+ is.putback('\xEF');
+ }
+ else if (c != std::char_traits<char>::eof())
+ {
+ is.unget(); // no byte order mark; process as usual
+ }
+ }
+
+ // delete because of pointer members
+ input_stream_adapter(const input_stream_adapter&) = delete;
+ input_stream_adapter& operator=(input_stream_adapter&) = delete;
+
+ // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
+ // ensure that std::char_traits<char>::eof() and the character 0xFF do not
+ // end up as the same value, eg. 0xFFFFFFFF.
+ std::char_traits<char>::int_type get_character() override
+ {
+ return sb.sbumpc();
+ }
+
+ void unget_character() override
+ {
+ sb.sungetc(); // is.unget() avoided for performance
+ }
+
+ private:
+ /// the associated input stream
+ std::istream& is;
+ std::streambuf& sb;
+};
+
+/// input adapter for buffer input
+class input_buffer_adapter : public input_adapter_protocol
{
+ public:
+ input_buffer_adapter(const char* b, const std::size_t l)
+ : cursor(b), limit(b + l), start(b)
+ {
+ // skip byte order mark
+ if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF')
+ {
+ cursor += 3;
+ }
+ }
+
+ // delete because of pointer members
+ input_buffer_adapter(const input_buffer_adapter&) = delete;
+ input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
+
+ std::char_traits<char>::int_type get_character() noexcept override
+ {
+ if (JSON_LIKELY(cursor < limit))
+ {
+ return std::char_traits<char>::to_int_type(*(cursor++));
+ }
+
+ return std::char_traits<char>::eof();
+ }
+
+ void unget_character() noexcept override
+ {
+ if (JSON_LIKELY(cursor > start))
+ {
+ --cursor;
+ }
+ }
+
private:
- template<typename C> static char test(typename C::mapped_type*);
- template<typename C> static char (&test(...))[2];
+ /// pointer to the current character
+ const char* cursor;
+ /// pointer past the last character
+ const char* limit;
+ /// pointer to the first character
+ const char* start;
+};
+
+class input_adapter
+{
public:
- static constexpr bool value = sizeof(test<T>(0)) == 1;
+ // native support
+
+ /// input adapter for input stream
+ input_adapter(std::istream& i)
+ : ia(std::make_shared<input_stream_adapter>(i)) {}
+
+ /// input adapter for input stream
+ input_adapter(std::istream&& i)
+ : ia(std::make_shared<input_stream_adapter>(i)) {}
+
+ /// input adapter for buffer
+ template<typename CharT,
+ typename std::enable_if<
+ std::is_pointer<CharT>::value and
+ std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+ sizeof(typename std::remove_pointer<CharT>::type) == 1,
+ int>::type = 0>
+ input_adapter(CharT b, std::size_t l)
+ : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
+
+ // derived support
+
+ /// input adapter for string literal
+ template<typename CharT,
+ typename std::enable_if<
+ std::is_pointer<CharT>::value and
+ std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+ sizeof(typename std::remove_pointer<CharT>::type) == 1,
+ int>::type = 0>
+ input_adapter(CharT b)
+ : input_adapter(reinterpret_cast<const char*>(b),
+ std::strlen(reinterpret_cast<const char*>(b))) {}
+
+ /// input adapter for iterator range with contiguous storage
+ template<class IteratorType,
+ typename std::enable_if<
+ std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
+ int>::type = 0>
+ input_adapter(IteratorType first, IteratorType last)
+ {
+ // assertion to check that the iterator range is indeed contiguous,
+ // see http://stackoverflow.com/a/35008842/266378 for more discussion
+ assert(std::accumulate(
+ first, last, std::pair<bool, int>(true, 0),
+ [&first](std::pair<bool, int> res, decltype(*first) val)
+ {
+ res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
+ return res;
+ }).first);
+
+ // assertion to check that each element is 1 byte long
+ static_assert(
+ sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
+ "each element in the iterator range must have the size of 1 byte");
+
+ const auto len = static_cast<size_t>(std::distance(first, last));
+ if (JSON_LIKELY(len > 0))
+ {
+ // there is at least one element: use the address of first
+ ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
+ }
+ else
+ {
+ // the address of first cannot be used: use nullptr
+ ia = std::make_shared<input_buffer_adapter>(nullptr, len);
+ }
+ }
+
+ /// input adapter for array
+ template<class T, std::size_t N>
+ input_adapter(T (&array)[N])
+ : input_adapter(std::begin(array), std::end(array)) {}
+
+ /// input adapter for contiguous container
+ template<class ContiguousContainer, typename
+ std::enable_if<not std::is_pointer<ContiguousContainer>::value and
+ std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
+ int>::type = 0>
+ input_adapter(const ContiguousContainer& c)
+ : input_adapter(std::begin(c), std::end(c)) {}
+
+ operator input_adapter_t()
+ {
+ return ia;
+ }
+
+ private:
+ /// the actual adapter
+ input_adapter_t ia = nullptr;
};
+//////////////////////
+// lexer and parser //
+//////////////////////
+
/*!
-@brief helper class to create locales with decimal point
-@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315
+@brief lexical analysis
+
+This class organizes the lexical analysis during JSON deserialization.
*/
-class DecimalSeparator : public std::numpunct<char>
+template<typename BasicJsonType>
+class lexer
{
- protected:
- char do_decimal_point() const
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+
+ public:
+ /// token types for the parser
+ enum class token_type
+ {
+ uninitialized, ///< indicating the scanner is uninitialized
+ literal_true, ///< the `true` literal
+ literal_false, ///< the `false` literal
+ literal_null, ///< the `null` literal
+ value_string, ///< a string -- use get_string() for actual value
+ value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
+ value_integer, ///< a signed integer -- use get_number_integer() for actual value
+ value_float, ///< an floating point number -- use get_number_float() for actual value
+ begin_array, ///< the character for array begin `[`
+ begin_object, ///< the character for object begin `{`
+ end_array, ///< the character for array end `]`
+ end_object, ///< the character for object end `}`
+ name_separator, ///< the name separator `:`
+ value_separator, ///< the value separator `,`
+ parse_error, ///< indicating a parse error
+ end_of_input, ///< indicating the end of the input buffer
+ literal_or_value ///< a literal or the begin of a value (only for diagnostics)
+ };
+
+ /// return name of values of type token_type (only used for errors)
+ static const char* token_type_name(const token_type t) noexcept
+ {
+ switch (t)
+ {
+ case token_type::uninitialized:
+ return "<uninitialized>";
+ case token_type::literal_true:
+ return "true literal";
+ case token_type::literal_false:
+ return "false literal";
+ case token_type::literal_null:
+ return "null literal";
+ case token_type::value_string:
+ return "string literal";
+ case lexer::token_type::value_unsigned:
+ case lexer::token_type::value_integer:
+ case lexer::token_type::value_float:
+ return "number literal";
+ case token_type::begin_array:
+ return "'['";
+ case token_type::begin_object:
+ return "'{'";
+ case token_type::end_array:
+ return "']'";
+ case token_type::end_object:
+ return "'}'";
+ case token_type::name_separator:
+ return "':'";
+ case token_type::value_separator:
+ return "','";
+ case token_type::parse_error:
+ return "<parse error>";
+ case token_type::end_of_input:
+ return "end of input";
+ case token_type::literal_or_value:
+ return "'[', '{', or a literal";
+ default: // catch non-enum values
+ return "unknown token"; // LCOV_EXCL_LINE
+ }
+ }
+
+ explicit lexer(detail::input_adapter_t adapter)
+ : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
+
+ // delete because of pointer members
+ lexer(const lexer&) = delete;
+ lexer& operator=(lexer&) = delete;
+
+ private:
+ /////////////////////
+ // locales
+ /////////////////////
+
+ /// return the locale-dependent decimal point
+ static char get_decimal_point() noexcept
+ {
+ const auto loc = localeconv();
+ assert(loc != nullptr);
+ return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
+ }
+
+ /////////////////////
+ // scan functions
+ /////////////////////
+
+ /*!
+ @brief get codepoint from 4 hex characters following `\u`
+
+ For input "\u c1 c2 c3 c4" the codepoint is:
+ (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
+ = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
+
+ Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
+ must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
+ conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
+ between the ASCII value of the character and the desired integer value.
+
+ @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
+ non-hex character)
+ */
+ int get_codepoint()
+ {
+ // this function only makes sense after reading `\u`
+ assert(current == 'u');
+ int codepoint = 0;
+
+ const auto factors = { 12, 8, 4, 0 };
+ for (const auto factor : factors)
+ {
+ get();
+
+ if (current >= '0' and current <= '9')
+ {
+ codepoint += ((current - 0x30) << factor);
+ }
+ else if (current >= 'A' and current <= 'F')
+ {
+ codepoint += ((current - 0x37) << factor);
+ }
+ else if (current >= 'a' and current <= 'f')
+ {
+ codepoint += ((current - 0x57) << factor);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
+ return codepoint;
+ }
+
+ /*!
+ @brief check if the next byte(s) are inside a given range
+
+ Adds the current byte and, for each passed range, reads a new byte and
+ checks if it is inside the range. If a violation was detected, set up an
+ error message and return false. Otherwise, return true.
+
+ @param[in] ranges list of integers; interpreted as list of pairs of
+ inclusive lower and upper bound, respectively
+
+ @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
+ 1, 2, or 3 pairs. This precondition is enforced by an assertion.
+
+ @return true if and only if no range violation was detected
+ */
+ bool next_byte_in_range(std::initializer_list<int> ranges)
+ {
+ assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
+ add(current);
+
+ for (auto range = ranges.begin(); range != ranges.end(); ++range)
+ {
+ get();
+ if (JSON_LIKELY(*range <= current and current <= *(++range)))
+ {
+ add(current);
+ }
+ else
+ {
+ error_message = "invalid string: ill-formed UTF-8 byte";
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /*!
+ @brief scan a string literal
+
+ This function scans a string according to Sect. 7 of RFC 7159. While
+ scanning, bytes are escaped and copied into buffer yytext. Then the function
+ returns successfully, yytext is *not* null-terminated (as it may contain \0
+ bytes), and yytext.size() is the number of bytes in the string.
+
+ @return token_type::value_string if string could be successfully scanned,
+ token_type::parse_error otherwise
+
+ @note In case of errors, variable error_message contains a textual
+ description.
+ */
+ token_type scan_string()
+ {
+ // reset yytext (ignore opening quote)
+ reset();
+
+ // we entered the function by reading an open quote
+ assert(current == '\"');
+
+ while (true)
+ {
+ // get next character
+ switch (get())
+ {
+ // end of file while parsing string
+ case std::char_traits<char>::eof():
+ {
+ error_message = "invalid string: missing closing quote";
+ return token_type::parse_error;
+ }
+
+ // closing quote
+ case '\"':
+ {
+ return token_type::value_string;
+ }
+
+ // escapes
+ case '\\':
+ {
+ switch (get())
+ {
+ // quotation mark
+ case '\"':
+ add('\"');
+ break;
+ // reverse solidus
+ case '\\':
+ add('\\');
+ break;
+ // solidus
+ case '/':
+ add('/');
+ break;
+ // backspace
+ case 'b':
+ add('\b');
+ break;
+ // form feed
+ case 'f':
+ add('\f');
+ break;
+ // line feed
+ case 'n':
+ add('\n');
+ break;
+ // carriage return
+ case 'r':
+ add('\r');
+ break;
+ // tab
+ case 't':
+ add('\t');
+ break;
+
+ // unicode escapes
+ case 'u':
+ {
+ const int codepoint1 = get_codepoint();
+ int codepoint = codepoint1; // start with codepoint1
+
+ if (JSON_UNLIKELY(codepoint1 == -1))
+ {
+ error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+ return token_type::parse_error;
+ }
+
+ // check if code point is a high surrogate
+ if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
+ {
+ // expect next \uxxxx entry
+ if (JSON_LIKELY(get() == '\\' and get() == 'u'))
+ {
+ const int codepoint2 = get_codepoint();
+
+ if (JSON_UNLIKELY(codepoint2 == -1))
+ {
+ error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+ return token_type::parse_error;
+ }
+
+ // check if codepoint2 is a low surrogate
+ if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
+ {
+ // overwrite codepoint
+ codepoint =
+ // high surrogate occupies the most significant 22 bits
+ (codepoint1 << 10)
+ // low surrogate occupies the least significant 15 bits
+ + codepoint2
+ // there is still the 0xD800, 0xDC00 and 0x10000 noise
+ // in the result so we have to subtract with:
+ // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
+ - 0x35FDC00;
+ }
+ else
+ {
+ error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
+ return token_type::parse_error;
+ }
+ }
+ else
+ {
+ error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
+ return token_type::parse_error;
+ }
+ }
+ else
+ {
+ if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
+ {
+ error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
+ return token_type::parse_error;
+ }
+ }
+
+ // result of the above calculation yields a proper codepoint
+ assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
+
+ // translate codepoint into bytes
+ if (codepoint < 0x80)
+ {
+ // 1-byte characters: 0xxxxxxx (ASCII)
+ add(codepoint);
+ }
+ else if (codepoint <= 0x7FF)
+ {
+ // 2-byte characters: 110xxxxx 10xxxxxx
+ add(0xC0 | (codepoint >> 6));
+ add(0x80 | (codepoint & 0x3F));
+ }
+ else if (codepoint <= 0xFFFF)
+ {
+ // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
+ add(0xE0 | (codepoint >> 12));
+ add(0x80 | ((codepoint >> 6) & 0x3F));
+ add(0x80 | (codepoint & 0x3F));
+ }
+ else
+ {
+ // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ add(0xF0 | (codepoint >> 18));
+ add(0x80 | ((codepoint >> 12) & 0x3F));
+ add(0x80 | ((codepoint >> 6) & 0x3F));
+ add(0x80 | (codepoint & 0x3F));
+ }
+
+ break;
+ }
+
+ // other characters after escape
+ default:
+ error_message = "invalid string: forbidden character after backslash";
+ return token_type::parse_error;
+ }
+
+ break;
+ }
+
+ // invalid control characters
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1A:
+ case 0x1B:
+ case 0x1C:
+ case 0x1D:
+ case 0x1E:
+ case 0x1F:
+ {
+ error_message = "invalid string: control character must be escaped";
+ return token_type::parse_error;
+ }
+
+ // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
+ case 0x20:
+ case 0x21:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0x3B:
+ case 0x3C:
+ case 0x3D:
+ case 0x3E:
+ case 0x3F:
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B:
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78:
+ case 0x79:
+ case 0x7A:
+ case 0x7B:
+ case 0x7C:
+ case 0x7D:
+ case 0x7E:
+ case 0x7F:
+ {
+ add(current);
+ break;
+ }
+
+ // U+0080..U+07FF: bytes C2..DF 80..BF
+ case 0xC2:
+ case 0xC3:
+ case 0xC4:
+ case 0xC5:
+ case 0xC6:
+ case 0xC7:
+ case 0xC8:
+ case 0xC9:
+ case 0xCA:
+ case 0xCB:
+ case 0xCC:
+ case 0xCD:
+ case 0xCE:
+ case 0xCF:
+ case 0xD0:
+ case 0xD1:
+ case 0xD2:
+ case 0xD3:
+ case 0xD4:
+ case 0xD5:
+ case 0xD6:
+ case 0xD7:
+ case 0xD8:
+ case 0xD9:
+ case 0xDA:
+ case 0xDB:
+ case 0xDC:
+ case 0xDD:
+ case 0xDE:
+ case 0xDF:
+ {
+ if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
+ case 0xE0:
+ {
+ if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
+ // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
+ case 0xE1:
+ case 0xE2:
+ case 0xE3:
+ case 0xE4:
+ case 0xE5:
+ case 0xE6:
+ case 0xE7:
+ case 0xE8:
+ case 0xE9:
+ case 0xEA:
+ case 0xEB:
+ case 0xEC:
+ case 0xEE:
+ case 0xEF:
+ {
+ if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+D000..U+D7FF: bytes ED 80..9F 80..BF
+ case 0xED:
+ {
+ if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
+ case 0xF0:
+ {
+ if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
+ case 0xF1:
+ case 0xF2:
+ case 0xF3:
+ {
+ if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+ case 0xF4:
+ {
+ if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // remaining bytes (80..C1 and F5..FF) are ill-formed
+ default:
+ {
+ error_message = "invalid string: ill-formed UTF-8 byte";
+ return token_type::parse_error;
+ }
+ }
+ }
+ }
+
+ static void strtof(float& f, const char* str, char** endptr) noexcept
+ {
+ f = std::strtof(str, endptr);
+ }
+
+ static void strtof(double& f, const char* str, char** endptr) noexcept
+ {
+ f = std::strtod(str, endptr);
+ }
+
+ static void strtof(long double& f, const char* str, char** endptr) noexcept
+ {
+ f = std::strtold(str, endptr);
+ }
+
+ /*!
+ @brief scan a number literal
+
+ This function scans a string according to Sect. 6 of RFC 7159.
+
+ The function is realized with a deterministic finite state machine derived
+ from the grammar described in RFC 7159. Starting in state "init", the
+ input is read and used to determined the next state. Only state "done"
+ accepts the number. State "error" is a trap state to model errors. In the
+ table below, "anything" means any character but the ones listed before.
+
+ state | 0 | 1-9 | e E | + | - | . | anything
+ ---------|----------|----------|----------|---------|---------|----------|-----------
+ init | zero | any1 | [error] | [error] | minus | [error] | [error]
+ minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
+ zero | done | done | exponent | done | done | decimal1 | done
+ any1 | any1 | any1 | exponent | done | done | decimal1 | done
+ decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error]
+ decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
+ exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
+ sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
+ any2 | any2 | any2 | done | done | done | done | done
+
+ The state machine is realized with one label per state (prefixed with
+ "scan_number_") and `goto` statements between them. The state machine
+ contains cycles, but any cycle can be left when EOF is read. Therefore,
+ the function is guaranteed to terminate.
+
+ During scanning, the read bytes are stored in yytext. This string is
+ then converted to a signed integer, an unsigned integer, or a
+ floating-point number.
+
+ @return token_type::value_unsigned, token_type::value_integer, or
+ token_type::value_float if number could be successfully scanned,
+ token_type::parse_error otherwise
+
+ @note The scanner is independent of the current locale. Internally, the
+ locale's decimal point is used instead of `.` to work with the
+ locale-dependent converters.
+ */
+ token_type scan_number()
+ {
+ // reset yytext to store the number's bytes
+ reset();
+
+ // the type of the parsed number; initially set to unsigned; will be
+ // changed if minus sign, decimal point or exponent is read
+ token_type number_type = token_type::value_unsigned;
+
+ // state (init): we just found out we need to scan a number
+ switch (current)
+ {
+ case '-':
+ {
+ add(current);
+ goto scan_number_minus;
+ }
+
+ case '0':
+ {
+ add(current);
+ goto scan_number_zero;
+ }
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any1;
+ }
+
+ default:
+ {
+ // all other characters are rejected outside scan_number()
+ assert(false); // LCOV_EXCL_LINE
+ }
+ }
+
+scan_number_minus:
+ // state: we just parsed a leading minus sign
+ number_type = token_type::value_integer;
+ switch (get())
+ {
+ case '0':
+ {
+ add(current);
+ goto scan_number_zero;
+ }
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any1;
+ }
+
+ default:
+ {
+ error_message = "invalid number; expected digit after '-'";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_zero:
+ // state: we just parse a zero (maybe with a leading minus sign)
+ switch (get())
+ {
+ case '.':
+ {
+ add(decimal_point_char);
+ goto scan_number_decimal1;
+ }
+
+ case 'e':
+ case 'E':
+ {
+ add(current);
+ goto scan_number_exponent;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_any1:
+ // state: we just parsed a number 0-9 (maybe with a leading minus sign)
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any1;
+ }
+
+ case '.':
+ {
+ add(decimal_point_char);
+ goto scan_number_decimal1;
+ }
+
+ case 'e':
+ case 'E':
+ {
+ add(current);
+ goto scan_number_exponent;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_decimal1:
+ // state: we just parsed a decimal point
+ number_type = token_type::value_float;
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_decimal2;
+ }
+
+ default:
+ {
+ error_message = "invalid number; expected digit after '.'";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_decimal2:
+ // we just parsed at least one number after a decimal point
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_decimal2;
+ }
+
+ case 'e':
+ case 'E':
+ {
+ add(current);
+ goto scan_number_exponent;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_exponent:
+ // we just parsed an exponent
+ number_type = token_type::value_float;
+ switch (get())
+ {
+ case '+':
+ case '-':
+ {
+ add(current);
+ goto scan_number_sign;
+ }
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any2;
+ }
+
+ default:
+ {
+ error_message =
+ "invalid number; expected '+', '-', or digit after exponent";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_sign:
+ // we just parsed an exponent sign
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any2;
+ }
+
+ default:
+ {
+ error_message = "invalid number; expected digit after exponent sign";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_any2:
+ // we just parsed a number after the exponent or exponent sign
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any2;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_done:
+ // unget the character after the number (we only read it to know that
+ // we are done scanning a number)
+ unget();
+
+ char* endptr = nullptr;
+ errno = 0;
+
+ // try to parse integers first and fall back to floats
+ if (number_type == token_type::value_unsigned)
+ {
+ const auto x = std::strtoull(yytext.data(), &endptr, 10);
+
+ // we checked the number format before
+ assert(endptr == yytext.data() + yytext.size());
+
+ if (errno == 0)
+ {
+ value_unsigned = static_cast<number_unsigned_t>(x);
+ if (value_unsigned == x)
+ {
+ return token_type::value_unsigned;
+ }
+ }
+ }
+ else if (number_type == token_type::value_integer)
+ {
+ const auto x = std::strtoll(yytext.data(), &endptr, 10);
+
+ // we checked the number format before
+ assert(endptr == yytext.data() + yytext.size());
+
+ if (errno == 0)
+ {
+ value_integer = static_cast<number_integer_t>(x);
+ if (value_integer == x)
+ {
+ return token_type::value_integer;
+ }
+ }
+ }
+
+ // this code is reached if we parse a floating-point number or if an
+ // integer conversion above failed
+ strtof(value_float, yytext.data(), &endptr);
+
+ // we checked the number format before
+ assert(endptr == yytext.data() + yytext.size());
+
+ return token_type::value_float;
+ }
+
+ /*!
+ @param[in] literal_text the literal text to expect
+ @param[in] length the length of the passed literal text
+ @param[in] return_type the token type to return on success
+ */
+ token_type scan_literal(const char* literal_text, const std::size_t length,
+ token_type return_type)
+ {
+ assert(current == literal_text[0]);
+ for (std::size_t i = 1; i < length; ++i)
+ {
+ if (JSON_UNLIKELY(get() != literal_text[i]))
+ {
+ error_message = "invalid literal";
+ return token_type::parse_error;
+ }
+ }
+ return return_type;
+ }
+
+ /////////////////////
+ // input management
+ /////////////////////
+
+ /// reset yytext; current character is beginning of token
+ void reset() noexcept
+ {
+ yytext.clear();
+ token_string.clear();
+ token_string.push_back(std::char_traits<char>::to_char_type(current));
+ }
+
+ /*
+ @brief get next character from the input
+
+ This function provides the interface to the used input adapter. It does
+ not throw in case the input reached EOF, but returns a
+ `std::char_traits<char>::eof()` in that case. Stores the scanned characters
+ for use in error messages.
+
+ @return character read from the input
+ */
+ std::char_traits<char>::int_type get()
+ {
+ ++chars_read;
+ current = ia->get_character();
+ if (JSON_LIKELY(current != std::char_traits<char>::eof()))
+ {
+ token_string.push_back(std::char_traits<char>::to_char_type(current));
+ }
+ return current;
+ }
+
+ /// unget current character (return it again on next get)
+ void unget()
+ {
+ --chars_read;
+ if (JSON_LIKELY(current != std::char_traits<char>::eof()))
+ {
+ ia->unget_character();
+ assert(token_string.size() != 0);
+ token_string.pop_back();
+ }
+ }
+
+ /// add a character to yytext
+ void add(int c)
+ {
+ yytext.push_back(std::char_traits<char>::to_char_type(c));
+ }
+
+ public:
+ /////////////////////
+ // value getters
+ /////////////////////
+
+ /// return integer value
+ constexpr number_integer_t get_number_integer() const noexcept
+ {
+ return value_integer;
+ }
+
+ /// return unsigned integer value
+ constexpr number_unsigned_t get_number_unsigned() const noexcept
+ {
+ return value_unsigned;
+ }
+
+ /// return floating-point value
+ constexpr number_float_t get_number_float() const noexcept
+ {
+ return value_float;
+ }
+
+ /// return current string value (implicitly resets the token; useful only once)
+ std::string move_string()
+ {
+ return std::move(yytext);
+ }
+
+ /////////////////////
+ // diagnostics
+ /////////////////////
+
+ /// return position of last read token
+ constexpr std::size_t get_position() const noexcept
+ {
+ return chars_read;
+ }
+
+ /// return the last read token (for errors only). Will never contain EOF
+ /// (an arbitrary value that is not a valid char value, often -1), because
+ /// 255 may legitimately occur. May contain NUL, which should be escaped.
+ std::string get_token_string() const
+ {
+ // escape control characters
+ std::string result;
+ for (const auto c : token_string)
+ {
+ if ('\x00' <= c and c <= '\x1F')
+ {
+ // escape control characters
+ std::stringstream ss;
+ ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0')
+ << std::hex << static_cast<int>(c) << ">";
+ result += ss.str();
+ }
+ else
+ {
+ // add character as is
+ result.push_back(c);
+ }
+ }
+
+ return result;
+ }
+
+ /// return syntax error message
+ constexpr const char* get_error_message() const noexcept
+ {
+ return error_message;
+ }
+
+ /////////////////////
+ // actual scanner
+ /////////////////////
+
+ token_type scan()
+ {
+ // read next character and ignore whitespace
+ do
+ {
+ get();
+ }
+ while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
+
+ switch (current)
+ {
+ // structural characters
+ case '[':
+ return token_type::begin_array;
+ case ']':
+ return token_type::end_array;
+ case '{':
+ return token_type::begin_object;
+ case '}':
+ return token_type::end_object;
+ case ':':
+ return token_type::name_separator;
+ case ',':
+ return token_type::value_separator;
+
+ // literals
+ case 't':
+ return scan_literal("true", 4, token_type::literal_true);
+ case 'f':
+ return scan_literal("false", 5, token_type::literal_false);
+ case 'n':
+ return scan_literal("null", 4, token_type::literal_null);
+
+ // string
+ case '\"':
+ return scan_string();
+
+ // number
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return scan_number();
+
+ // end of input (the null byte is needed when parsing from
+ // string literals)
+ case '\0':
+ case std::char_traits<char>::eof():
+ return token_type::end_of_input;
+
+ // error
+ default:
+ error_message = "invalid literal";
+ return token_type::parse_error;
+ }
+ }
+
+ private:
+ /// input adapter
+ detail::input_adapter_t ia = nullptr;
+
+ /// the current character
+ std::char_traits<char>::int_type current = std::char_traits<char>::eof();
+
+ /// the number of characters read
+ std::size_t chars_read = 0;
+
+ /// raw input token string (for error messages)
+ std::vector<char> token_string {};
+
+ /// buffer for variable-length tokens (numbers, strings)
+ std::string yytext {};
+
+ /// a description of occurred lexer errors
+ const char* error_message = "";
+
+ // number values
+ number_integer_t value_integer = 0;
+ number_unsigned_t value_unsigned = 0;
+ number_float_t value_float = 0;
+
+ /// the decimal point
+ const char decimal_point_char = '.';
+};
+
+/*!
+@brief syntax analysis
+
+This class implements a recursive decent parser.
+*/
+template<typename BasicJsonType>
+class parser
+{
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using lexer_t = lexer<BasicJsonType>;
+ using token_type = typename lexer_t::token_type;
+
+ public:
+ enum class parse_event_t : uint8_t
+ {
+ /// the parser read `{` and started to process a JSON object
+ object_start,
+ /// the parser read `}` and finished processing a JSON object
+ object_end,
+ /// the parser read `[` and started to process a JSON array
+ array_start,
+ /// the parser read `]` and finished processing a JSON array
+ array_end,
+ /// the parser read a key of a value in an object
+ key,
+ /// the parser finished reading a JSON value
+ value
+ };
+
+ using parser_callback_t =
+ std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
+
+ /// a parser reading from an input adapter
+ explicit parser(detail::input_adapter_t adapter,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions_ = true)
+ : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
+ {}
+
+ /*!
+ @brief public parser interface
+
+ @param[in] strict whether to expect the last token to be EOF
+ @param[in,out] result parsed JSON value
+
+ @throw parse_error.101 in case of an unexpected token
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+ */
+ void parse(const bool strict, BasicJsonType& result)
+ {
+ // read first token
+ get_token();
+
+ parse_internal(true, result);
+ result.assert_invariant();
+
+ // in strict mode, input must be completely read
+ if (strict)
+ {
+ get_token();
+ expect(token_type::end_of_input);
+ }
+
+ // in case of an error, return discarded value
+ if (errored)
+ {
+ result = value_t::discarded;
+ return;
+ }
+
+ // set top-level value to null if it was discarded by the callback
+ // function
+ if (result.is_discarded())
+ {
+ result = nullptr;
+ }
+ }
+
+ /*!
+ @brief public accept interface
+
+ @param[in] strict whether to expect the last token to be EOF
+ @return whether the input is a proper JSON text
+ */
+ bool accept(const bool strict = true)
+ {
+ // read first token
+ get_token();
+
+ if (not accept_internal())
+ {
+ return false;
+ }
+
+ // strict => last token must be EOF
+ return not strict or (get_token() == token_type::end_of_input);
+ }
+
+ private:
+ /*!
+ @brief the actual parser
+ @throw parse_error.101 in case of an unexpected token
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+ */
+ void parse_internal(bool keep, BasicJsonType& result)
+ {
+ // never parse after a parse error was detected
+ assert(not errored);
+
+ // start with a discarded value
+ if (not result.is_discarded())
+ {
+ result.m_value.destroy(result.m_type);
+ result.m_type = value_t::discarded;
+ }
+
+ switch (last_token)
+ {
+ case token_type::begin_object:
+ {
+ if (keep)
+ {
+ if (callback)
+ {
+ keep = callback(depth++, parse_event_t::object_start, result);
+ }
+
+ if (not callback or keep)
+ {
+ // explicitly set result to object to cope with {}
+ result.m_type = value_t::object;
+ result.m_value = value_t::object;
+ }
+ }
+
+ // read next token
+ get_token();
+
+ // closing } -> we are done
+ if (last_token == token_type::end_object)
+ {
+ if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
+ {
+ result.m_value.destroy(result.m_type);
+ result.m_type = value_t::discarded;
+ }
+ break;
+ }
+
+ // parse values
+ std::string key;
+ BasicJsonType value;
+ while (true)
+ {
+ // store key
+ if (not expect(token_type::value_string))
+ {
+ return;
+ }
+ key = m_lexer.move_string();
+
+ bool keep_tag = false;
+ if (keep)
+ {
+ if (callback)
+ {
+ BasicJsonType k(key);
+ keep_tag = callback(depth, parse_event_t::key, k);
+ }
+ else
+ {
+ keep_tag = true;
+ }
+ }
+
+ // parse separator (:)
+ get_token();
+ if (not expect(token_type::name_separator))
+ {
+ return;
+ }
+
+ // parse and add value
+ get_token();
+ value.m_value.destroy(value.m_type);
+ value.m_type = value_t::discarded;
+ parse_internal(keep, value);
+
+ if (JSON_UNLIKELY(errored))
+ {
+ return;
+ }
+
+ if (keep and keep_tag and not value.is_discarded())
+ {
+ result.m_value.object->emplace(std::move(key), std::move(value));
+ }
+
+ // comma -> next value
+ get_token();
+ if (last_token == token_type::value_separator)
+ {
+ get_token();
+ continue;
+ }
+
+ // closing }
+ if (not expect(token_type::end_object))
+ {
+ return;
+ }
+ break;
+ }
+
+ if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
+ {
+ result.m_value.destroy(result.m_type);
+ result.m_type = value_t::discarded;
+ }
+ break;
+ }
+
+ case token_type::begin_array:
+ {
+ if (keep)
+ {
+ if (callback)
+ {
+ keep = callback(depth++, parse_event_t::array_start, result);
+ }
+
+ if (not callback or keep)
+ {
+ // explicitly set result to array to cope with []
+ result.m_type = value_t::array;
+ result.m_value = value_t::array;
+ }
+ }
+
+ // read next token
+ get_token();
+
+ // closing ] -> we are done
+ if (last_token == token_type::end_array)
+ {
+ if (callback and not callback(--depth, parse_event_t::array_end, result))
+ {
+ result.m_value.destroy(result.m_type);
+ result.m_type = value_t::discarded;
+ }
+ break;
+ }
+
+ // parse values
+ BasicJsonType value;
+ while (true)
+ {
+ // parse value
+ value.m_value.destroy(value.m_type);
+ value.m_type = value_t::discarded;
+ parse_internal(keep, value);
+
+ if (JSON_UNLIKELY(errored))
+ {
+ return;
+ }
+
+ if (keep and not value.is_discarded())
+ {
+ result.m_value.array->push_back(std::move(value));
+ }
+
+ // comma -> next value
+ get_token();
+ if (last_token == token_type::value_separator)
+ {
+ get_token();
+ continue;
+ }
+
+ // closing ]
+ if (not expect(token_type::end_array))
+ {
+ return;
+ }
+ break;
+ }
+
+ if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
+ {
+ result.m_value.destroy(result.m_type);
+ result.m_type = value_t::discarded;
+ }
+ break;
+ }
+
+ case token_type::literal_null:
+ {
+ result.m_type = value_t::null;
+ break;
+ }
+
+ case token_type::value_string:
+ {
+ result.m_type = value_t::string;
+ result.m_value = m_lexer.move_string();
+ break;
+ }
+
+ case token_type::literal_true:
+ {
+ result.m_type = value_t::boolean;
+ result.m_value = true;
+ break;
+ }
+
+ case token_type::literal_false:
+ {
+ result.m_type = value_t::boolean;
+ result.m_value = false;
+ break;
+ }
+
+ case token_type::value_unsigned:
+ {
+ result.m_type = value_t::number_unsigned;
+ result.m_value = m_lexer.get_number_unsigned();
+ break;
+ }
+
+ case token_type::value_integer:
+ {
+ result.m_type = value_t::number_integer;
+ result.m_value = m_lexer.get_number_integer();
+ break;
+ }
+
+ case token_type::value_float:
+ {
+ result.m_type = value_t::number_float;
+ result.m_value = m_lexer.get_number_float();
+
+ // throw in case of infinity or NAN
+ if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
+ {
+ if (allow_exceptions)
+ {
+ JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
+ m_lexer.get_token_string() + "'"));
+ }
+ expect(token_type::uninitialized);
+ }
+ break;
+ }
+
+ case token_type::parse_error:
+ {
+ // using "uninitialized" to avoid "expected" message
+ if (not expect(token_type::uninitialized))
+ {
+ return;
+ }
+ break; // LCOV_EXCL_LINE
+ }
+
+ default:
+ {
+ // the last token was unexpected; we expected a value
+ if (not expect(token_type::literal_or_value))
+ {
+ return;
+ }
+ break; // LCOV_EXCL_LINE
+ }
+ }
+
+ if (keep and callback and not callback(depth, parse_event_t::value, result))
+ {
+ result.m_type = value_t::discarded;
+ }
+ }
+
+ /*!
+ @brief the actual acceptor
+
+ @invariant 1. The last token is not yet processed. Therefore, the caller
+ of this function must make sure a token has been read.
+ 2. When this function returns, the last token is processed.
+ That is, the last read character was already considered.
+
+ This invariant makes sure that no token needs to be "unput".
+ */
+ bool accept_internal()
+ {
+ switch (last_token)
+ {
+ case token_type::begin_object:
+ {
+ // read next token
+ get_token();
+
+ // closing } -> we are done
+ if (last_token == token_type::end_object)
+ {
+ return true;
+ }
+
+ // parse values
+ while (true)
+ {
+ // parse key
+ if (last_token != token_type::value_string)
+ {
+ return false;
+ }
+
+ // parse separator (:)
+ get_token();
+ if (last_token != token_type::name_separator)
+ {
+ return false;
+ }
+
+ // parse value
+ get_token();
+ if (not accept_internal())
+ {
+ return false;
+ }
+
+ // comma -> next value
+ get_token();
+ if (last_token == token_type::value_separator)
+ {
+ get_token();
+ continue;
+ }
+
+ // closing }
+ return (last_token == token_type::end_object);
+ }
+ }
+
+ case token_type::begin_array:
+ {
+ // read next token
+ get_token();
+
+ // closing ] -> we are done
+ if (last_token == token_type::end_array)
+ {
+ return true;
+ }
+
+ // parse values
+ while (true)
+ {
+ // parse value
+ if (not accept_internal())
+ {
+ return false;
+ }
+
+ // comma -> next value
+ get_token();
+ if (last_token == token_type::value_separator)
+ {
+ get_token();
+ continue;
+ }
+
+ // closing ]
+ return (last_token == token_type::end_array);
+ }
+ }
+
+ case token_type::value_float:
+ {
+ // reject infinity or NAN
+ return std::isfinite(m_lexer.get_number_float());
+ }
+
+ case token_type::literal_false:
+ case token_type::literal_null:
+ case token_type::literal_true:
+ case token_type::value_integer:
+ case token_type::value_string:
+ case token_type::value_unsigned:
+ return true;
+
+ default: // the last token was unexpected
+ return false;
+ }
+ }
+
+ /// get next token from lexer
+ token_type get_token()
+ {
+ return (last_token = m_lexer.scan());
+ }
+
+ /*!
+ @throw parse_error.101 if expected token did not occur
+ */
+ bool expect(token_type t)
+ {
+ if (JSON_UNLIKELY(t != last_token))
+ {
+ errored = true;
+ expected = t;
+ if (allow_exceptions)
+ {
+ throw_exception();
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [[noreturn]] void throw_exception() const
+ {
+ std::string error_msg = "syntax error - ";
+ if (last_token == token_type::parse_error)
+ {
+ error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
+ m_lexer.get_token_string() + "'";
+ }
+ else
+ {
+ error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
+ }
+
+ if (expected != token_type::uninitialized)
+ {
+ error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
+ }
+
+ JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
+ }
+
+ private:
+ /// current level of recursion
+ int depth = 0;
+ /// callback function
+ const parser_callback_t callback = nullptr;
+ /// the type of the last read token
+ token_type last_token = token_type::uninitialized;
+ /// the lexer
+ lexer_t m_lexer;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// possible reason for the syntax error
+ token_type expected = token_type::uninitialized;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+};
+
+///////////////
+// iterators //
+///////////////
+
+/*!
+@brief an iterator for primitive JSON types
+
+This class models an iterator for primitive JSON types (boolean, number,
+string). It's only purpose is to allow the iterator/const_iterator classes
+to "iterate" over primitive values. Internally, the iterator is modeled by
+a `difference_type` variable. Value begin_value (`0`) models the begin,
+end_value (`1`) models past the end.
+*/
+class primitive_iterator_t
+{
+ public:
+ using difference_type = std::ptrdiff_t;
+
+ constexpr difference_type get_value() const noexcept
+ {
+ return m_it;
+ }
+
+ /// set iterator to a defined beginning
+ void set_begin() noexcept
+ {
+ m_it = begin_value;
+ }
+
+ /// set iterator to a defined past the end
+ void set_end() noexcept
+ {
+ m_it = end_value;
+ }
+
+ /// return whether the iterator can be dereferenced
+ constexpr bool is_begin() const noexcept
+ {
+ return m_it == begin_value;
+ }
+
+ /// return whether the iterator is at end
+ constexpr bool is_end() const noexcept
+ {
+ return m_it == end_value;
+ }
+
+ friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+ {
+ return lhs.m_it == rhs.m_it;
+ }
+
+ friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+ {
+ return lhs.m_it < rhs.m_it;
+ }
+
+ primitive_iterator_t operator+(difference_type i)
+ {
+ auto result = *this;
+ result += i;
+ return result;
+ }
+
+ friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+ {
+ return lhs.m_it - rhs.m_it;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
+ {
+ return os << it.m_it;
+ }
+
+ primitive_iterator_t& operator++()
+ {
+ ++m_it;
+ return *this;
+ }
+
+ primitive_iterator_t const operator++(int)
+ {
+ auto result = *this;
+ m_it++;
+ return result;
+ }
+
+ primitive_iterator_t& operator--()
+ {
+ --m_it;
+ return *this;
+ }
+
+ primitive_iterator_t const operator--(int)
+ {
+ auto result = *this;
+ m_it--;
+ return result;
+ }
+
+ primitive_iterator_t& operator+=(difference_type n)
+ {
+ m_it += n;
+ return *this;
+ }
+
+ primitive_iterator_t& operator-=(difference_type n)
+ {
+ m_it -= n;
+ return *this;
+ }
+
+ private:
+ static constexpr difference_type begin_value = 0;
+ static constexpr difference_type end_value = begin_value + 1;
+
+ /// iterator as signed integer type
+ difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
+};
+
+/*!
+@brief an iterator value
+
+@note This structure could easily be a union, but MSVC currently does not allow
+unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
+*/
+template<typename BasicJsonType> struct internal_iterator
+{
+ /// iterator for JSON objects
+ typename BasicJsonType::object_t::iterator object_iterator {};
+ /// iterator for JSON arrays
+ typename BasicJsonType::array_t::iterator array_iterator {};
+ /// generic iterator for all other types
+ primitive_iterator_t primitive_iterator {};
+};
+
+template<typename IteratorType> class iteration_proxy;
+
+/*!
+@brief a template for a bidirectional iterator for the @ref basic_json class
+
+This class implements a both iterators (iterator and const_iterator) for the
+@ref basic_json class.
+
+@note An iterator is called *initialized* when a pointer to a JSON value has
+ been set (e.g., by a constructor or a copy assignment). If the iterator is
+ default-constructed, it is *uninitialized* and most methods are undefined.
+ **The library uses assertions to detect calls on uninitialized iterators.**
+
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
+ The iterator that can be moved can be moved in both directions (i.e.
+ incremented and decremented).
+
+@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
+ iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
+*/
+template<typename BasicJsonType>
+class iter_impl
+{
+ /// allow basic_json to access private members
+ friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
+ friend BasicJsonType;
+ friend iteration_proxy<iter_impl>;
+
+ using object_t = typename BasicJsonType::object_t;
+ using array_t = typename BasicJsonType::array_t;
+ // make sure BasicJsonType is basic_json or const basic_json
+ static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
+ "iter_impl only accepts (const) basic_json");
+
+ public:
+
+ /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
+ /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
+ /// A user-defined iterator should provide publicly accessible typedefs named
+ /// iterator_category, value_type, difference_type, pointer, and reference.
+ /// Note that value_type is required to be non-const, even for constant iterators.
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ /// the type of the values when the iterator is dereferenced
+ using value_type = typename BasicJsonType::value_type;
+ /// a type to represent differences between iterators
+ using difference_type = typename BasicJsonType::difference_type;
+ /// defines a pointer to the type iterated over (value_type)
+ using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
+ typename BasicJsonType::const_pointer,
+ typename BasicJsonType::pointer>::type;
+ /// defines a reference to the type iterated over (value_type)
+ using reference =
+ typename std::conditional<std::is_const<BasicJsonType>::value,
+ typename BasicJsonType::const_reference,
+ typename BasicJsonType::reference>::type;
+
+ /// default constructor
+ iter_impl() = default;
+
+ /*!
+ @brief constructor for a given JSON instance
+ @param[in] object pointer to a JSON object for this iterator
+ @pre object != nullptr
+ @post The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ explicit iter_impl(pointer object) noexcept : m_object(object)
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ m_it.object_iterator = typename object_t::iterator();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_it.array_iterator = typename array_t::iterator();
+ break;
+ }
+
+ default:
+ {
+ m_it.primitive_iterator = primitive_iterator_t();
+ break;
+ }
+ }
+ }
+
+ /*!
+ @note The conventional copy constructor and copy assignment are implicitly
+ defined. Combined with the following converting constructor and
+ assignment, they support: (1) copy from iterator to iterator, (2)
+ copy from const iterator to const iterator, and (3) conversion from
+ iterator to const iterator. However conversion from const iterator
+ to iterator is not defined.
+ */
+
+ /*!
+ @brief converting constructor
+ @param[in] other non-const iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
+ iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+ : m_object(other.m_object), m_it(other.m_it) {}
+
+ /*!
+ @brief converting assignment
+ @param[in,out] other non-const iterator to copy from
+ @return const/non-const iterator
+ @note It is not checked whether @a other is initialized.
+ */
+ iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+ {
+ m_object = other.m_object;
+ m_it = other.m_it;
+ return *this;
+ }
+
+ private:
+ /*!
+ @brief set the iterator to the first value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ void set_begin() noexcept
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ m_it.object_iterator = m_object->m_value.object->begin();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_it.array_iterator = m_object->m_value.array->begin();
+ break;
+ }
+
+ case value_t::null:
+ {
+ // set to end so begin()==end() is true: null is empty
+ m_it.primitive_iterator.set_end();
+ break;
+ }
+
+ default:
+ {
+ m_it.primitive_iterator.set_begin();
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief set the iterator past the last value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ void set_end() noexcept
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ m_it.object_iterator = m_object->m_value.object->end();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_it.array_iterator = m_object->m_value.array->end();
+ break;
+ }
+
+ default:
+ {
+ m_it.primitive_iterator.set_end();
+ break;
+ }
+ }
+ }
+
+ public:
+ /*!
+ @brief return a reference to the value pointed to by the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ reference operator*() const
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ assert(m_it.object_iterator != m_object->m_value.object->end());
+ return m_it.object_iterator->second;
+ }
+
+ case value_t::array:
+ {
+ assert(m_it.array_iterator != m_object->m_value.array->end());
+ return *m_it.array_iterator;
+ }
+
+ case value_t::null:
+ JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+
+ default:
+ {
+ if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
+ {
+ return *m_object;
+ }
+
+ JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+ }
+ }
+ }
+
+ /*!
+ @brief dereference the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ pointer operator->() const
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ assert(m_it.object_iterator != m_object->m_value.object->end());
+ return &(m_it.object_iterator->second);
+ }
+
+ case value_t::array:
+ {
+ assert(m_it.array_iterator != m_object->m_value.array->end());
+ return &*m_it.array_iterator;
+ }
+
+ default:
+ {
+ if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
+ {
+ return m_object;
+ }
+
+ JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+ }
+ }
+ }
+
+ /*!
+ @brief post-increment (it++)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl const operator++(int)
+ {
+ auto result = *this;
+ ++(*this);
+ return result;
+ }
+
+ /*!
+ @brief pre-increment (++it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator++()
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ std::advance(m_it.object_iterator, 1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ std::advance(m_it.array_iterator, 1);
+ break;
+ }
+
+ default:
+ {
+ ++m_it.primitive_iterator;
+ break;
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ @brief post-decrement (it--)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl const operator--(int)
+ {
+ auto result = *this;
+ --(*this);
+ return result;
+ }
+
+ /*!
+ @brief pre-decrement (--it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator--()
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ std::advance(m_it.object_iterator, -1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ std::advance(m_it.array_iterator, -1);
+ break;
+ }
+
+ default:
+ {
+ --m_it.primitive_iterator;
+ break;
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ @brief comparison: equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator==(const iter_impl& other) const
+ {
+ // if objects are not the same, the comparison is undefined
+ if (JSON_UNLIKELY(m_object != other.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
+ }
+
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ return (m_it.object_iterator == other.m_it.object_iterator);
+
+ case value_t::array:
+ return (m_it.array_iterator == other.m_it.array_iterator);
+
+ default:
+ return (m_it.primitive_iterator == other.m_it.primitive_iterator);
+ }
+ }
+
+ /*!
+ @brief comparison: not equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator!=(const iter_impl& other) const
+ {
+ return not operator==(other);
+ }
+
+ /*!
+ @brief comparison: smaller
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator<(const iter_impl& other) const
+ {
+ // if objects are not the same, the comparison is undefined
+ if (JSON_UNLIKELY(m_object != other.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
+ }
+
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
+
+ case value_t::array:
+ return (m_it.array_iterator < other.m_it.array_iterator);
+
+ default:
+ return (m_it.primitive_iterator < other.m_it.primitive_iterator);
+ }
+ }
+
+ /*!
+ @brief comparison: less than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator<=(const iter_impl& other) const
+ {
+ return not other.operator < (*this);
+ }
+
+ /*!
+ @brief comparison: greater than
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator>(const iter_impl& other) const
+ {
+ return not operator<=(other);
+ }
+
+ /*!
+ @brief comparison: greater than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator>=(const iter_impl& other) const
+ {
+ return not operator<(other);
+ }
+
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator+=(difference_type i)
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
+
+ case value_t::array:
+ {
+ std::advance(m_it.array_iterator, i);
+ break;
+ }
+
+ default:
+ {
+ m_it.primitive_iterator += i;
+ break;
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator-=(difference_type i)
+ {
+ return operator+=(-i);
+ }
+
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl operator+(difference_type i) const
+ {
+ auto result = *this;
+ result += i;
+ return result;
+ }
+
+ /*!
+ @brief addition of distance and iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ friend iter_impl operator+(difference_type i, const iter_impl& it)
+ {
+ auto result = it;
+ result += i;
+ return result;
+ }
+
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl operator-(difference_type i) const
+ {
+ auto result = *this;
+ result -= i;
+ return result;
+ }
+
+ /*!
+ @brief return difference
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ difference_type operator-(const iter_impl& other) const
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
+
+ case value_t::array:
+ return m_it.array_iterator - other.m_it.array_iterator;
+
+ default:
+ return m_it.primitive_iterator - other.m_it.primitive_iterator;
+ }
+ }
+
+ /*!
+ @brief access to successor
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ reference operator[](difference_type n) const
+ {
+ assert(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
+
+ case value_t::array:
+ return *std::next(m_it.array_iterator, n);
+
+ case value_t::null:
+ JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+
+ default:
+ {
+ if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
+ {
+ return *m_object;
+ }
+
+ JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+ }
+ }
+ }
+
+ /*!
+ @brief return the key of an object iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ typename object_t::key_type key() const
+ {
+ assert(m_object != nullptr);
+
+ if (JSON_LIKELY(m_object->is_object()))
+ {
+ return m_it.object_iterator->first;
+ }
+
+ JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
+ }
+
+ /*!
+ @brief return the value of an iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ reference value() const
+ {
+ return operator*();
+ }
+
+ private:
+ /// associated JSON instance
+ pointer m_object = nullptr;
+ /// the actual iterator of the associated instance
+ internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it = {};
+};
+
+/// proxy class for the iterator_wrapper functions
+template<typename IteratorType> class iteration_proxy
+{
+ private:
+ /// helper class for iteration
+ class iteration_proxy_internal
+ {
+ private:
+ /// the iterator
+ IteratorType anchor;
+ /// an index for arrays (used to create key names)
+ std::size_t array_index = 0;
+
+ public:
+ explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
+
+ /// dereference operator (needed for range-based for)
+ iteration_proxy_internal& operator*()
+ {
+ return *this;
+ }
+
+ /// increment operator (needed for range-based for)
+ iteration_proxy_internal& operator++()
+ {
+ ++anchor;
+ ++array_index;
+
+ return *this;
+ }
+
+ /// inequality operator (needed for range-based for)
+ bool operator!=(const iteration_proxy_internal& o) const noexcept
+ {
+ return anchor != o.anchor;
+ }
+
+ /// return key of the iterator
+ std::string key() const
+ {
+ assert(anchor.m_object != nullptr);
+
+ switch (anchor.m_object->type())
+ {
+ // use integer array index as key
+ case value_t::array:
+ return std::to_string(array_index);
+
+ // use key from the object
+ case value_t::object:
+ return anchor.key();
+
+ // use an empty key for all primitive types
+ default:
+ return "";
+ }
+ }
+
+ /// return value of the iterator
+ typename IteratorType::reference value() const
+ {
+ return anchor.value();
+ }
+ };
+
+ /// the container to iterate
+ typename IteratorType::reference container;
+
+ public:
+ /// construct iteration proxy from a container
+ explicit iteration_proxy(typename IteratorType::reference cont)
+ : container(cont) {}
+
+ /// return iterator begin (needed for range-based for)
+ iteration_proxy_internal begin() noexcept
+ {
+ return iteration_proxy_internal(container.begin());
+ }
+
+ /// return iterator end (needed for range-based for)
+ iteration_proxy_internal end() noexcept
+ {
+ return iteration_proxy_internal(container.end());
+ }
+};
+
+/*!
+@brief a template for a reverse iterator class
+
+@tparam Base the base iterator type to reverse. Valid types are @ref
+iterator (to create @ref reverse_iterator) and @ref const_iterator (to
+create @ref const_reverse_iterator).
+
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
+ The iterator that can be moved can be moved in both directions (i.e.
+ incremented and decremented).
+- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
+ It is possible to write to the pointed-to element (only if @a Base is
+ @ref iterator).
+
+@since version 1.0.0
+*/
+template<typename Base>
+class json_reverse_iterator : public std::reverse_iterator<Base>
+{
+ public:
+ using difference_type = std::ptrdiff_t;
+ /// shortcut to the reverse iterator adapter
+ using base_iterator = std::reverse_iterator<Base>;
+ /// the reference type for the pointed-to element
+ using reference = typename Base::reference;
+
+ /// create reverse iterator from iterator
+ json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+ : base_iterator(it) {}
+
+ /// create reverse iterator from base class
+ json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+
+ /// post-increment (it++)
+ json_reverse_iterator const operator++(int)
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
+ }
+
+ /// pre-increment (++it)
+ json_reverse_iterator& operator++()
+ {
+ return static_cast<json_reverse_iterator&>(base_iterator::operator++());
+ }
+
+ /// post-decrement (it--)
+ json_reverse_iterator const operator--(int)
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
+ }
+
+ /// pre-decrement (--it)
+ json_reverse_iterator& operator--()
+ {
+ return static_cast<json_reverse_iterator&>(base_iterator::operator--());
+ }
+
+ /// add to iterator
+ json_reverse_iterator& operator+=(difference_type i)
+ {
+ return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
+ }
+
+ /// add to iterator
+ json_reverse_iterator operator+(difference_type i) const
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
+ }
+
+ /// subtract from iterator
+ json_reverse_iterator operator-(difference_type i) const
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
+ }
+
+ /// return difference
+ difference_type operator-(const json_reverse_iterator& other) const
+ {
+ return base_iterator(*this) - base_iterator(other);
+ }
+
+ /// access to successor
+ reference operator[](difference_type n) const
+ {
+ return *(this->operator+(n));
+ }
+
+ /// return the key of an object iterator
+ auto key() const -> decltype(std::declval<Base>().key())
+ {
+ auto it = --this->base();
+ return it.key();
+ }
+
+ /// return the value of an iterator
+ reference value() const
+ {
+ auto it = --this->base();
+ return it.operator * ();
+ }
+};
+
+/////////////////////
+// output adapters //
+/////////////////////
+
+/// abstract output adapter interface
+template<typename CharType> struct output_adapter_protocol
+{
+ virtual void write_character(CharType c) = 0;
+ virtual void write_characters(const CharType* s, std::size_t length) = 0;
+ virtual ~output_adapter_protocol() = default;
+};
+
+/// a type to simplify interfaces
+template<typename CharType>
+using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
+
+/// output adapter for byte vectors
+template<typename CharType>
+class output_vector_adapter : public output_adapter_protocol<CharType>
+{
+ public:
+ explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}
+
+ void write_character(CharType c) override
+ {
+ v.push_back(c);
+ }
+
+ void write_characters(const CharType* s, std::size_t length) override
+ {
+ std::copy(s, s + length, std::back_inserter(v));
+ }
+
+ private:
+ std::vector<CharType>& v;
+};
+
+/// output adapter for output streams
+template<typename CharType>
+class output_stream_adapter : public output_adapter_protocol<CharType>
+{
+ public:
+ explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}
+
+ void write_character(CharType c) override
+ {
+ stream.put(c);
+ }
+
+ void write_characters(const CharType* s, std::size_t length) override
+ {
+ stream.write(s, static_cast<std::streamsize>(length));
+ }
+
+ private:
+ std::basic_ostream<CharType>& stream;
+};
+
+/// output adapter for basic_string
+template<typename CharType>
+class output_string_adapter : public output_adapter_protocol<CharType>
+{
+ public:
+ explicit output_string_adapter(std::basic_string<CharType>& s) : str(s) {}
+
+ void write_character(CharType c) override
+ {
+ str.push_back(c);
+ }
+
+ void write_characters(const CharType* s, std::size_t length) override
+ {
+ str.append(s, length);
+ }
+
+ private:
+ std::basic_string<CharType>& str;
+};
+
+template<typename CharType>
+class output_adapter
+{
+ public:
+ output_adapter(std::vector<CharType>& vec)
+ : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
+
+ output_adapter(std::basic_ostream<CharType>& s)
+ : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
+
+ output_adapter(std::basic_string<CharType>& s)
+ : oa(std::make_shared<output_string_adapter<CharType>>(s)) {}
+
+ operator output_adapter_t<CharType>()
+ {
+ return oa;
+ }
+
+ private:
+ output_adapter_t<CharType> oa = nullptr;
+};
+
+//////////////////////////////
+// binary reader and writer //
+//////////////////////////////
+
+/*!
+@brief deserialization of CBOR and MessagePack values
+*/
+template<typename BasicJsonType>
+class binary_reader
+{
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+
+ public:
+ /*!
+ @brief create a binary reader
+
+ @param[in] adapter input adapter to read from
+ */
+ explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
+ {
+ assert(ia);
+ }
+
+ /*!
+ @brief create a JSON value from CBOR input
+
+ @param[in] strict whether to expect the input to be consumed completed
+ @return JSON value created from CBOR input
+
+ @throw parse_error.110 if input ended unexpectedly or the end of file was
+ not reached when @a strict was set to true
+ @throw parse_error.112 if unsupported byte was read
+ */
+ BasicJsonType parse_cbor(const bool strict)
+ {
+ const auto res = parse_cbor_internal();
+ if (strict)
+ {
+ get();
+ check_eof(true);
+ }
+ return res;
+ }
+
+ /*!
+ @brief create a JSON value from MessagePack input
+
+ @param[in] strict whether to expect the input to be consumed completed
+ @return JSON value created from MessagePack input
+
+ @throw parse_error.110 if input ended unexpectedly or the end of file was
+ not reached when @a strict was set to true
+ @throw parse_error.112 if unsupported byte was read
+ */
+ BasicJsonType parse_msgpack(const bool strict)
+ {
+ const auto res = parse_msgpack_internal();
+ if (strict)
+ {
+ get();
+ check_eof(true);
+ }
+ return res;
+ }
+
+ /*!
+ @brief determine system byte order
+
+ @return true if and only if system's byte order is little endian
+
+ @note from http://stackoverflow.com/a/1001328/266378
+ */
+ static constexpr bool little_endianess(int num = 1) noexcept
+ {
+ return (*reinterpret_cast<char*>(&num) == 1);
+ }
+
+ private:
+ /*!
+ @param[in] get_char whether a new character should be retrieved from the
+ input (true, default) or whether the last read
+ character should be considered instead
+ */
+ BasicJsonType parse_cbor_internal(const bool get_char = true)
+ {
+ switch (get_char ? get() : current)
+ {
+ // EOF
+ case std::char_traits<char>::eof():
+ JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+
+ // Integer 0x00..0x17 (0..23)
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ return static_cast<number_unsigned_t>(current);
+
+ case 0x18: // Unsigned integer (one-byte uint8_t follows)
+ return get_number<uint8_t>();
+
+ case 0x19: // Unsigned integer (two-byte uint16_t follows)
+ return get_number<uint16_t>();
+
+ case 0x1A: // Unsigned integer (four-byte uint32_t follows)
+ return get_number<uint32_t>();
+
+ case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
+ return get_number<uint64_t>();
+
+ // Negative integer -1-0x00..-1-0x17 (-1..-24)
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ return static_cast<int8_t>(0x20 - 1 - current);
+
+ case 0x38: // Negative integer (one-byte uint8_t follows)
+ {
+ // must be uint8_t !
+ return static_cast<number_integer_t>(-1) - get_number<uint8_t>();
+ }
+
+ case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+ {
+ return static_cast<number_integer_t>(-1) - get_number<uint16_t>();
+ }
+
+ case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
+ {
+ return static_cast<number_integer_t>(-1) - get_number<uint32_t>();
+ }
+
+ case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
+ {
+ return static_cast<number_integer_t>(-1) -
+ static_cast<number_integer_t>(get_number<uint64_t>());
+ }
+
+ // UTF-8 string (0x00..0x17 bytes follow)
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+ case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+ case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+ case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+ case 0x7F: // UTF-8 string (indefinite length)
+ {
+ return get_cbor_string();
+ }
+
+ // array (0x00..0x17 data items follow)
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ case 0x8D:
+ case 0x8E:
+ case 0x8F:
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ {
+ return get_cbor_array(current & 0x1F);
+ }
+
+ case 0x98: // array (one-byte uint8_t for n follows)
+ {
+ return get_cbor_array(get_number<uint8_t>());
+ }
+
+ case 0x99: // array (two-byte uint16_t for n follow)
+ {
+ return get_cbor_array(get_number<uint16_t>());
+ }
+
+ case 0x9A: // array (four-byte uint32_t for n follow)
+ {
+ return get_cbor_array(get_number<uint32_t>());
+ }
+
+ case 0x9B: // array (eight-byte uint64_t for n follow)
+ {
+ return get_cbor_array(get_number<uint64_t>());
+ }
+
+ case 0x9F: // array (indefinite length)
+ {
+ BasicJsonType result = value_t::array;
+ while (get() != 0xFF)
+ {
+ result.push_back(parse_cbor_internal(false));
+ }
+ return result;
+ }
+
+ // map (0x00..0x17 pairs of data items follow)
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF:
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ {
+ return get_cbor_object(current & 0x1F);
+ }
+
+ case 0xB8: // map (one-byte uint8_t for n follows)
+ {
+ return get_cbor_object(get_number<uint8_t>());
+ }
+
+ case 0xB9: // map (two-byte uint16_t for n follow)
+ {
+ return get_cbor_object(get_number<uint16_t>());
+ }
+
+ case 0xBA: // map (four-byte uint32_t for n follow)
+ {
+ return get_cbor_object(get_number<uint32_t>());
+ }
+
+ case 0xBB: // map (eight-byte uint64_t for n follow)
+ {
+ return get_cbor_object(get_number<uint64_t>());
+ }
+
+ case 0xBF: // map (indefinite length)
+ {
+ BasicJsonType result = value_t::object;
+ while (get() != 0xFF)
+ {
+ auto key = get_cbor_string();
+ result[key] = parse_cbor_internal();
+ }
+ return result;
+ }
+
+ case 0xF4: // false
+ {
+ return false;
+ }
+
+ case 0xF5: // true
+ {
+ return true;
+ }
+
+ case 0xF6: // null
+ {
+ return value_t::null;
+ }
+
+ case 0xF9: // Half-Precision Float (two-byte IEEE 754)
+ {
+ const int byte1 = get();
+ check_eof();
+ const int byte2 = get();
+ check_eof();
+
+ // code from RFC 7049, Appendix D, Figure 3:
+ // As half-precision floating-point numbers were only added
+ // to IEEE 754 in 2008, today's programming platforms often
+ // still only have limited support for them. It is very
+ // easy to include at least decoding support for them even
+ // without such support. An example of a small decoder for
+ // half-precision floating-point numbers in the C language
+ // is shown in Fig. 3.
+ const int half = (byte1 << 8) + byte2;
+ const int exp = (half >> 10) & 0x1F;
+ const int mant = half & 0x3FF;
+ double val;
+ if (exp == 0)
+ {
+ val = std::ldexp(mant, -24);
+ }
+ else if (exp != 31)
+ {
+ val = std::ldexp(mant + 1024, exp - 25);
+ }
+ else
+ {
+ val = (mant == 0) ? std::numeric_limits<double>::infinity()
+ : std::numeric_limits<double>::quiet_NaN();
+ }
+ return (half & 0x8000) != 0 ? -val : val;
+ }
+
+ case 0xFA: // Single-Precision Float (four-byte IEEE 754)
+ {
+ return get_number<float>();
+ }
+
+ case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
+ {
+ return get_number<double>();
+ }
+
+ default: // anything else (0xFF is handled inside the other types)
+ {
+ std::stringstream ss;
+ ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
+ JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
+ }
+ }
+ }
+
+ BasicJsonType parse_msgpack_internal()
+ {
+ switch (get())
+ {
+ // EOF
+ case std::char_traits<char>::eof():
+ JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+
+ // positive fixint
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1A:
+ case 0x1B:
+ case 0x1C:
+ case 0x1D:
+ case 0x1E:
+ case 0x1F:
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0x3B:
+ case 0x3C:
+ case 0x3D:
+ case 0x3E:
+ case 0x3F:
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B:
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78:
+ case 0x79:
+ case 0x7A:
+ case 0x7B:
+ case 0x7C:
+ case 0x7D:
+ case 0x7E:
+ case 0x7F:
+ return static_cast<number_unsigned_t>(current);
+
+ // fixmap
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ case 0x8D:
+ case 0x8E:
+ case 0x8F:
+ {
+ return get_msgpack_object(current & 0x0F);
+ }
+
+ // fixarray
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ case 0x98:
+ case 0x99:
+ case 0x9A:
+ case 0x9B:
+ case 0x9C:
+ case 0x9D:
+ case 0x9E:
+ case 0x9F:
+ {
+ return get_msgpack_array(current & 0x0F);
+ }
+
+ // fixstr
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF:
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF:
+ return get_msgpack_string();
+
+ case 0xC0: // nil
+ return value_t::null;
+
+ case 0xC2: // false
+ return false;
+
+ case 0xC3: // true
+ return true;
+
+ case 0xCA: // float 32
+ return get_number<float>();
+
+ case 0xCB: // float 64
+ return get_number<double>();
+
+ case 0xCC: // uint 8
+ return get_number<uint8_t>();
+
+ case 0xCD: // uint 16
+ return get_number<uint16_t>();
+
+ case 0xCE: // uint 32
+ return get_number<uint32_t>();
+
+ case 0xCF: // uint 64
+ return get_number<uint64_t>();
+
+ case 0xD0: // int 8
+ return get_number<int8_t>();
+
+ case 0xD1: // int 16
+ return get_number<int16_t>();
+
+ case 0xD2: // int 32
+ return get_number<int32_t>();
+
+ case 0xD3: // int 64
+ return get_number<int64_t>();
+
+ case 0xD9: // str 8
+ case 0xDA: // str 16
+ case 0xDB: // str 32
+ return get_msgpack_string();
+
+ case 0xDC: // array 16
+ {
+ return get_msgpack_array(get_number<uint16_t>());
+ }
+
+ case 0xDD: // array 32
+ {
+ return get_msgpack_array(get_number<uint32_t>());
+ }
+
+ case 0xDE: // map 16
+ {
+ return get_msgpack_object(get_number<uint16_t>());
+ }
+
+ case 0xDF: // map 32
+ {
+ return get_msgpack_object(get_number<uint32_t>());
+ }
+
+ // positive fixint
+ case 0xE0:
+ case 0xE1:
+ case 0xE2:
+ case 0xE3:
+ case 0xE4:
+ case 0xE5:
+ case 0xE6:
+ case 0xE7:
+ case 0xE8:
+ case 0xE9:
+ case 0xEA:
+ case 0xEB:
+ case 0xEC:
+ case 0xED:
+ case 0xEE:
+ case 0xEF:
+ case 0xF0:
+ case 0xF1:
+ case 0xF2:
+ case 0xF3:
+ case 0xF4:
+ case 0xF5:
+ case 0xF6:
+ case 0xF7:
+ case 0xF8:
+ case 0xF9:
+ case 0xFA:
+ case 0xFB:
+ case 0xFC:
+ case 0xFD:
+ case 0xFE:
+ case 0xFF:
+ return static_cast<int8_t>(current);
+
+ default: // anything else
+ {
+ std::stringstream ss;
+ ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
+ JSON_THROW(parse_error::create(112, chars_read,
+ "error reading MessagePack; last byte: 0x" + ss.str()));
+ }
+ }
+ }
+
+ /*!
+ @brief get next character from the input
+
+ This function provides the interface to the used input adapter. It does
+ not throw in case the input reached EOF, but returns a -'ve valued
+ `std::char_traits<char>::eof()` in that case.
+
+ @return character read from the input
+ */
+ int get()
+ {
+ ++chars_read;
+ return (current = ia->get_character());
+ }
+
+ /*
+ @brief read a number from the input
+
+ @tparam NumberType the type of the number
+
+ @return number of type @a NumberType
+
+ @note This function needs to respect the system's endianess, because
+ bytes in CBOR and MessagePack are stored in network order (big
+ endian) and therefore need reordering on little endian systems.
+
+ @throw parse_error.110 if input has less than `sizeof(NumberType)` bytes
+ */
+ template<typename NumberType> NumberType get_number()
+ {
+ // step 1: read input into array with system's byte order
+ std::array<uint8_t, sizeof(NumberType)> vec;
+ for (std::size_t i = 0; i < sizeof(NumberType); ++i)
+ {
+ get();
+ check_eof();
+
+ // reverse byte order prior to conversion if necessary
+ if (is_little_endian)
+ {
+ vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
+ }
+ else
+ {
+ vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
+ }
+ }
+
+ // step 2: convert array into number of type T and return
+ NumberType result;
+ std::memcpy(&result, vec.data(), sizeof(NumberType));
+ return result;
+ }
+
+ /*!
+ @brief create a string by reading characters from the input
+
+ @param[in] len number of bytes to read
+
+ @note We can not reserve @a len bytes for the result, because @a len
+ may be too large. Usually, @ref check_eof() detects the end of
+ the input before we run out of string memory.
+
+ @return string created by reading @a len bytes
+
+ @throw parse_error.110 if input has less than @a len bytes
+ */
+ template<typename NumberType>
+ std::string get_string(const NumberType len)
+ {
+ std::string result;
+ std::generate_n(std::back_inserter(result), len, [this]()
+ {
+ get();
+ check_eof();
+ return static_cast<char>(current);
+ });
+ return result;
+ }
+
+ /*!
+ @brief reads a CBOR string
+
+ This function first reads starting bytes to determine the expected
+ string length and then copies this number of bytes into a string.
+ Additionally, CBOR's strings with indefinite lengths are supported.
+
+ @return string
+
+ @throw parse_error.110 if input ended
+ @throw parse_error.113 if an unexpected byte is read
+ */
+ std::string get_cbor_string()
+ {
+ check_eof();
+
+ switch (current)
+ {
+ // UTF-8 string (0x00..0x17 bytes follow)
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ {
+ return get_string(current & 0x1F);
+ }
+
+ case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+ {
+ return get_string(get_number<uint8_t>());
+ }
+
+ case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+ {
+ return get_string(get_number<uint16_t>());
+ }
+
+ case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+ {
+ return get_string(get_number<uint32_t>());
+ }
+
+ case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+ {
+ return get_string(get_number<uint64_t>());
+ }
+
+ case 0x7F: // UTF-8 string (indefinite length)
+ {
+ std::string result;
+ while (get() != 0xFF)
+ {
+ check_eof();
+ result.push_back(static_cast<char>(current));
+ }
+ return result;
+ }
+
+ default:
+ {
+ std::stringstream ss;
+ ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
+ JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
+ }
+ }
+ }
+
+ template<typename NumberType>
+ BasicJsonType get_cbor_array(const NumberType len)
+ {
+ BasicJsonType result = value_t::array;
+ std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
+ {
+ return parse_cbor_internal();
+ });
+ return result;
+ }
+
+ template<typename NumberType>
+ BasicJsonType get_cbor_object(const NumberType len)
+ {
+ BasicJsonType result = value_t::object;
+ std::generate_n(std::inserter(*result.m_value.object,
+ result.m_value.object->end()),
+ len, [this]()
+ {
+ get();
+ auto key = get_cbor_string();
+ auto val = parse_cbor_internal();
+ return std::make_pair(std::move(key), std::move(val));
+ });
+ return result;
+ }
+
+ /*!
+ @brief reads a MessagePack string
+
+ This function first reads starting bytes to determine the expected
+ string length and then copies this number of bytes into a string.
+
+ @return string
+
+ @throw parse_error.110 if input ended
+ @throw parse_error.113 if an unexpected byte is read
+ */
+ std::string get_msgpack_string()
+ {
+ check_eof();
+
+ switch (current)
+ {
+ // fixstr
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF:
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF:
+ {
+ return get_string(current & 0x1F);
+ }
+
+ case 0xD9: // str 8
+ {
+ return get_string(get_number<uint8_t>());
+ }
+
+ case 0xDA: // str 16
+ {
+ return get_string(get_number<uint16_t>());
+ }
+
+ case 0xDB: // str 32
+ {
+ return get_string(get_number<uint32_t>());
+ }
+
+ default:
+ {
+ std::stringstream ss;
+ ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
+ JSON_THROW(parse_error::create(113, chars_read,
+ "expected a MessagePack string; last byte: 0x" + ss.str()));
+ }
+ }
+ }
+
+ template<typename NumberType>
+ BasicJsonType get_msgpack_array(const NumberType len)
+ {
+ BasicJsonType result = value_t::array;
+ std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
+ {
+ return parse_msgpack_internal();
+ });
+ return result;
+ }
+
+ template<typename NumberType>
+ BasicJsonType get_msgpack_object(const NumberType len)
+ {
+ BasicJsonType result = value_t::object;
+ std::generate_n(std::inserter(*result.m_value.object,
+ result.m_value.object->end()),
+ len, [this]()
+ {
+ get();
+ auto key = get_msgpack_string();
+ auto val = parse_msgpack_internal();
+ return std::make_pair(std::move(key), std::move(val));
+ });
+ return result;
+ }
+
+ /*!
+ @brief check if input ended
+ @throw parse_error.110 if input ended
+ */
+ void check_eof(const bool expect_eof = false) const
+ {
+ if (expect_eof)
+ {
+ if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
+ {
+ JSON_THROW(parse_error::create(110, chars_read, "expected end of input"));
+ }
+ }
+ else
+ {
+ if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
+ {
+ JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ }
+ }
+ }
+
+ private:
+ /// input adapter
+ input_adapter_t ia = nullptr;
+
+ /// the current character
+ int current = std::char_traits<char>::eof();
+
+ /// the number of characters read
+ std::size_t chars_read = 0;
+
+ /// whether we can assume little endianess
+ const bool is_little_endian = little_endianess();
+};
+
+/*!
+@brief serialization to CBOR and MessagePack values
+*/
+template<typename BasicJsonType, typename CharType>
+class binary_writer
+{
+ public:
+ /*!
+ @brief create a binary writer
+
+ @param[in] adapter output adapter to write to
+ */
+ explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
+ {
+ assert(oa);
+ }
+
+ /*!
+ @brief[in] j JSON value to serialize
+ */
+ void write_cbor(const BasicJsonType& j)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ oa->write_character(static_cast<CharType>(0xF6));
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ oa->write_character(j.m_value.boolean
+ ? static_cast<CharType>(0xF5)
+ : static_cast<CharType>(0xF4));
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // CBOR does not differentiate between positive signed
+ // integers and unsigned integers. Therefore, we used the
+ // code from the value_t::number_unsigned case here.
+ if (j.m_value.number_integer <= 0x17)
+ {
+ write_number(static_cast<uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x18));
+ write_number(static_cast<uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x19));
+ write_number(static_cast<uint16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x1A));
+ write_number(static_cast<uint32_t>(j.m_value.number_integer));
+ }
+ else
+ {
+ oa->write_character(static_cast<CharType>(0x1B));
+ write_number(static_cast<uint64_t>(j.m_value.number_integer));
+ }
+ }
+ else
+ {
+ // The conversions below encode the sign in the first
+ // byte, and the value is converted to a positive number.
+ const auto positive_number = -1 - j.m_value.number_integer;
+ if (j.m_value.number_integer >= -24)
+ {
+ write_number(static_cast<uint8_t>(0x20 + positive_number));
+ }
+ else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x38));
+ write_number(static_cast<uint8_t>(positive_number));
+ }
+ else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x39));
+ write_number(static_cast<uint16_t>(positive_number));
+ }
+ else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x3A));
+ write_number(static_cast<uint32_t>(positive_number));
+ }
+ else
+ {
+ oa->write_character(static_cast<CharType>(0x3B));
+ write_number(static_cast<uint64_t>(positive_number));
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned <= 0x17)
+ {
+ write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x18));
+ write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x19));
+ write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
+ {
+ oa->write_character(static_cast<CharType>(0x1A));
+ write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
+ }
+ else
+ {
+ oa->write_character(static_cast<CharType>(0x1B));
+ write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
+ }
+ break;
+ }
+
+ case value_t::number_float: // Double-Precision Float
+ {
+ oa->write_character(static_cast<CharType>(0xFB));
+ write_number(j.m_value.number_float);
+ break;
+ }
+
+ case value_t::string:
+ {
+ // step 1: write control byte and the string length
+ const auto N = j.m_value.string->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<uint8_t>(0x60 + N));
+ }
+ else if (N <= 0xFF)
+ {
+ oa->write_character(static_cast<CharType>(0x78));
+ write_number(static_cast<uint8_t>(N));
+ }
+ else if (N <= 0xFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0x79));
+ write_number(static_cast<uint16_t>(N));
+ }
+ else if (N <= 0xFFFFFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0x7A));
+ write_number(static_cast<uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xFFFFFFFFFFFFFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0x7B));
+ write_number(static_cast<uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write the string
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+ j.m_value.string->size());
+ break;
+ }
+
+ case value_t::array:
+ {
+ // step 1: write control byte and the array size
+ const auto N = j.m_value.array->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<uint8_t>(0x80 + N));
+ }
+ else if (N <= 0xFF)
+ {
+ oa->write_character(static_cast<CharType>(0x98));
+ write_number(static_cast<uint8_t>(N));
+ }
+ else if (N <= 0xFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0x99));
+ write_number(static_cast<uint16_t>(N));
+ }
+ else if (N <= 0xFFFFFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0x9A));
+ write_number(static_cast<uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xFFFFFFFFFFFFFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0x9B));
+ write_number(static_cast<uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.array)
+ {
+ write_cbor(el);
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ // step 1: write control byte and the object size
+ const auto N = j.m_value.object->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<uint8_t>(0xA0 + N));
+ }
+ else if (N <= 0xFF)
+ {
+ oa->write_character(static_cast<CharType>(0xB8));
+ write_number(static_cast<uint8_t>(N));
+ }
+ else if (N <= 0xFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0xB9));
+ write_number(static_cast<uint16_t>(N));
+ }
+ else if (N <= 0xFFFFFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0xBA));
+ write_number(static_cast<uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xFFFFFFFFFFFFFFFF)
+ {
+ oa->write_character(static_cast<CharType>(0xBB));
+ write_number(static_cast<uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.object)
+ {
+ write_cbor(el.first);
+ write_cbor(el.second);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ /*!
+ @brief[in] j JSON value to serialize
+ */
+ void write_msgpack(const BasicJsonType& j)
+ {
+ switch (j.type())
+ {
+ case value_t::null: // nil
+ {
+ oa->write_character(static_cast<CharType>(0xC0));
+ break;
+ }
+
+ case value_t::boolean: // true and false
+ {
+ oa->write_character(j.m_value.boolean
+ ? static_cast<CharType>(0xC3)
+ : static_cast<CharType>(0xC2));
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // MessagePack does not differentiate between positive
+ // signed integers and unsigned integers. Therefore, we used
+ // the code from the value_t::number_unsigned case here.
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ write_number(static_cast<uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
+ {
+ // uint 8
+ oa->write_character(static_cast<CharType>(0xCC));
+ write_number(static_cast<uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
+ {
+ // uint 16
+ oa->write_character(static_cast<CharType>(0xCD));
+ write_number(static_cast<uint16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
+ {
+ // uint 32
+ oa->write_character(static_cast<CharType>(0xCE));
+ write_number(static_cast<uint32_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
+ {
+ // uint 64
+ oa->write_character(static_cast<CharType>(0xCF));
+ write_number(static_cast<uint64_t>(j.m_value.number_integer));
+ }
+ }
+ else
+ {
+ if (j.m_value.number_integer >= -32)
+ {
+ // negative fixnum
+ write_number(static_cast<int8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
+ j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
+ {
+ // int 8
+ oa->write_character(static_cast<CharType>(0xD0));
+ write_number(static_cast<int8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
+ j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
+ {
+ // int 16
+ oa->write_character(static_cast<CharType>(0xD1));
+ write_number(static_cast<int16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
+ j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
+ {
+ // int 32
+ oa->write_character(static_cast<CharType>(0xD2));
+ write_number(static_cast<int32_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
+ j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
+ {
+ // int 64
+ oa->write_character(static_cast<CharType>(0xD3));
+ write_number(static_cast<int64_t>(j.m_value.number_integer));
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ write_number(static_cast<uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
+ {
+ // uint 8
+ oa->write_character(static_cast<CharType>(0xCC));
+ write_number(static_cast<uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
+ {
+ // uint 16
+ oa->write_character(static_cast<CharType>(0xCD));
+ write_number(static_cast<uint16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
+ {
+ // uint 32
+ oa->write_character(static_cast<CharType>(0xCE));
+ write_number(static_cast<uint32_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
+ {
+ // uint 64
+ oa->write_character(static_cast<CharType>(0xCF));
+ write_number(static_cast<uint64_t>(j.m_value.number_integer));
+ }
+ break;
+ }
+
+ case value_t::number_float: // float 64
+ {
+ oa->write_character(static_cast<CharType>(0xCB));
+ write_number(j.m_value.number_float);
+ break;
+ }
+
+ case value_t::string:
+ {
+ // step 1: write control byte and the string length
+ const auto N = j.m_value.string->size();
+ if (N <= 31)
+ {
+ // fixstr
+ write_number(static_cast<uint8_t>(0xA0 | N));
+ }
+ else if (N <= 255)
+ {
+ // str 8
+ oa->write_character(static_cast<CharType>(0xD9));
+ write_number(static_cast<uint8_t>(N));
+ }
+ else if (N <= 65535)
+ {
+ // str 16
+ oa->write_character(static_cast<CharType>(0xDA));
+ write_number(static_cast<uint16_t>(N));
+ }
+ else if (N <= 4294967295)
+ {
+ // str 32
+ oa->write_character(static_cast<CharType>(0xDB));
+ write_number(static_cast<uint32_t>(N));
+ }
+
+ // step 2: write the string
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+ j.m_value.string->size());
+ break;
+ }
+
+ case value_t::array:
+ {
+ // step 1: write control byte and the array size
+ const auto N = j.m_value.array->size();
+ if (N <= 15)
+ {
+ // fixarray
+ write_number(static_cast<uint8_t>(0x90 | N));
+ }
+ else if (N <= 0xFFFF)
+ {
+ // array 16
+ oa->write_character(static_cast<CharType>(0xDC));
+ write_number(static_cast<uint16_t>(N));
+ }
+ else if (N <= 0xFFFFFFFF)
+ {
+ // array 32
+ oa->write_character(static_cast<CharType>(0xDD));
+ write_number(static_cast<uint32_t>(N));
+ }
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.array)
+ {
+ write_msgpack(el);
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ // step 1: write control byte and the object size
+ const auto N = j.m_value.object->size();
+ if (N <= 15)
+ {
+ // fixmap
+ write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
+ }
+ else if (N <= 65535)
+ {
+ // map 16
+ oa->write_character(static_cast<CharType>(0xDE));
+ write_number(static_cast<uint16_t>(N));
+ }
+ else if (N <= 4294967295)
+ {
+ // map 32
+ oa->write_character(static_cast<CharType>(0xDF));
+ write_number(static_cast<uint32_t>(N));
+ }
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.object)
+ {
+ write_msgpack(el.first);
+ write_msgpack(el.second);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ private:
+ /*
+ @brief write a number to output input
+
+ @param[in] n number of type @a NumberType
+ @tparam NumberType the type of the number
+
+ @note This function needs to respect the system's endianess, because bytes
+ in CBOR and MessagePack are stored in network order (big endian) and
+ therefore need reordering on little endian systems.
+ */
+ template<typename NumberType> void write_number(NumberType n)
{
- return '.';
+ // step 1: write number to array of length NumberType
+ std::array<CharType, sizeof(NumberType)> vec;
+ std::memcpy(vec.data(), &n, sizeof(NumberType));
+
+ // step 2: write array to output (with possible reordering)
+ if (is_little_endian)
+ {
+ // reverse byte order prior to conversion if necessary
+ std::reverse(vec.begin(), vec.end());
+ }
+
+ oa->write_characters(vec.data(), sizeof(NumberType));
}
+
+ private:
+ /// whether we can assume little endianess
+ const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
+
+ /// the output
+ output_adapter_t<CharType> oa = nullptr;
};
+///////////////////
+// serialization //
+///////////////////
+
+template<typename BasicJsonType>
+class serializer
+{
+ using string_t = typename BasicJsonType::string_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ public:
+ /*!
+ @param[in] s output stream to serialize to
+ @param[in] ichar indentation character to use
+ */
+ serializer(output_adapter_t<char> s, const char ichar)
+ : o(std::move(s)), loc(std::localeconv()),
+ thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep)),
+ decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point)),
+ indent_char(ichar), indent_string(512, indent_char) {}
+
+ // delete because of pointer members
+ serializer(const serializer&) = delete;
+ serializer& operator=(const serializer&) = delete;
+
+ /*!
+ @brief internal implementation of the serialization function
+
+ This function is called by the public member function dump and organizes
+ the serialization internally. The indentation level is propagated as
+ additional parameter. In case of arrays and objects, the function is
+ called recursively.
+
+ - strings and object keys are escaped using `escape_string()`
+ - integer numbers are converted implicitly via `operator<<`
+ - floating-point numbers are converted to a string using `"%g"` format
+
+ @param[in] val value to serialize
+ @param[in] pretty_print whether the output shall be pretty-printed
+ @param[in] indent_step the indent level
+ @param[in] current_indent the current indent level (only used internally)
+ */
+ void dump(const BasicJsonType& val, const bool pretty_print,
+ const bool ensure_ascii,
+ const unsigned int indent_step,
+ const unsigned int current_indent = 0)
+ {
+ switch (val.m_type)
+ {
+ case value_t::object:
+ {
+ if (val.m_value.object->empty())
+ {
+ o->write_characters("{}", 2);
+ return;
+ }
+
+ if (pretty_print)
+ {
+ o->write_characters("{\n", 2);
+
+ // variable to hold indentation for recursive calls
+ const auto new_indent = current_indent + indent_step;
+ if (JSON_UNLIKELY(indent_string.size() < new_indent))
+ {
+ indent_string.resize(indent_string.size() * 2, ' ');
+ }
+
+ // first n-1 elements
+ auto i = val.m_value.object->cbegin();
+ for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+ {
+ o->write_characters(indent_string.c_str(), new_indent);
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\": ", 3);
+ dump(i->second, true, ensure_ascii, indent_step, new_indent);
+ o->write_characters(",\n", 2);
+ }
+
+ // last element
+ assert(i != val.m_value.object->cend());
+ assert(std::next(i) == val.m_value.object->cend());
+ o->write_characters(indent_string.c_str(), new_indent);
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\": ", 3);
+ dump(i->second, true, ensure_ascii, indent_step, new_indent);
+
+ o->write_character('\n');
+ o->write_characters(indent_string.c_str(), current_indent);
+ o->write_character('}');
+ }
+ else
+ {
+ o->write_character('{');
+
+ // first n-1 elements
+ auto i = val.m_value.object->cbegin();
+ for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+ {
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\":", 2);
+ dump(i->second, false, ensure_ascii, indent_step, current_indent);
+ o->write_character(',');
+ }
+
+ // last element
+ assert(i != val.m_value.object->cend());
+ assert(std::next(i) == val.m_value.object->cend());
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\":", 2);
+ dump(i->second, false, ensure_ascii, indent_step, current_indent);
+
+ o->write_character('}');
+ }
+
+ return;
+ }
+
+ case value_t::array:
+ {
+ if (val.m_value.array->empty())
+ {
+ o->write_characters("[]", 2);
+ return;
+ }
+
+ if (pretty_print)
+ {
+ o->write_characters("[\n", 2);
+
+ // variable to hold indentation for recursive calls
+ const auto new_indent = current_indent + indent_step;
+ if (JSON_UNLIKELY(indent_string.size() < new_indent))
+ {
+ indent_string.resize(indent_string.size() * 2, ' ');
+ }
+
+ // first n-1 elements
+ for (auto i = val.m_value.array->cbegin();
+ i != val.m_value.array->cend() - 1; ++i)
+ {
+ o->write_characters(indent_string.c_str(), new_indent);
+ dump(*i, true, ensure_ascii, indent_step, new_indent);
+ o->write_characters(",\n", 2);
+ }
+
+ // last element
+ assert(not val.m_value.array->empty());
+ o->write_characters(indent_string.c_str(), new_indent);
+ dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
+
+ o->write_character('\n');
+ o->write_characters(indent_string.c_str(), current_indent);
+ o->write_character(']');
+ }
+ else
+ {
+ o->write_character('[');
+
+ // first n-1 elements
+ for (auto i = val.m_value.array->cbegin();
+ i != val.m_value.array->cend() - 1; ++i)
+ {
+ dump(*i, false, ensure_ascii, indent_step, current_indent);
+ o->write_character(',');
+ }
+
+ // last element
+ assert(not val.m_value.array->empty());
+ dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
+
+ o->write_character(']');
+ }
+
+ return;
+ }
+
+ case value_t::string:
+ {
+ o->write_character('\"');
+ dump_escaped(*val.m_value.string, ensure_ascii);
+ o->write_character('\"');
+ return;
+ }
+
+ case value_t::boolean:
+ {
+ if (val.m_value.boolean)
+ {
+ o->write_characters("true", 4);
+ }
+ else
+ {
+ o->write_characters("false", 5);
+ }
+ return;
+ }
+
+ case value_t::number_integer:
+ {
+ dump_integer(val.m_value.number_integer);
+ return;
+ }
+
+ case value_t::number_unsigned:
+ {
+ dump_integer(val.m_value.number_unsigned);
+ return;
+ }
+
+ case value_t::number_float:
+ {
+ dump_float(val.m_value.number_float);
+ return;
+ }
+
+ case value_t::discarded:
+ {
+ o->write_characters("<discarded>", 11);
+ return;
+ }
+
+ case value_t::null:
+ {
+ o->write_characters("null", 4);
+ return;
+ }
+ }
+ }
+
+ private:
+ /*!
+ @brief returns the number of expected bytes following in UTF-8 string
+
+ @param[in] u the first byte of a UTF-8 string
+ @return the number of expected bytes following
+ */
+ static constexpr std::size_t bytes_following(const uint8_t u)
+ {
+ return ((u <= 127) ? 0
+ : ((192 <= u and u <= 223) ? 1
+ : ((224 <= u and u <= 239) ? 2
+ : ((240 <= u and u <= 247) ? 3 : std::string::npos))));
+ }
+
+ /*!
+ @brief calculates the extra space to escape a JSON string
+
+ @param[in] s the string to escape
+ @param[in] ensure_ascii whether to escape non-ASCII characters with
+ \uXXXX sequences
+ @return the number of characters required to escape string @a s
+
+ @complexity Linear in the length of string @a s.
+ */
+ static std::size_t extra_space(const string_t& s,
+ const bool ensure_ascii) noexcept
+ {
+ std::size_t res = 0;
+
+ for (std::size_t i = 0; i < s.size(); ++i)
+ {
+ switch (s[i])
+ {
+ // control characters that can be escaped with a backslash
+ case '"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ {
+ // from c (1 byte) to \x (2 bytes)
+ res += 1;
+ break;
+ }
+
+ // control characters that need \uxxxx escaping
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x0B:
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1A:
+ case 0x1B:
+ case 0x1C:
+ case 0x1D:
+ case 0x1E:
+ case 0x1F:
+ {
+ // from c (1 byte) to \uxxxx (6 bytes)
+ res += 5;
+ break;
+ }
+
+ default:
+ {
+ if (ensure_ascii and (s[i] & 0x80 or s[i] == 0x7F))
+ {
+ const auto bytes = bytes_following(static_cast<uint8_t>(s[i]));
+ // invalid characters will be detected by throw_if_invalid_utf8
+ assert (bytes != std::string::npos);
+
+ if (bytes == 3)
+ {
+ // codepoints that need 4 bytes (i.e., 3 additional
+ // bytes) in UTF-8 need a surrogate pair when \u
+ // escaping is used: from 4 bytes to \uxxxx\uxxxx
+ // (12 bytes)
+ res += (12 - bytes - 1);
+ }
+ else
+ {
+ // from x bytes to \uxxxx (6 bytes)
+ res += (6 - bytes - 1);
+ }
+
+ // skip the additional bytes
+ i += bytes;
+ }
+ break;
+ }
+ }
+ }
+
+ return res;
+ }
+
+ static void escape_codepoint(int codepoint, string_t& result, std::size_t& pos)
+ {
+ // expecting a proper codepoint
+ assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
+
+ // the last written character was the backslash before the 'u'
+ assert(result[pos] == '\\');
+
+ // write the 'u'
+ result[++pos] = 'u';
+
+ // convert a number 0..15 to its hex representation (0..f)
+ static const std::array<char, 16> hexify =
+ {
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ }
+ };
+
+ if (codepoint < 0x10000)
+ {
+ // codepoints U+0000..U+FFFF can be represented as \uxxxx.
+ result[++pos] = hexify[(codepoint >> 12) & 0x0F];
+ result[++pos] = hexify[(codepoint >> 8) & 0x0F];
+ result[++pos] = hexify[(codepoint >> 4) & 0x0F];
+ result[++pos] = hexify[codepoint & 0x0F];
+ }
+ else
+ {
+ // codepoints U+10000..U+10FFFF need a surrogate pair to be
+ // represented as \uxxxx\uxxxx.
+ // http://www.unicode.org/faq/utf_bom.html#utf16-4
+ codepoint -= 0x10000;
+ const int high_surrogate = 0xD800 | ((codepoint >> 10) & 0x3FF);
+ const int low_surrogate = 0xDC00 | (codepoint & 0x3FF);
+ result[++pos] = hexify[(high_surrogate >> 12) & 0x0F];
+ result[++pos] = hexify[(high_surrogate >> 8) & 0x0F];
+ result[++pos] = hexify[(high_surrogate >> 4) & 0x0F];
+ result[++pos] = hexify[high_surrogate & 0x0F];
+ ++pos; // backslash is already in output
+ result[++pos] = 'u';
+ result[++pos] = hexify[(low_surrogate >> 12) & 0x0F];
+ result[++pos] = hexify[(low_surrogate >> 8) & 0x0F];
+ result[++pos] = hexify[(low_surrogate >> 4) & 0x0F];
+ result[++pos] = hexify[low_surrogate & 0x0F];
+ }
+
+ ++pos;
+ }
+
+ /*!
+ @brief dump escaped string
+
+ Escape a string by replacing certain special characters by a sequence of an
+ escape character (backslash) and another character and other control
+ characters by a sequence of "\u" followed by a four-digit hex
+ representation. The escaped string is written to output stream @a o.
+
+ @param[in] s the string to escape
+ @param[in] ensure_ascii whether to escape non-ASCII characters with
+ \uXXXX sequences
+
+ @complexity Linear in the length of string @a s.
+ */
+ void dump_escaped(const string_t& s, const bool ensure_ascii) const
+ {
+ throw_if_invalid_utf8(s);
+
+ const auto space = extra_space(s, ensure_ascii);
+ if (space == 0)
+ {
+ o->write_characters(s.c_str(), s.size());
+ return;
+ }
+
+ // create a result string of necessary size
+ string_t result(s.size() + space, '\\');
+ std::size_t pos = 0;
+
+ for (std::size_t i = 0; i < s.size(); ++i)
+ {
+ switch (s[i])
+ {
+ case '"': // quotation mark (0x22)
+ {
+ result[pos + 1] = '"';
+ pos += 2;
+ break;
+ }
+
+ case '\\': // reverse solidus (0x5C)
+ {
+ // nothing to change
+ pos += 2;
+ break;
+ }
+
+ case '\b': // backspace (0x08)
+ {
+ result[pos + 1] = 'b';
+ pos += 2;
+ break;
+ }
+
+ case '\f': // formfeed (0x0C)
+ {
+ result[pos + 1] = 'f';
+ pos += 2;
+ break;
+ }
+
+ case '\n': // newline (0x0A)
+ {
+ result[pos + 1] = 'n';
+ pos += 2;
+ break;
+ }
+
+ case '\r': // carriage return (0x0D)
+ {
+ result[pos + 1] = 'r';
+ pos += 2;
+ break;
+ }
+
+ case '\t': // horizontal tab (0x09)
+ {
+ result[pos + 1] = 't';
+ pos += 2;
+ break;
+ }
+
+ default:
+ {
+ // escape control characters (0x00..0x1F) or, if
+ // ensure_ascii parameter is used, non-ASCII characters
+ if ((0x00 <= s[i] and s[i] <= 0x1F) or
+ (ensure_ascii and (s[i] & 0x80 or s[i] == 0x7F)))
+ {
+ const auto bytes = bytes_following(static_cast<uint8_t>(s[i]));
+ // invalid characters will be detected by throw_if_invalid_utf8
+ assert (bytes != std::string::npos);
+
+ // check that the additional bytes are present
+ assert(i + bytes < s.size());
+
+ // to use \uxxxx escaping, we first need to calculate
+ // the codepoint from the UTF-8 bytes
+ int codepoint = 0;
+
+ // bytes is unsigned type:
+ assert(bytes <= 3);
+ switch (bytes)
+ {
+ case 0:
+ {
+ codepoint = s[i] & 0xFF;
+ break;
+ }
+
+ case 1:
+ {
+ codepoint = ((s[i] & 0x3F) << 6)
+ + (s[i + 1] & 0x7F);
+ break;
+ }
+
+ case 2:
+ {
+ codepoint = ((s[i] & 0x1F) << 12)
+ + ((s[i + 1] & 0x7F) << 6)
+ + (s[i + 2] & 0x7F);
+ break;
+ }
+
+ case 3:
+ {
+ codepoint = ((s[i] & 0xF) << 18)
+ + ((s[i + 1] & 0x7F) << 12)
+ + ((s[i + 2] & 0x7F) << 6)
+ + (s[i + 3] & 0x7F);
+ break;
+ }
+
+ default:
+ break; // LCOV_EXCL_LINE
+ }
+
+ escape_codepoint(codepoint, result, pos);
+ i += bytes;
+ }
+ else
+ {
+ // all other characters are added as-is
+ result[pos++] = s[i];
+ }
+ break;
+ }
+ }
+ }
+
+ assert(pos == result.size());
+ o->write_characters(result.c_str(), result.size());
+ }
+
+ /*!
+ @brief dump an integer
+
+ Dump a given integer to output stream @a o. Works internally with
+ @a number_buffer.
+
+ @param[in] x integer number (signed or unsigned) to dump
+ @tparam NumberType either @a number_integer_t or @a number_unsigned_t
+ */
+ template<typename NumberType, detail::enable_if_t<
+ std::is_same<NumberType, number_unsigned_t>::value or
+ std::is_same<NumberType, number_integer_t>::value,
+ int> = 0>
+ void dump_integer(NumberType x)
+ {
+ // special case for "0"
+ if (x == 0)
+ {
+ o->write_character('0');
+ return;
+ }
+
+ const bool is_negative = (x <= 0) and (x != 0); // see issue #755
+ std::size_t i = 0;
+
+ while (x != 0)
+ {
+ // spare 1 byte for '\0'
+ assert(i < number_buffer.size() - 1);
+
+ const auto digit = std::labs(static_cast<long>(x % 10));
+ number_buffer[i++] = static_cast<char>('0' + digit);
+ x /= 10;
+ }
+
+ if (is_negative)
+ {
+ // make sure there is capacity for the '-'
+ assert(i < number_buffer.size() - 2);
+ number_buffer[i++] = '-';
+ }
+
+ std::reverse(number_buffer.begin(), number_buffer.begin() + i);
+ o->write_characters(number_buffer.data(), i);
+ }
+
+ /*!
+ @brief dump a floating-point number
+
+ Dump a given floating-point number to output stream @a o. Works internally
+ with @a number_buffer.
+
+ @param[in] x floating-point number to dump
+ */
+ void dump_float(number_float_t x)
+ {
+ // NaN / inf
+ if (not std::isfinite(x) or std::isnan(x))
+ {
+ o->write_characters("null", 4);
+ return;
+ }
+
+ // get number of digits for a text -> float -> text round-trip
+ static constexpr auto d = std::numeric_limits<number_float_t>::digits10;
+
+ // the actual conversion
+ std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
+
+ // negative value indicates an error
+ assert(len > 0);
+ // check if buffer was large enough
+ assert(static_cast<std::size_t>(len) < number_buffer.size());
+
+ // erase thousands separator
+ if (thousands_sep != '\0')
+ {
+ const auto end = std::remove(number_buffer.begin(),
+ number_buffer.begin() + len, thousands_sep);
+ std::fill(end, number_buffer.end(), '\0');
+ assert((end - number_buffer.begin()) <= len);
+ len = (end - number_buffer.begin());
+ }
+
+ // convert decimal point to '.'
+ if (decimal_point != '\0' and decimal_point != '.')
+ {
+ const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
+ if (dec_pos != number_buffer.end())
+ {
+ *dec_pos = '.';
+ }
+ }
+
+ o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
+
+ // determine if need to append ".0"
+ const bool value_is_int_like =
+ std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
+ [](char c)
+ {
+ return (c == '.' or c == 'e');
+ });
+
+ if (value_is_int_like)
+ {
+ o->write_characters(".0", 2);
+ }
+ }
+
+ /*!
+ @brief check whether a string is UTF-8 encoded
+
+ The function checks each byte of a string whether it is UTF-8 encoded. The
+ result of the check is stored in the @a state parameter. The function must
+ be called initially with state 0 (accept). State 1 means the string must
+ be rejected, because the current byte is not allowed. If the string is
+ completely processed, but the state is non-zero, the string ended
+ prematurely; that is, the last byte indicated more bytes should have
+ followed.
+
+ @param[in,out] state the state of the decoding
+ @param[in] byte next byte to decode
+
+ @note The function has been edited: a std::array is used and the code
+ point is not calculated.
+
+ @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+ @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+ */
+ static void decode(uint8_t& state, const uint8_t byte)
+ {
+ static const std::array<uint8_t, 400> utf8d =
+ {
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
+ 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, // A0..BF
+ 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
+ 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
+ 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
+ 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
+ 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
+ 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
+ 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
+ }
+ };
+
+ const uint8_t type = utf8d[byte];
+ state = utf8d[256u + state * 16u + type];
+ }
+
+ /*!
+ @brief throw an exception if a string is not UTF-8 encoded
+
+ @param[in] str UTF-8 string to check
+ @throw type_error.316 if passed string is not UTF-8 encoded
+
+ @since version 3.0.0
+ */
+ static void throw_if_invalid_utf8(const std::string& str)
+ {
+ // start with state 0 (= accept)
+ uint8_t state = 0;
+
+ for (size_t i = 0; i < str.size(); ++i)
+ {
+ const auto byte = static_cast<uint8_t>(str[i]);
+ decode(state, byte);
+ if (state == 1)
+ {
+ // state 1 means reject
+ std::stringstream ss;
+ ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(byte);
+ JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str()));
+ }
+ }
+
+ if (state != 0)
+ {
+ // we finish reading, but do not accept: string was incomplete
+ std::stringstream ss;
+ ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(static_cast<uint8_t>(str.back()));
+ JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str()));
+ }
+ }
+
+ private:
+ /// the output of the serializer
+ output_adapter_t<char> o = nullptr;
+
+ /// a (hopefully) large enough character buffer
+ std::array<char, 64> number_buffer{{}};
+
+ /// the locale
+ const std::lconv* loc = nullptr;
+ /// the locale's thousand separator character
+ const char thousands_sep = '\0';
+ /// the locale's decimal point character
+ const char decimal_point = '\0';
+
+ /// the indentation character
+ const char indent_char;
+
+ /// the indentation string
+ string_t indent_string;
+};
+
+template<typename BasicJsonType>
+class json_ref
+{
+ public:
+ using value_type = BasicJsonType;
+
+ json_ref(value_type&& value)
+ : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
+ {}
+
+ json_ref(const value_type& value)
+ : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
+ {}
+
+ json_ref(std::initializer_list<json_ref> init)
+ : owned_value(init), value_ref(&owned_value), is_rvalue(true)
+ {}
+
+ template<class... Args>
+ json_ref(Args&& ... args)
+ : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
+ {}
+
+ // class should be movable only
+ json_ref(json_ref&&) = default;
+ json_ref(const json_ref&) = delete;
+ json_ref& operator=(const json_ref&) = delete;
+
+ value_type moved_or_copied() const
+ {
+ if (is_rvalue)
+ {
+ return std::move(*value_ref);
+ }
+ return *value_ref;
+ }
+
+ value_type const& operator*() const
+ {
+ return *static_cast<value_type const*>(value_ref);
+ }
+
+ value_type const* operator->() const
+ {
+ return static_cast<value_type const*>(value_ref);
+ }
+
+ private:
+ mutable value_type owned_value = nullptr;
+ value_type* value_ref = nullptr;
+ const bool is_rvalue;
+};
+
+} // namespace detail
+
+/// namespace to hold default `to_json` / `from_json` functions
+namespace
+{
+constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
+constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
}
+
+/*!
+@brief default JSONSerializer template argument
+
+This serializer ignores the template arguments and uses ADL
+([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))
+for serialization.
+*/
+template<typename, typename>
+struct adl_serializer
+{
+ /*!
+ @brief convert a JSON value to any value type
+
+ This function is usually called by the `get()` function of the
+ @ref basic_json class (either explicit or via conversion operators).
+
+ @param[in] j JSON value to read from
+ @param[in,out] val value to write to
+ */
+ template<typename BasicJsonType, typename ValueType>
+ static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
+ noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
+ {
+ ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
+ }
+
+ /*!
+ @brief convert any value type to a JSON value
+
+ This function is usually called by the constructors of the @ref basic_json
+ class.
+
+ @param[in,out] j JSON value to write to
+ @param[in] val value to read from
+ */
+ template<typename BasicJsonType, typename ValueType>
+ static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
+ noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
+ {
+ ::nlohmann::to_json(j, std::forward<ValueType>(val));
+ }
+};
+
+/*!
+@brief JSON Pointer
+
+A JSON pointer defines a string syntax for identifying a specific value
+within a JSON document. It can be used with functions `at` and
+`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
+
+@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
+
+@since version 2.0.0
+*/
+class json_pointer
+{
+ /// allow basic_json to access private members
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ friend class basic_json;
+
+ public:
+ /*!
+ @brief create JSON pointer
+
+ Create a JSON pointer according to the syntax described in
+ [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
+
+ @param[in] s string representing the JSON pointer; if omitted, the empty
+ string is assumed which references the whole JSON value
+
+ @throw parse_error.107 if the given JSON pointer @a s is nonempty and
+ does not begin with a slash (`/`); see example below
+
+ @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s
+ is not followed by `0` (representing `~`) or `1` (representing `/`);
+ see example below
+
+ @liveexample{The example shows the construction several valid JSON
+ pointers as well as the exceptional behavior.,json_pointer}
+
+ @since version 2.0.0
+ */
+ explicit json_pointer(const std::string& s = "") : reference_tokens(split(s)) {}
+
+ /*!
+ @brief return a string representation of the JSON pointer
+
+ @invariant For each JSON pointer `ptr`, it holds:
+ @code {.cpp}
+ ptr == json_pointer(ptr.to_string());
+ @endcode
+
+ @return a string representation of the JSON pointer
+
+ @liveexample{The example shows the result of `to_string`.,
+ json_pointer__to_string}
+
+ @since version 2.0.0
+ */
+ std::string to_string() const noexcept
+ {
+ return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
+ std::string{},
+ [](const std::string & a, const std::string & b)
+ {
+ return a + "/" + escape(b);
+ });
+ }
+
+ /// @copydoc to_string()
+ operator std::string() const
+ {
+ return to_string();
+ }
+
+ /*!
+ @param[in] s reference token to be converted into an array index
+
+ @return integer representation of @a s
+
+ @throw out_of_range.404 if string @a s could not be converted to an integer
+ */
+ static int array_index(const std::string& s)
+ {
+ size_t processed_chars = 0;
+ const int res = std::stoi(s, &processed_chars);
+
+ // check if the string was completely read
+ if (JSON_UNLIKELY(processed_chars != s.size()))
+ {
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
+ }
+
+ return res;
+ }
+
+ private:
+ /*!
+ @brief remove and return last reference pointer
+ @throw out_of_range.405 if JSON pointer has no parent
+ */
+ std::string pop_back()
+ {
+ if (JSON_UNLIKELY(is_root()))
+ {
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
+ }
+
+ auto last = reference_tokens.back();
+ reference_tokens.pop_back();
+ return last;
+ }
+
+ /// return whether pointer points to the root document
+ bool is_root() const
+ {
+ return reference_tokens.empty();
+ }
+
+ json_pointer top() const
+ {
+ if (JSON_UNLIKELY(is_root()))
+ {
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
+ }
+
+ json_pointer result = *this;
+ result.reference_tokens = {reference_tokens[0]};
+ return result;
+ }
+
+ /*!
+ @brief create and return a reference to the pointed to value
+
+ @complexity Linear in the number of reference tokens.
+
+ @throw parse_error.109 if array index is not a number
+ @throw type_error.313 if value cannot be unflattened
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ NLOHMANN_BASIC_JSON_TPL& get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const;
+
+ /*!
+ @brief return a reference to the pointed to value
+
+ @note This version does not throw if a value is not present, but tries to
+ create nested values instead. For instance, calling this function
+ with pointer `"/this/that"` on a null value is equivalent to calling
+ `operator[]("this").operator[]("that")` on that value, effectively
+ changing the null value to an object.
+
+ @param[in] ptr a JSON value
+
+ @return reference to the JSON value pointed to by the JSON pointer
+
+ @complexity Linear in the length of the JSON pointer.
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ NLOHMANN_BASIC_JSON_TPL& get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const;
+
+ /*!
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ NLOHMANN_BASIC_JSON_TPL& get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const;
+
+ /*!
+ @brief return a const reference to the pointed to value
+
+ @param[in] ptr a JSON value
+
+ @return const reference to the JSON value pointed to by the JSON
+ pointer
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ const NLOHMANN_BASIC_JSON_TPL& get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const;
+
+ /*!
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ const NLOHMANN_BASIC_JSON_TPL& get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const;
+
+ /*!
+ @brief split the string input to reference tokens
+
+ @note This function is only called by the json_pointer constructor.
+ All exceptions below are documented there.
+
+ @throw parse_error.107 if the pointer is not empty or begins with '/'
+ @throw parse_error.108 if character '~' is not followed by '0' or '1'
+ */
+ static std::vector<std::string> split(const std::string& reference_string)
+ {
+ std::vector<std::string> result;
+
+ // special case: empty reference string -> no reference tokens
+ if (reference_string.empty())
+ {
+ return result;
+ }
+
+ // check if nonempty reference string begins with slash
+ if (JSON_UNLIKELY(reference_string[0] != '/'))
+ {
+ JSON_THROW(detail::parse_error::create(107, 1,
+ "JSON pointer must be empty or begin with '/' - was: '" +
+ reference_string + "'"));
+ }
+
+ // extract the reference tokens:
+ // - slash: position of the last read slash (or end of string)
+ // - start: position after the previous slash
+ for (
+ // search for the first slash after the first character
+ std::size_t slash = reference_string.find_first_of('/', 1),
+ // set the beginning of the first reference token
+ start = 1;
+ // we can stop if start == string::npos+1 = 0
+ start != 0;
+ // set the beginning of the next reference token
+ // (will eventually be 0 if slash == std::string::npos)
+ start = slash + 1,
+ // find next slash
+ slash = reference_string.find_first_of('/', start))
+ {
+ // use the text between the beginning of the reference token
+ // (start) and the last slash (slash).
+ auto reference_token = reference_string.substr(start, slash - start);
+
+ // check reference tokens are properly escaped
+ for (std::size_t pos = reference_token.find_first_of('~');
+ pos != std::string::npos;
+ pos = reference_token.find_first_of('~', pos + 1))
+ {
+ assert(reference_token[pos] == '~');
+
+ // ~ must be followed by 0 or 1
+ if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
+ (reference_token[pos + 1] != '0' and
+ reference_token[pos + 1] != '1')))
+ {
+ JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
+ }
+ }
+
+ // finally, store the reference token
+ unescape(reference_token);
+ result.push_back(reference_token);
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief replace all occurrences of a substring by another string
+
+ @param[in,out] s the string to manipulate; changed so that all
+ occurrences of @a f are replaced with @a t
+ @param[in] f the substring to replace with @a t
+ @param[in] t the string to replace @a f
+
+ @pre The search string @a f must not be empty. **This precondition is
+ enforced with an assertion.**
+
+ @since version 2.0.0
+ */
+ static void replace_substring(std::string& s, const std::string& f,
+ const std::string& t)
+ {
+ assert(not f.empty());
+ for (auto pos = s.find(f); // find first occurrence of f
+ pos != std::string::npos; // make sure f was found
+ s.replace(pos, f.size(), t), // replace with t, and
+ pos = s.find(f, pos + t.size())) // find next occurrence of f
+ {}
+ }
+
+ /// escape "~"" to "~0" and "/" to "~1"
+ static std::string escape(std::string s)
+ {
+ replace_substring(s, "~", "~0");
+ replace_substring(s, "/", "~1");
+ return s;
+ }
+
+ /// unescape "~1" to tilde and "~0" to slash (order is important!)
+ static void unescape(std::string& s)
+ {
+ replace_substring(s, "~1", "/");
+ replace_substring(s, "~0", "~");
+ }
+
+ /*!
+ @param[in] reference_string the reference string to the current value
+ @param[in] value the value to consider
+ @param[in,out] result the result object to insert values to
+
+ @note Empty objects or arrays are flattened to `null`.
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ static void flatten(const std::string& reference_string,
+ const NLOHMANN_BASIC_JSON_TPL& value,
+ NLOHMANN_BASIC_JSON_TPL& result);
+
+ /*!
+ @param[in] value flattened JSON
+
+ @return unflattened JSON
+
+ @throw parse_error.109 if array index is not a number
+ @throw type_error.314 if value is not an object
+ @throw type_error.315 if object values are not primitive
+ @throw type_error.313 if value cannot be unflattened
+ */
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ static NLOHMANN_BASIC_JSON_TPL
+ unflatten(const NLOHMANN_BASIC_JSON_TPL& value);
+
+ friend bool operator==(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept;
+
+ friend bool operator!=(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept;
+
+ /// the reference tokens
+ std::vector<std::string> reference_tokens;
+};
+
/*!
@brief a class to store JSON values
@@ -122,11 +7300,14 @@ default; will be used in @ref number_integer_t)
default; will be used in @ref number_float_t)
@tparam AllocatorType type of the allocator to use (`std::allocator` by
default)
+@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
+and `from_json()` (@ref adl_serializer by default)
@requirement The class satisfies the following concept requirements:
- Basic
- [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
- JSON values can be default constructed. The result will be a JSON null value.
+ JSON values can be default constructed. The result will be a JSON null
+ value.
- [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
A JSON value can be constructed from an rvalue argument.
- [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
@@ -141,8 +7322,8 @@ default)
- [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
JSON values have
[standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
- All non-static data members are private and standard layout types, the class
- has no virtual functions or (virtual) base classes.
+ All non-static data members are private and standard layout types, the
+ class has no virtual functions or (virtual) base classes.
- Library-wide
- [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
JSON values can be compared with `==`, see @ref
@@ -163,6 +7344,13 @@ default)
JSON values can be used like STL containers and provide reverse iterator
access.
+@invariant The member variables @a m_value and @a m_type have the following
+relationship:
+- If `m_type == value_t::object`, then `m_value.object != nullptr`.
+- If `m_type == value_t::array`, then `m_value.array != nullptr`.
+- If `m_type == value_t::string`, then `m_value.string != nullptr`.
+The invariants are checked by member function assert_invariant().
+
@internal
@note ObjectType trick from http://stackoverflow.com/a/9860911
@endinternal
@@ -174,39 +7362,85 @@ Format](http://rfc7159.net/rfc7159)
@nosubgrouping
*/
-template <
- template<typename U, typename V, typename... Args> class ObjectType = std::map,
- template<typename U, typename... Args> class ArrayType = std::vector,
- class StringType = std::string,
- class BooleanType = bool,
- class NumberIntegerType = std::int64_t,
- class NumberUnsignedType = std::uint64_t,
- class NumberFloatType = double,
- template<typename U> class AllocatorType = std::allocator
- >
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
class basic_json
{
private:
+ template<detail::value_t> friend struct detail::external_constructor;
+ friend ::nlohmann::json_pointer;
+ friend ::nlohmann::detail::parser<basic_json>;
+ friend ::nlohmann::detail::serializer<basic_json>;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::iter_impl;
+ template<typename BasicJsonType, typename CharType>
+ friend class ::nlohmann::detail::binary_writer;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::binary_reader;
+
/// workaround type for MSVC
- using basic_json_t = basic_json<ObjectType,
- ArrayType,
- StringType,
- BooleanType,
- NumberIntegerType,
- NumberUnsignedType,
- NumberFloatType,
- AllocatorType>;
+ using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
+
+ // convenience aliases for types residing in namespace detail;
+ using lexer = ::nlohmann::detail::lexer<basic_json>;
+ using parser = ::nlohmann::detail::parser<basic_json>;
+
+ using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
+ template<typename BasicJsonType>
+ using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
+ template<typename BasicJsonType>
+ using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
+ template<typename Iterator>
+ using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
+ template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
+
+ template<typename CharType>
+ using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
+
+ using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
+ template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
+
+ using serializer = ::nlohmann::detail::serializer<basic_json>;
public:
- // forward declarations
- template<typename Base> class json_reverse_iterator;
- class json_pointer;
+ using value_t = detail::value_t;
+ /// @copydoc nlohmann::json_pointer
+ using json_pointer = ::nlohmann::json_pointer;
+ template<typename T, typename SFINAE>
+ using json_serializer = JSONSerializer<T, SFINAE>;
+ /// helper type for initializer lists of basic_json values
+ using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+
+ ////////////////
+ // exceptions //
+ ////////////////
+
+ /// @name exceptions
+ /// Classes to implement user-defined exceptions.
+ /// @{
+
+ /// @copydoc detail::exception
+ using exception = detail::exception;
+ /// @copydoc detail::parse_error
+ using parse_error = detail::parse_error;
+ /// @copydoc detail::invalid_iterator
+ using invalid_iterator = detail::invalid_iterator;
+ /// @copydoc detail::type_error
+ using type_error = detail::type_error;
+ /// @copydoc detail::out_of_range
+ using out_of_range = detail::out_of_range;
+ /// @copydoc detail::other_error
+ using other_error = detail::other_error;
+
+ /// @}
+
/////////////////////
// container types //
/////////////////////
/// @name container types
+ /// The canonic container types to use @ref basic_json like any other STL
+ /// container.
/// @{
/// the type of elements in a basic_json container
@@ -231,9 +7465,9 @@ class basic_json
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
/// an iterator for a basic_json container
- class iterator;
+ using iterator = iter_impl<basic_json>;
/// a const iterator for a basic_json container
- class const_iterator;
+ using const_iterator = iter_impl<const basic_json>;
/// a reverse iterator for a basic_json container
using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
/// a const reverse iterator for a basic_json container
@@ -250,14 +7484,102 @@ class basic_json
return allocator_type();
}
+ /*!
+ @brief returns version information on the library
+
+ This function returns a JSON object with information about the library,
+ including the version number and information on the platform and compiler.
+
+ @return JSON object holding version information
+ key | description
+ ----------- | ---------------
+ `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
+ `copyright` | The copyright line for the library as string.
+ `name` | The name of the library as string.
+ `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
+ `url` | The URL of the project as string.
+ `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
+
+ @liveexample{The following code shows an example output of the `meta()`
+ function.,meta}
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @complexity Constant.
+
+ @since 2.1.0
+ */
+ static basic_json meta()
+ {
+ basic_json result;
+
+ result["copyright"] = "(C) 2013-2017 Niels Lohmann";
+ result["name"] = "JSON for Modern C++";
+ result["url"] = "https://github.com/nlohmann/json";
+ result["version"] =
+ {
+ {"string", "3.0.1"}, {"major", 3}, {"minor", 0}, {"patch", 1}
+ };
+
+#ifdef _WIN32
+ result["platform"] = "win32";
+#elif defined __linux__
+ result["platform"] = "linux";
+#elif defined __APPLE__
+ result["platform"] = "apple";
+#elif defined __unix__
+ result["platform"] = "unix";
+#else
+ result["platform"] = "unknown";
+#endif
+
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+ result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
+#elif defined(__clang__)
+ result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
+#elif defined(__GNUC__) || defined(__GNUG__)
+ result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
+#elif defined(__HP_cc) || defined(__HP_aCC)
+ result["compiler"] = "hp"
+#elif defined(__IBMCPP__)
+ result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
+#elif defined(_MSC_VER)
+ result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
+#elif defined(__PGI)
+ result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
+#elif defined(__SUNPRO_CC)
+ result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
+#else
+ result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
+#endif
+
+#ifdef __cplusplus
+ result["compiler"]["c++"] = std::to_string(__cplusplus);
+#else
+ result["compiler"]["c++"] = "unknown";
+#endif
+ return result;
+ }
+
///////////////////////////
// JSON value data types //
///////////////////////////
/// @name JSON value data types
+ /// The data types to store a JSON value. These types are derived from
+ /// the template arguments passed to class @ref basic_json.
/// @{
+#if defined(JSON_HAS_CPP_14)
+ // Use transparent comparator if possible, combined with perfect forwarding
+ // on find() and count() calls prevents unnecessary string construction.
+ using object_comparator_t = std::less<>;
+#else
+ using object_comparator_t = std::less<StringType>;
+#endif
+
/*!
@brief a type for an object
@@ -318,7 +7640,7 @@ class basic_json
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the maximum depth of nesting.
- In this class, the object's limit of nesting is not constraint explicitly.
+ In this class, the object's limit of nesting is not explicitly constrained.
However, a maximum depth of nesting may be introduced by the compiler or
runtime environment. A theoretical limit can be queried by calling the
@ref max_size function of a JSON object.
@@ -343,7 +7665,7 @@ class basic_json
*/
using object_t = ObjectType<StringType,
basic_json,
- std::less<StringType>,
+ object_comparator_t,
AllocatorType<std::pair<const StringType,
basic_json>>>;
@@ -358,7 +7680,7 @@ class basic_json
@tparam ArrayType container type to store arrays (e.g., `std::vector` or
`std::list`)
- @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
+ @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
#### Default type
@@ -377,7 +7699,7 @@ class basic_json
[RFC 7159](http://rfc7159.net/rfc7159) specifies:
> An implementation may set limits on the maximum depth of nesting.
- In this class, the array's limit of nesting is not constraint explicitly.
+ In this class, the array's limit of nesting is not explicitly constrained.
However, a maximum depth of nesting may be introduced by the compiler or
runtime environment. A theoretical limit can be queried by calling the
@ref max_size function of a JSON array.
@@ -415,6 +7737,12 @@ class basic_json
std::string
@endcode
+ #### Encoding
+
+ Strings are stored in UTF-8 encoding. Therefore, functions like
+ `std::string::size()` or `std::string::length()` return the number of
+ bytes in the string rather than the number of characters or glyphs.
+
#### String comparison
[RFC 7159](http://rfc7159.net/rfc7159) states:
@@ -595,15 +7923,14 @@ class basic_json
> that implementations will agree exactly on their numeric values.
As this range is a subrange (when considered in conjunction with the
- number_integer_t type) of the exactly supported range [0, UINT64_MAX], this
- class's integer type is interoperable.
+ number_integer_t type) of the exactly supported range [0, UINT64_MAX],
+ this class's integer type is interoperable.
#### Storage
Integer number values are stored directly inside a @ref basic_json type.
@sa @ref number_float_t -- type for number values (floating-point)
-
@sa @ref number_integer_t -- type for number values (integer)
@since version 2.0.0
@@ -680,115 +8007,22 @@ class basic_json
/// @}
-
- ///////////////////////////
- // JSON type enumeration //
- ///////////////////////////
-
- /*!
- @brief the JSON type enumeration
-
- This enumeration collects the different JSON types. It is internally used
- to distinguish the stored values, and the functions @ref is_null(), @ref
- is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref
- is_number(), and @ref is_discarded() rely on it.
-
- @since version 1.0.0
- */
- enum class value_t : uint8_t
- {
- null, ///< null value
- object, ///< object (unordered set of name/value pairs)
- array, ///< array (ordered collection of values)
- string, ///< string value
- boolean, ///< boolean value
- number_integer, ///< number value (integer)
- number_unsigned, ///< number value (unsigned integer)
- number_float, ///< number value (floating-point)
- discarded ///< discarded by the the parser callback function
- };
-
-
private:
- /*!
- @brief a type to hold JSON type information
-
- This bitfield type holds information about JSON types. It is internally
- used to hold the basic JSON type enumeration, as well as additional
- information in the case of values that have been parsed from a string
- including whether of not it was created directly or parsed, and in the
- case of floating point numbers the number of significant figures in the
- original representaiton and if it was in exponential form, if a '+' was
- included in the exponent and the capitilization of the exponent marker.
- The sole purpose of this information is to permit accurate round trips.
-
- @since version 2.0.0
- */
- union type_data_t
- {
- struct
- {
- /// the type of the value (@ref value_t)
- uint16_t type : 4;
- /// whether the number was parsed from a string
- uint16_t parsed : 1;
- /// whether parsed number contained an exponent ('e'/'E')
- uint16_t has_exp : 1;
- /// whether parsed number contained a plus in the exponent
- uint16_t exp_plus : 1;
- /// whether parsed number's exponent was capitalized ('E')
- uint16_t exp_cap : 1;
- /// the number of figures for a parsed number
- uint16_t precision : 8;
- } bits;
- uint16_t data;
-
- /// return the type as value_t
- operator value_t() const
- {
- return static_cast<value_t>(bits.type);
- }
-
- /// test type for equality (ignore other fields)
- bool operator==(const value_t& rhs) const
- {
- return static_cast<value_t>(bits.type) == rhs;
- }
-
- /// assignment
- type_data_t& operator=(value_t rhs)
- {
- bits.type = static_cast<uint16_t>(rhs) & 15; // avoid overflow
- return *this;
- }
-
- /// construct from value_t
- type_data_t(value_t t) noexcept
- {
- *reinterpret_cast<uint16_t*>(this) = 0;
- bits.type = static_cast<uint16_t>(t) & 15; // avoid overflow
- }
-
- /// default constructor
- type_data_t() noexcept
- {
- data = 0;
- bits.type = reinterpret_cast<uint16_t>(value_t::null);
- }
- };
-
/// helper for exception-safe object creation
template<typename T, typename... Args>
static T* create(Args&& ... args)
{
AllocatorType<T> alloc;
+ using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
+
auto deleter = [&](T * object)
{
- alloc.deallocate(object, 1);
+ AllocatorTraits::deallocate(alloc, object, 1);
};
- std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
- alloc.construct(object.get(), std::forward<Args>(args)...);
+ std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
+ AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
+ assert(object != nullptr);
return object.release();
}
@@ -799,7 +8033,24 @@ class basic_json
/*!
@brief a JSON value
- The actual storage for a JSON value of the @ref basic_json class.
+ The actual storage for a JSON value of the @ref basic_json class. This
+ union combines the different storage types for the JSON value types
+ defined in @ref value_t.
+
+ JSON type | value_t type | used type
+ --------- | --------------- | ------------------------
+ object | object | pointer to @ref object_t
+ array | array | pointer to @ref array_t
+ string | string | pointer to @ref string_t
+ boolean | boolean | @ref boolean_t
+ number | number_integer | @ref number_integer_t
+ number | number_unsigned | @ref number_unsigned_t
+ number | number_float | @ref number_float_t
+ null | null | *no value is stored*
+
+ @note Variable-length types (objects, arrays, and strings) are stored as
+ pointers. The size of the union should not exceed 64 bits if the default
+ value types are used.
@since version 1.0.0
*/
@@ -877,8 +8128,19 @@ class basic_json
break;
}
+ case value_t::null:
+ {
+ object = nullptr; // silence warning, see #821
+ break;
+ }
+
default:
{
+ object = nullptr; // silence warning, see #821
+ if (JSON_UNLIKELY(t == value_t::null))
+ {
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.0.1")); // LCOV_EXCL_LINE
+ }
break;
}
}
@@ -890,19 +8152,87 @@ class basic_json
string = create<string_t>(value);
}
+ /// constructor for rvalue strings
+ json_value(string_t&& value)
+ {
+ string = create<string_t>(std::move(value));
+ }
+
/// constructor for objects
json_value(const object_t& value)
{
object = create<object_t>(value);
}
+ /// constructor for rvalue objects
+ json_value(object_t&& value)
+ {
+ object = create<object_t>(std::move(value));
+ }
+
/// constructor for arrays
json_value(const array_t& value)
{
array = create<array_t>(value);
}
+
+ /// constructor for rvalue arrays
+ json_value(array_t&& value)
+ {
+ array = create<array_t>(std::move(value));
+ }
+
+ void destroy(value_t t)
+ {
+ switch (t)
+ {
+ case value_t::object:
+ {
+ AllocatorType<object_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ AllocatorType<array_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
+ break;
+ }
+
+ case value_t::string:
+ {
+ AllocatorType<string_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
};
+ /*!
+ @brief checks the class invariants
+
+ This function asserts the class invariants. It needs to be called at the
+ end of every constructor to make sure that created objects respect the
+ invariant. Furthermore, it has to be called each time the type of a JSON
+ value is changed, because the invariant expresses a relationship between
+ @a m_type and @a m_value.
+ */
+ void assert_invariant() const
+ {
+ assert(m_type != value_t::object or m_value.object != nullptr);
+ assert(m_type != value_t::array or m_value.array != nullptr);
+ assert(m_type != value_t::string or m_value.string != nullptr);
+ }
public:
//////////////////////////
@@ -910,39 +8240,31 @@ class basic_json
//////////////////////////
/*!
- @brief JSON callback events
+ @brief parser event types
- This enumeration lists the parser events that can trigger calling a
- callback function of type @ref parser_callback_t during parsing.
+ The parser callback distinguishes the following events:
+ - `object_start`: the parser read `{` and started to process a JSON object
+ - `key`: the parser read a key of a value in an object
+ - `object_end`: the parser read `}` and finished processing a JSON object
+ - `array_start`: the parser read `[` and started to process a JSON array
+ - `array_end`: the parser read `]` and finished processing a JSON array
+ - `value`: the parser finished reading a JSON value
- @since version 1.0.0
+ @image html callback_events.png "Example when certain parse events are triggered"
+
+ @sa @ref parser_callback_t for more information and examples
*/
- enum class parse_event_t : uint8_t
- {
- /// the parser read `{` and started to process a JSON object
- object_start,
- /// the parser read `}` and finished processing a JSON object
- object_end,
- /// the parser read `[` and started to process a JSON array
- array_start,
- /// the parser read `]` and finished processing a JSON array
- array_end,
- /// the parser read a key of a value in an object
- key,
- /// the parser finished reading a JSON value
- value
- };
+ using parse_event_t = typename parser::parse_event_t;
/*!
@brief per-element parser callback type
With a parser callback function, the result of parsing a JSON text can be
- influenced. When passed to @ref parse(std::istream&, parser_callback_t) or
- @ref parse(const string_t&, parser_callback_t), it is called on certain
- events (passed as @ref parse_event_t via parameter @a event) with a set
- recursion depth @a depth and context JSON value @a parsed. The return
- value of the callback function is a boolean indicating whether the element
- that emitted the callback shall be kept or not.
+ influenced. When passed to @ref parse, it is called on certain events
+ (passed as @ref parse_event_t via parameter @a event) with a set recursion
+ depth @a depth and context JSON value @a parsed. The return value of the
+ callback function is a boolean indicating whether the element that emitted
+ the callback shall be kept or not.
We distinguish six scenarios (determined by the event type) in which the
callback function can be called. The following table describes the values
@@ -957,6 +8279,8 @@ class basic_json
parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
+ @image html callback_events.png "Example when certain parse events are triggered"
+
Discarding a value (i.e., returning `false`) has different effects
depending on the context in which function was called:
@@ -977,12 +8301,11 @@ class basic_json
should be kept (`true`) or not (`false`). In the latter case, it is either
skipped completely or replaced by an empty discarded object.
- @sa @ref parse(std::istream&, parser_callback_t) or
- @ref parse(const string_t&, parser_callback_t) for examples
+ @sa @ref parse for examples
@since version 1.0.0
*/
- using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
+ using parser_callback_t = typename parser::parser_callback_t;
//////////////////
@@ -990,6 +8313,8 @@ class basic_json
//////////////////
/// @name constructors and destructors
+ /// Constructors of class @ref basic_json, copy/move constructor, copy
+ /// assignment, static functions creating objects, and the destructor.
/// @{
/*!
@@ -1007,66 +8332,31 @@ class basic_json
object | `{}`
array | `[]`
- @param[in] value_type the type of the value to create
+ @param[in] v the type of the value to create
@complexity Constant.
- @throw std::bad_alloc if allocation for object, array, or string value
- fails
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
@liveexample{The following code shows the constructor for different @ref
value_t values,basic_json__value_t}
- @sa @ref basic_json(std::nullptr_t) -- create a `null` value
- @sa @ref basic_json(boolean_t value) -- create a boolean value
- @sa @ref basic_json(const string_t&) -- create a string value
- @sa @ref basic_json(const object_t&) -- create a object value
- @sa @ref basic_json(const array_t&) -- create a array value
- @sa @ref basic_json(const number_float_t) -- create a number
- (floating-point) value
- @sa @ref basic_json(const number_integer_t) -- create a number (integer)
- value
- @sa @ref basic_json(const number_unsigned_t) -- create a number (unsigned)
- value
+ @sa @ref clear() -- restores the postcondition of this constructor
@since version 1.0.0
*/
- basic_json(const value_t value_type)
- : m_type(value_type), m_value(value_type)
- {}
-
- /*!
- @brief create a null object (implicitly)
-
- Create a `null` JSON value. This is the implicit version of the `null`
- value constructor as it takes no parameters.
-
- @complexity Constant.
-
- @exceptionsafety No-throw guarantee: this constructor never throws
- exceptions.
-
- @requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
- requirements:
- - The complexity is constant.
- - As postcondition, it holds: `basic_json().empty() == true`.
-
- @liveexample{The following code shows the constructor for a `null` JSON
- value.,basic_json}
-
- @sa @ref basic_json(std::nullptr_t) -- create a `null` value
-
- @since version 1.0.0
- */
- basic_json() = default;
+ basic_json(const value_t v)
+ : m_type(v), m_value(v)
+ {
+ assert_invariant();
+ }
/*!
- @brief create a null object (explicitly)
+ @brief create a null object
- Create a `null` JSON value. This is the explicitly version of the `null`
- value constructor as it takes a null pointer as parameter. It allows to
- create `null` values by explicitly assigning a `nullptr` to a JSON value.
+ Create a `null` JSON value. It either takes a null pointer as parameter
+ (explicitly creating `null`) or no parameter (implicitly creating `null`).
The passed null pointer itself is not read -- it is only used to choose
the right constructor.
@@ -1075,480 +8365,88 @@ class basic_json
@exceptionsafety No-throw guarantee: this constructor never throws
exceptions.
- @liveexample{The following code shows the constructor with null pointer
- parameter.,basic_json__nullptr_t}
-
- @sa @ref basic_json() -- default constructor (implicitly creating a `null`
- value)
+ @liveexample{The following code shows the constructor with and without a
+ null pointer parameter.,basic_json__nullptr_t}
@since version 1.0.0
*/
- basic_json(std::nullptr_t) noexcept
+ basic_json(std::nullptr_t = nullptr) noexcept
: basic_json(value_t::null)
- {}
-
- /*!
- @brief create an object (explicit)
-
- Create an object JSON value with a given content.
-
- @param[in] val a value for the object
-
- @complexity Linear in the size of the passed @a val.
-
- @throw std::bad_alloc if allocation for object value fails
-
- @liveexample{The following code shows the constructor with an @ref
- object_t parameter.,basic_json__object_t}
-
- @sa @ref basic_json(const CompatibleObjectType&) -- create an object value
- from a compatible STL container
-
- @since version 1.0.0
- */
- basic_json(const object_t& val)
- : m_type(value_t::object), m_value(val)
- {}
-
- /*!
- @brief create an object (implicit)
-
- Create an object JSON value with a given content. This constructor allows
- any type @a CompatibleObjectType that can be used to construct values of
- type @ref object_t.
-
- @tparam CompatibleObjectType An object type whose `key_type` and
- `value_type` is compatible to @ref object_t. Examples include `std::map`,
- `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with
- a `key_type` of `std::string`, and a `value_type` from which a @ref
- basic_json value can be constructed.
-
- @param[in] val a value for the object
-
- @complexity Linear in the size of the passed @a val.
-
- @throw std::bad_alloc if allocation for object value fails
-
- @liveexample{The following code shows the constructor with several
- compatible object type parameters.,basic_json__CompatibleObjectType}
-
- @sa @ref basic_json(const object_t&) -- create an object value
-
- @since version 1.0.0
- */
- template <class CompatibleObjectType, typename
- std::enable_if<
- std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
- std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
- = 0>
- basic_json(const CompatibleObjectType& val)
- : m_type(value_t::object)
{
- using std::begin;
- using std::end;
- m_value.object = create<object_t>(begin(val), end(val));
+ assert_invariant();
}
/*!
- @brief create an array (explicit)
-
- Create an array JSON value with a given content.
-
- @param[in] val a value for the array
-
- @complexity Linear in the size of the passed @a val.
-
- @throw std::bad_alloc if allocation for array value fails
+ @brief create a JSON value
- @liveexample{The following code shows the constructor with an @ref array_t
- parameter.,basic_json__array_t}
+ This is a "catch all" constructor for all compatible JSON types; that is,
+ types for which a `to_json()` method exists. The constructor forwards the
+ parameter @a val to that method (to `json_serializer<U>::to_json` method
+ with `U = uncvref_t<CompatibleType>`, to be exact).
- @sa @ref basic_json(const CompatibleArrayType&) -- create an array value
- from a compatible STL containers
+ Template type @a CompatibleType includes, but is not limited to, the
+ following types:
+ - **arrays**: @ref array_t and all kinds of compatible containers such as
+ `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
+ `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
+ `std::multiset`, and `std::unordered_multiset` with a `value_type` from
+ which a @ref basic_json value can be constructed.
+ - **objects**: @ref object_t and all kinds of compatible associative
+ containers such as `std::map`, `std::unordered_map`, `std::multimap`,
+ and `std::unordered_multimap` with a `key_type` compatible to
+ @ref string_t and a `value_type` from which a @ref basic_json value can
+ be constructed.
+ - **strings**: @ref string_t, string literals, and all compatible string
+ containers can be used.
+ - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
+ @ref number_float_t, and all convertible number types such as `int`,
+ `size_t`, `int64_t`, `float` or `double` can be used.
+ - **boolean**: @ref boolean_t / `bool` can be used.
- @since version 1.0.0
- */
- basic_json(const array_t& val)
- : m_type(value_t::array), m_value(val)
- {}
+ See the examples below.
- /*!
- @brief create an array (implicit)
-
- Create an array JSON value with a given content. This constructor allows
- any type @a CompatibleArrayType that can be used to construct values of
- type @ref array_t.
+ @tparam CompatibleType a type such that:
+ - @a CompatibleType is not derived from `std::istream`,
+ - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
+ constructors),
+ - @a CompatibleType is not a @ref basic_json nested type (e.g.,
+ @ref json_pointer, @ref iterator, etc ...)
+ - @ref @ref json_serializer<U> has a
+ `to_json(basic_json_t&, CompatibleType&&)` method
- @tparam CompatibleArrayType An object type whose `value_type` is
- compatible to @ref array_t. Examples include `std::vector`, `std::deque`,
- `std::list`, `std::forward_list`, `std::array`, `std::set`,
- `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a
- `value_type` from which a @ref basic_json value can be constructed.
+ @tparam U = `uncvref_t<CompatibleType>`
- @param[in] val a value for the array
+ @param[in] val the value to be forwarded to the respective constructor
- @complexity Linear in the size of the passed @a val.
+ @complexity Usually linear in the size of the passed @a val, also
+ depending on the implementation of the called `to_json()`
+ method.
- @throw std::bad_alloc if allocation for array value fails
+ @exceptionsafety Depends on the called constructor. For types directly
+ supported by the library (i.e., all types for which no `to_json()` function
+ was provided), strong guarantee holds: if an exception is thrown, there are
+ no changes to any JSON value.
@liveexample{The following code shows the constructor with several
- compatible array type parameters.,basic_json__CompatibleArrayType}
-
- @sa @ref basic_json(const array_t&) -- create an array value
+ compatible types.,basic_json__CompatibleType}
- @since version 1.0.0
+ @since version 2.1.0
*/
- template <class CompatibleArrayType, typename
- std::enable_if<
- not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
- not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
- not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
- not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
- not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
- not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
- std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
- = 0>
- basic_json(const CompatibleArrayType& val)
- : m_type(value_t::array)
+ template<typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
+ detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
+ not std::is_same<U, basic_json_t>::value and
+ not detail::is_basic_json_nested_type<
+ basic_json_t, U>::value and
+ detail::has_to_json<basic_json, U>::value,
+ int> = 0>
+ basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(
+ std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
{
- using std::begin;
- using std::end;
- m_value.array = create<array_t>(begin(val), end(val));
+ JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
+ assert_invariant();
}
/*!
- @brief create a string (explicit)
-
- Create an string JSON value with a given content.
-
- @param[in] val a value for the string
-
- @complexity Linear in the size of the passed @a val.
-
- @throw std::bad_alloc if allocation for string value fails
-
- @liveexample{The following code shows the constructor with an @ref
- string_t parameter.,basic_json__string_t}
-
- @sa @ref basic_json(const typename string_t::value_type*) -- create a
- string value from a character pointer
- @sa @ref basic_json(const CompatibleStringType&) -- create a string value
- from a compatible string container
-
- @since version 1.0.0
- */
- basic_json(const string_t& val)
- : m_type(value_t::string), m_value(val)
- {}
-
- /*!
- @brief create a string (explicit)
-
- Create a string JSON value with a given content.
-
- @param[in] val a literal value for the string
-
- @complexity Linear in the size of the passed @a val.
-
- @throw std::bad_alloc if allocation for string value fails
-
- @liveexample{The following code shows the constructor with string literal
- parameter.,basic_json__string_t_value_type}
-
- @sa @ref basic_json(const string_t&) -- create a string value
- @sa @ref basic_json(const CompatibleStringType&) -- create a string value
- from a compatible string container
-
- @since version 1.0.0
- */
- basic_json(const typename string_t::value_type* val)
- : basic_json(string_t(val))
- {}
-
- /*!
- @brief create a string (implicit)
-
- Create a string JSON value with a given content.
-
- @param[in] val a value for the string
-
- @tparam CompatibleStringType an string type which is compatible to @ref
- string_t, for instance `std::string`.
-
- @complexity Linear in the size of the passed @a val.
-
- @throw std::bad_alloc if allocation for string value fails
-
- @liveexample{The following code shows the construction of a string value
- from a compatible type.,basic_json__CompatibleStringType}
-
- @sa @ref basic_json(const string_t&) -- create a string value
- @sa @ref basic_json(const typename string_t::value_type*) -- create a
- string value from a character pointer
-
- @since version 1.0.0
- */
- template <class CompatibleStringType, typename
- std::enable_if<
- std::is_constructible<string_t, CompatibleStringType>::value, int>::type
- = 0>
- basic_json(const CompatibleStringType& val)
- : basic_json(string_t(val))
- {}
-
- /*!
- @brief create a boolean (explicit)
-
- Creates a JSON boolean type from a given value.
-
- @param[in] val a boolean value to store
-
- @complexity Constant.
-
- @liveexample{The example below demonstrates boolean
- values.,basic_json__boolean_t}
-
- @since version 1.0.0
- */
- basic_json(boolean_t val) noexcept
- : m_type(value_t::boolean), m_value(val)
- {}
-
- /*!
- @brief create an integer number (explicit)
-
- Create an integer number JSON value with a given content.
-
- @tparam T A helper type to remove this function via SFINAE in case @ref
- number_integer_t is the same as `int`. In this case, this constructor
- would have the same signature as @ref basic_json(const int value). Note
- the helper type @a T is not visible in this constructor's interface.
-
- @param[in] val an integer to create a JSON number from
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of an integer
- number value.,basic_json__number_integer_t}
-
- @sa @ref basic_json(const int) -- create a number value (integer)
- @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number
- value (integer) from a compatible number type
-
- @since version 1.0.0
- */
- template<typename T,
- typename std::enable_if<
- not (std::is_same<T, int>::value)
- and std::is_same<T, number_integer_t>::value
- , int>::type
- = 0>
- basic_json(const number_integer_t val) noexcept
- : m_type(value_t::number_integer), m_value(val)
- {}
-
- /*!
- @brief create an integer number from an enum type (explicit)
-
- Create an integer number JSON value with a given content.
-
- @param[in] val an integer to create a JSON number from
-
- @note This constructor allows to pass enums directly to a constructor. As
- C++ has no way of specifying the type of an anonymous enum explicitly, we
- can only rely on the fact that such values implicitly convert to int. As
- int may already be the same type of number_integer_t, we may need to
- switch off the constructor @ref basic_json(const number_integer_t).
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of an integer
- number value from an anonymous enum.,basic_json__const_int}
-
- @sa @ref basic_json(const number_integer_t) -- create a number value
- (integer)
- @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number
- value (integer) from a compatible number type
-
- @since version 1.0.0
- */
- basic_json(const int val) noexcept
- : m_type(value_t::number_integer),
- m_value(static_cast<number_integer_t>(val))
- {}
-
- /*!
- @brief create an integer number (implicit)
-
- Create an integer number JSON value with a given content. This constructor
- allows any type @a CompatibleNumberIntegerType that can be used to
- construct values of type @ref number_integer_t.
-
- @tparam CompatibleNumberIntegerType An integer type which is compatible to
- @ref number_integer_t. Examples include the types `int`, `int32_t`,
- `long`, and `short`.
-
- @param[in] val an integer to create a JSON number from
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of several integer
- number values from compatible
- types.,basic_json__CompatibleIntegerNumberType}
-
- @sa @ref basic_json(const number_integer_t) -- create a number value
- (integer)
- @sa @ref basic_json(const int) -- create a number value (integer)
-
- @since version 1.0.0
- */
- template<typename CompatibleNumberIntegerType, typename
- std::enable_if<
- std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
- std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
- std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
- CompatibleNumberIntegerType>::type
- = 0>
- basic_json(const CompatibleNumberIntegerType val) noexcept
- : m_type(value_t::number_integer),
- m_value(static_cast<number_integer_t>(val))
- {}
-
- /*!
- @brief create an unsigned integer number (explicit)
-
- Create an unsigned integer number JSON value with a given content.
-
- @tparam T helper type to compare number_unsigned_t and unsigned int
- (not visible in) the interface.
-
- @param[in] val an integer to create a JSON number from
-
- @complexity Constant.
-
- @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number
- value (unsigned integer) from a compatible number type
-
- @since version 2.0.0
- */
- template<typename T,
- typename std::enable_if<
- not (std::is_same<T, int>::value)
- and std::is_same<T, number_unsigned_t>::value
- , int>::type
- = 0>
- basic_json(const number_unsigned_t val) noexcept
- : m_type(value_t::number_unsigned), m_value(val)
- {}
-
- /*!
- @brief create an unsigned number (implicit)
-
- Create an unsigned number JSON value with a given content. This
- constructor allows any type @a CompatibleNumberUnsignedType that can be
- used to construct values of type @ref number_unsigned_t.
-
- @tparam CompatibleNumberUnsignedType An integer type which is compatible
- to @ref number_unsigned_t. Examples may include the types `unsigned int`,
- `uint32_t`, or `unsigned short`.
-
- @param[in] val an unsigned integer to create a JSON number from
-
- @complexity Constant.
-
- @sa @ref basic_json(const number_unsigned_t) -- create a number value
- (unsigned)
-
- @since version 2.0.0
- */
- template <typename CompatibleNumberUnsignedType, typename
- std::enable_if <
- std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
- std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
- not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
- CompatibleNumberUnsignedType>::type
- = 0>
- basic_json(const CompatibleNumberUnsignedType val) noexcept
- : m_type(value_t::number_unsigned),
- m_value(static_cast<number_unsigned_t>(val))
- {}
-
- /*!
- @brief create a floating-point number (explicit)
-
- Create a floating-point number JSON value with a given content.
-
- @param[in] val a floating-point value to create a JSON number from
-
- @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6
- disallows NaN values:
- > Numeric values that cannot be represented in the grammar below (such as
- > Infinity and NaN) are not permitted.
- In case the parameter @a val is not a number, a JSON null value is
- created instead.
-
- @complexity Constant.
-
- @liveexample{The following example creates several floating-point
- values.,basic_json__number_float_t}
-
- @sa @ref basic_json(const CompatibleNumberFloatType) -- create a number
- value (floating-point) from a compatible number type
-
- @since version 1.0.0
- */
- basic_json(const number_float_t val) noexcept
- : m_type(value_t::number_float), m_value(val)
- {
- // replace infinity and NAN by null
- if (not std::isfinite(val))
- {
- m_type = value_t::null;
- m_value = json_value();
- }
- }
-
- /*!
- @brief create an floating-point number (implicit)
-
- Create an floating-point number JSON value with a given content. This
- constructor allows any type @a CompatibleNumberFloatType that can be used
- to construct values of type @ref number_float_t.
-
- @tparam CompatibleNumberFloatType A floating-point type which is
- compatible to @ref number_float_t. Examples may include the types `float`
- or `double`.
-
- @param[in] val a floating-point to create a JSON number from
-
- @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6
- disallows NaN values:
- > Numeric values that cannot be represented in the grammar below (such as
- > Infinity and NaN) are not permitted.
- In case the parameter @a val is not a number, a JSON null value is
- created instead.
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of several
- floating-point number values from compatible
- types.,basic_json__CompatibleNumberFloatType}
-
- @sa @ref basic_json(const number_float_t) -- create a number value
- (floating-point)
-
- @since version 1.0.0
- */
- template<typename CompatibleNumberFloatType, typename = typename
- std::enable_if<
- std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
- std::is_floating_point<CompatibleNumberFloatType>::value>::type
- >
- basic_json(const CompatibleNumberFloatType val) noexcept
- : basic_json(number_float_t(val))
- {}
-
- /*!
@brief create a container (array or object) from an initializer list
Creates a JSON value of type array or object from the passed initializer
@@ -1558,29 +8456,29 @@ class basic_json
1. If the list is empty, an empty JSON object value `{}` is created.
2. If the list consists of pairs whose first element is a string, a JSON
- object value is created where the first elements of the pairs are treated
- as keys and the second elements are as values.
+ object value is created where the first elements of the pairs are
+ treated as keys and the second elements are as values.
3. In all other cases, an array is created.
The rules aim to create the best fit between a C++ initializer list and
JSON values. The rationale is as follows:
1. The empty initializer list is written as `{}` which is exactly an empty
- JSON object.
- 2. C++ has now way of describing mapped types other than to list a list of
- pairs. As JSON requires that keys must be of type string, rule 2 is the
- weakest constraint one can pose on initializer lists to interpret them as
- an object.
+ JSON object.
+ 2. C++ has no way of describing mapped types other than to list a list of
+ pairs. As JSON requires that keys must be of type string, rule 2 is the
+ weakest constraint one can pose on initializer lists to interpret them
+ as an object.
3. In all other cases, the initializer list could not be interpreted as
- JSON object type, so interpreting it as JSON array type is safe.
+ JSON object type, so interpreting it as JSON array type is safe.
With the rules described above, the following JSON values cannot be
expressed by an initializer list:
- - the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)
+ - the empty array (`[]`): use @ref array(initializer_list_t)
with an empty initializer list in this case
- arrays whose elements satisfy rule 2: use @ref
- array(std::initializer_list<basic_json>) with the same initializer list
+ array(initializer_list_t) with the same initializer list
in this case
@note When used without parentheses around an empty initializer list, @ref
@@ -1592,51 +8490,47 @@ class basic_json
@param[in] type_deduction internal parameter; when set to `true`, the type
of the JSON value is deducted from the initializer list @a init; when set
to `false`, the type provided via @a manual_type is forced. This mode is
- used by the functions @ref array(std::initializer_list<basic_json>) and
- @ref object(std::initializer_list<basic_json>).
+ used by the functions @ref array(initializer_list_t) and
+ @ref object(initializer_list_t).
@param[in] manual_type internal parameter; when @a type_deduction is set
to `false`, the created JSON value will use the provided type (only @ref
value_t::array and @ref value_t::object are valid); when @a type_deduction
is set to `true`, this parameter has no effect
- @throw std::domain_error if @a type_deduction is `false`, @a manual_type
- is `value_t::object`, but @a init contains an element which is not a pair
- whose first element is a string; example: `"cannot create object from
- initializer list"`
+ @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
+ `value_t::object`, but @a init contains an element which is not a pair
+ whose first element is a string. In this case, the constructor could not
+ create an object. If @a type_deduction would have be `true`, an array
+ would have been created. See @ref object(initializer_list_t)
+ for an example.
@complexity Linear in the size of the initializer list @a init.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
@liveexample{The example below shows how JSON values are created from
initializer lists.,basic_json__list_init_t}
- @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array
+ @sa @ref array(initializer_list_t) -- create a JSON array
value from an initializer list
- @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object
+ @sa @ref object(initializer_list_t) -- create a JSON object
value from an initializer list
@since version 1.0.0
*/
- basic_json(std::initializer_list<basic_json> init,
+ basic_json(initializer_list_t init,
bool type_deduction = true,
value_t manual_type = value_t::array)
{
- // the initializer list could describe an object
- bool is_an_object = true;
-
// check if each element is an array with two elements whose first
// element is a string
- for (const auto& element : init)
+ bool is_an_object = std::all_of(init.begin(), init.end(),
+ [](const detail::json_ref<basic_json>& element_ref)
{
- if (not element.is_array() or element.size() != 2
- or not element[0].is_string())
- {
- // we found an element that makes it impossible to use the
- // initializer list as object
- is_an_object = false;
- break;
- }
- }
+ return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
+ });
// adjust type if type deduction is not wanted
if (not type_deduction)
@@ -1648,9 +8542,9 @@ class basic_json
}
// if object is wanted but impossible, throw an exception
- if (manual_type == value_t::object and not is_an_object)
+ if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
{
- throw std::domain_error("cannot create object from initializer list");
+ JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
}
}
@@ -1660,19 +8554,22 @@ class basic_json
m_type = value_t::object;
m_value = value_t::object;
- assert(m_value.object != nullptr);
-
- for (auto& element : init)
+ std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
{
- m_value.object->emplace(*(element[0].m_value.string), element[1]);
- }
+ auto element = element_ref.moved_or_copied();
+ m_value.object->emplace(
+ std::move(*((*element.m_value.array)[0].m_value.string)),
+ std::move((*element.m_value.array)[1]));
+ });
}
else
{
// the initializer list describes an array -> create array
m_type = value_t::array;
- m_value.array = create<array_t>(init);
+ m_value.array = create<array_t>(init.begin(), init.end());
}
+
+ assert_invariant();
}
/*!
@@ -1684,7 +8581,7 @@ class basic_json
@note This function is only needed to express two edge cases that cannot
be realized with the initializer list constructor (@ref
- basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases
+ basic_json(initializer_list_t, bool, value_t)). These cases
are:
1. creating an array whose elements are all pairs whose first element is a
string -- in this case, the initializer list constructor would create an
@@ -1699,18 +8596,20 @@ class basic_json
@complexity Linear in the size of @a init.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
@liveexample{The following code shows an example for the `array`
function.,array}
- @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --
+ @sa @ref basic_json(initializer_list_t, bool, value_t) --
create a JSON value from an initializer list
- @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object
+ @sa @ref object(initializer_list_t) -- create a JSON object
value from an initializer list
@since version 1.0.0
*/
- static basic_json array(std::initializer_list<basic_json> init =
- std::initializer_list<basic_json>())
+ static basic_json array(initializer_list_t init = {})
{
return basic_json(init, false, value_t::array);
}
@@ -1723,34 +8622,37 @@ class basic_json
the initializer list is empty, the empty object `{}` is created.
@note This function is only added for symmetry reasons. In contrast to the
- related function @ref array(std::initializer_list<basic_json>), there are
+ related function @ref array(initializer_list_t), there are
no cases which can only be expressed by this function. That is, any
initializer list @a init can also be passed to the initializer list
- constructor @ref basic_json(std::initializer_list<basic_json>, bool,
- value_t).
+ constructor @ref basic_json(initializer_list_t, bool, value_t).
@param[in] init initializer list to create an object from (optional)
@return JSON object value
- @throw std::domain_error if @a init is not a pair whose first elements are
- strings; thrown by
- @ref basic_json(std::initializer_list<basic_json>, bool, value_t)
+ @throw type_error.301 if @a init is not a list of pairs whose first
+ elements are strings. In this case, no object can be created. When such a
+ value is passed to @ref basic_json(initializer_list_t, bool, value_t),
+ an array would have been created from the passed initializer list @a init.
+ See example below.
@complexity Linear in the size of @a init.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
@liveexample{The following code shows an example for the `object`
function.,object}
- @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --
+ @sa @ref basic_json(initializer_list_t, bool, value_t) --
create a JSON value from an initializer list
- @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array
+ @sa @ref array(initializer_list_t) -- create a JSON array
value from an initializer list
@since version 1.0.0
*/
- static basic_json object(std::initializer_list<basic_json> init =
- std::initializer_list<basic_json>())
+ static basic_json object(initializer_list_t init = {})
{
return basic_json(init, false, value_t::object);
}
@@ -1759,14 +8661,18 @@ class basic_json
@brief construct an array with count copies of given value
Constructs a JSON array value by creating @a cnt copies of a passed value.
- In case @a cnt is `0`, an empty array is created. As postcondition,
- `std::distance(begin(),end()) == cnt` holds.
+ In case @a cnt is `0`, an empty array is created.
@param[in] cnt the number of JSON copies of @a val to create
@param[in] val the JSON value to copy
+ @post `std::distance(begin(),end()) == cnt` holds.
+
@complexity Linear in @a cnt.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
@liveexample{The following code shows examples for the @ref
basic_json(size_type\, const basic_json&)
constructor.,basic_json__size_type_basic_json}
@@ -1777,6 +8683,7 @@ class basic_json
: m_type(value_t::array)
{
m_value.array = create<array_t>(cnt, val);
+ assert_invariant();
}
/*!
@@ -1784,12 +8691,13 @@ class basic_json
Constructs the JSON value with the contents of the range `[first, last)`.
The semantics depends on the different types a JSON value can have:
- - In case of primitive types (number, boolean, or string), @a first must
- be `begin()` and @a last must be `end()`. In this case, the value is
- copied. Otherwise, std::out_of_range is thrown.
+ - In case of a null type, invalid_iterator.206 is thrown.
+ - In case of other primitive types (number, boolean, or string), @a first
+ must be `begin()` and @a last must be `end()`. In this case, the value is
+ copied. Otherwise, invalid_iterator.204 is thrown.
- In case of structured types (array, object), the constructor behaves as
- similar versions for `std::vector`.
- - In case of a null type, std::domain_error is thrown.
+ similar versions for `std::vector` or `std::map`; that is, a JSON array
+ or object is constructed from the values in the range.
@tparam InputIT an input iterator type (@ref iterator or @ref
const_iterator)
@@ -1797,36 +8705,59 @@ class basic_json
@param[in] first begin of the range to copy from (included)
@param[in] last end of the range to copy from (excluded)
- @throw std::domain_error if iterators are not compatible; that is, do not
- belong to the same JSON value; example: `"iterators are not compatible"`
- @throw std::out_of_range if iterators are for a primitive type (number,
- boolean, or string) where an out of range error can be detected easily;
- example: `"iterators out of range"`
- @throw std::bad_alloc if allocation for object, array, or string fails
- @throw std::domain_error if called with a null value; example: `"cannot
- use construct with iterators from null"`
+ @pre Iterators @a first and @a last must be initialized. **This
+ precondition is enforced with an assertion (see warning).** If
+ assertions are switched off, a violation of this precondition yields
+ undefined behavior.
+
+ @pre Range `[first, last)` is valid. Usually, this precondition cannot be
+ checked efficiently. Only certain edge cases are detected; see the
+ description of the exceptions below. A violation of this precondition
+ yields undefined behavior.
+
+ @warning A precondition is enforced with a runtime assertion that will
+ result in calling `std::abort` if this precondition is not met.
+ Assertions can be disabled by defining `NDEBUG` at compile time.
+ See http://en.cppreference.com/w/cpp/error/assert for more
+ information.
+
+ @throw invalid_iterator.201 if iterators @a first and @a last are not
+ compatible (i.e., do not belong to the same JSON value). In this case,
+ the range `[first, last)` is undefined.
+ @throw invalid_iterator.204 if iterators @a first and @a last belong to a
+ primitive type (number, boolean, or string), but @a first does not point
+ to the first element any more. In this case, the range `[first, last)` is
+ undefined. See example code below.
+ @throw invalid_iterator.206 if iterators @a first and @a last belong to a
+ null value. In this case, the range `[first, last)` is undefined.
@complexity Linear in distance between @a first and @a last.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
@liveexample{The example below shows several ways to create JSON values by
specifying a subrange with iterators.,basic_json__InputIt_InputIt}
@since version 1.0.0
*/
- template <class InputIT, typename
- std::enable_if<
- std::is_same<InputIT, typename basic_json_t::iterator>::value or
- std::is_same<InputIT, typename basic_json_t::const_iterator>::value
- , int>::type
- = 0>
- basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
+ template<class InputIT, typename std::enable_if<
+ std::is_same<InputIT, typename basic_json_t::iterator>::value or
+ std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
+ basic_json(InputIT first, InputIT last)
{
+ assert(first.m_object != nullptr);
+ assert(last.m_object != nullptr);
+
// make sure iterator fits the current value
- if (first.m_object != last.m_object)
+ if (JSON_UNLIKELY(first.m_object != last.m_object))
{
- throw std::domain_error("iterators are not compatible");
+ JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
}
+ // copy type from first iterator
+ m_type = first.m_object->m_type;
+
// check if iterator range is complete for primitive values
switch (m_type)
{
@@ -1836,105 +8767,82 @@ class basic_json
case value_t::number_unsigned:
case value_t::string:
{
- if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
+ if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
+ or not last.m_it.primitive_iterator.is_end()))
{
- throw std::out_of_range("iterators out of range");
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
}
break;
}
default:
- {
break;
- }
}
switch (m_type)
{
case value_t::number_integer:
{
- assert(first.m_object != nullptr);
m_value.number_integer = first.m_object->m_value.number_integer;
break;
}
case value_t::number_unsigned:
{
- assert(first.m_object != nullptr);
m_value.number_unsigned = first.m_object->m_value.number_unsigned;
break;
}
case value_t::number_float:
{
- assert(first.m_object != nullptr);
m_value.number_float = first.m_object->m_value.number_float;
break;
}
case value_t::boolean:
{
- assert(first.m_object != nullptr);
m_value.boolean = first.m_object->m_value.boolean;
break;
}
case value_t::string:
{
- assert(first.m_object != nullptr);
m_value = *first.m_object->m_value.string;
break;
}
case value_t::object:
{
- m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
+ m_value.object = create<object_t>(first.m_it.object_iterator,
+ last.m_it.object_iterator);
break;
}
case value_t::array:
{
- m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
+ m_value.array = create<array_t>(first.m_it.array_iterator,
+ last.m_it.array_iterator);
break;
}
default:
- {
- assert(first.m_object != nullptr);
- throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
- }
+ JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
+ std::string(first.m_object->type_name())));
}
- }
-
- /*!
- @brief construct a JSON value given an input stream
-
- @param[in,out] i stream to read a serialized JSON value from
- @param[in] cb a parser callback function of type @ref parser_callback_t
- which is used to control the deserialization by filtering unwanted values
- (optional)
-
- @complexity Linear in the length of the input. The parser is a predictive
- LL(1) parser. The complexity can be higher if the parser callback function
- @a cb has a super-linear complexity.
- @note A UTF-8 byte order mark is silently ignored.
-
- @liveexample{The example below demonstrates constructing a JSON value from
- a `std::stringstream` with and without callback
- function.,basic_json__istream}
-
- @since version 2.0.0
- */
- explicit basic_json(std::istream& i, parser_callback_t cb = nullptr)
- {
- *this = parser(i, cb).parse();
+ assert_invariant();
}
+
///////////////////////////////////////
// other constructors and destructor //
///////////////////////////////////////
+ /// @private
+ basic_json(const detail::json_ref<basic_json>& ref)
+ : basic_json(ref.moved_or_copied())
+ {}
+
/*!
@brief copy constructor
@@ -1942,16 +8850,19 @@ class basic_json
@param[in] other the JSON value to copy
+ @post `*this == other`
+
@complexity Linear in the size of @a other.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
@requirement This function helps `basic_json` satisfying the
[Container](http://en.cppreference.com/w/cpp/concept/Container)
requirements:
- The complexity is linear.
- As postcondition, it holds: `other == basic_json(other)`.
- @throw std::bad_alloc if allocation for object, array, or string fails.
-
@liveexample{The following code shows an example for the copy
constructor.,basic_json__basic_json}
@@ -1960,25 +8871,25 @@ class basic_json
basic_json(const basic_json& other)
: m_type(other.m_type)
{
+ // check of passed value is valid
+ other.assert_invariant();
+
switch (m_type)
{
case value_t::object:
{
- assert(other.m_value.object != nullptr);
m_value = *other.m_value.object;
break;
}
case value_t::array:
{
- assert(other.m_value.array != nullptr);
m_value = *other.m_value.array;
break;
}
case value_t::string:
{
- assert(other.m_value.string != nullptr);
m_value = *other.m_value.string;
break;
}
@@ -2008,10 +8919,10 @@ class basic_json
}
default:
- {
break;
- }
}
+
+ assert_invariant();
}
/*!
@@ -2023,10 +8934,18 @@ class basic_json
@param[in,out] other value to move to this object
- @post @a other is a JSON null value
+ @post `*this` has the same value as @a other before the call.
+ @post @a other is a JSON null value.
@complexity Constant.
+ @exceptionsafety No-throw guarantee: this constructor never throws
+ exceptions.
+
+ @requirement This function helps `basic_json` satisfying the
+ [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible)
+ requirements.
+
@liveexample{The code below shows the move constructor explicitly called
via std::move.,basic_json__moveconstructor}
@@ -2036,9 +8955,14 @@ class basic_json
: m_type(std::move(other.m_type)),
m_value(std::move(other.m_value))
{
+ // check that passed value is valid
+ other.assert_invariant();
+
// invalidate payload
other.m_type = value_t::null;
other.m_value = {};
+
+ assert_invariant();
}
/*!
@@ -2046,7 +8970,7 @@ class basic_json
Copy assignment operator. Copies a JSON value via the "copy and swap"
strategy: It is expressed in terms of the copy constructor, destructor,
- and the swap() member function.
+ and the `swap()` member function.
@param[in] other value to copy from
@@ -2071,9 +8995,14 @@ class basic_json
std::is_nothrow_move_assignable<json_value>::value
)
{
+ // check that passed value is valid
+ other.assert_invariant();
+
using std::swap;
swap(m_type, other.m_type);
swap(m_value, other.m_value);
+
+ assert_invariant();
return *this;
}
@@ -2094,38 +9023,8 @@ class basic_json
*/
~basic_json()
{
- switch (m_type)
- {
- case value_t::object:
- {
- AllocatorType<object_t> alloc;
- alloc.destroy(m_value.object);
- alloc.deallocate(m_value.object, 1);
- break;
- }
-
- case value_t::array:
- {
- AllocatorType<array_t> alloc;
- alloc.destroy(m_value.array);
- alloc.deallocate(m_value.array, 1);
- break;
- }
-
- case value_t::string:
- {
- AllocatorType<string_t> alloc;
- alloc.destroy(m_value.string);
- alloc.deallocate(m_value.string, 1);
- break;
- }
-
- default:
- {
- // all other types need no specific destructor
- break;
- }
- }
+ assert_invariant();
+ m_value.destroy(m_type);
}
/// @}
@@ -2136,45 +9035,61 @@ class basic_json
///////////////////////
/// @name object inspection
+ /// Functions to inspect the type of a JSON value.
/// @{
/*!
@brief serialization
Serialization function for JSON values. The function tries to mimic
- Python's @p json.dumps() function, and currently supports its @p indent
- parameter.
+ Python's `json.dumps()` function, and currently supports its @a indent
+ and @a ensure_ascii parameters.
- @param[in] indent if indent is nonnegative, then array elements and object
+ @param[in] indent If indent is nonnegative, then array elements and object
members will be pretty-printed with that indent level. An indent level of
- 0 will only insert newlines. -1 (the default) selects the most compact
- representation
+ `0` will only insert newlines. `-1` (the default) selects the most compact
+ representation.
+ @param[in] indent_char The character to use for indentation if @a indent is
+ greater than `0`. The default is ` ` (space).
+ @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+ in the output are escaped with `\uXXXX` sequences, and the result consists
+ of ASCII characters only.
@return string containing the serialization of the JSON value
+ @throw type_error.316 if a string stored inside the JSON value is not
+ UTF-8 encoded
+
@complexity Linear.
- @liveexample{The following example shows the effect of different @a indent
- parameters to the result of the serialization.,dump}
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @liveexample{The following example shows the effect of different @a indent\,
+ @a indent_char\, and @a ensure_ascii parameters to the result of the
+ serialization.,dump}
@see https://docs.python.org/2/library/json.html#json.dump
- @since version 1.0.0
+ @since version 1.0.0; indentation character @a indent_char, option
+ @a ensure_ascii and exceptions added in version 3.0.0
*/
- string_t dump(const int indent = -1) const
+ string_t dump(const int indent = -1, const char indent_char = ' ',
+ const bool ensure_ascii = false) const
{
- std::stringstream ss;
+ string_t result;
+ serializer s(detail::output_adapter<char>(result), indent_char);
if (indent >= 0)
{
- dump(ss, true, static_cast<unsigned int>(indent));
+ s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
}
else
{
- dump(ss, false, 0);
+ s.dump(*this, false, ensure_ascii, 0);
}
- return ss.str();
+ return result;
}
/*!
@@ -2184,6 +9099,17 @@ class basic_json
enumeration.
@return the type of the JSON value
+ Value type | return value
+ ------------------------- | -------------------------
+ null | value_t::null
+ boolean | value_t::boolean
+ string | value_t::string
+ number (integer) | value_t::number_integer
+ number (unsigned integer) | value_t::number_unsigned
+ number (floating-point) | value_t::number_float
+ object | value_t::object
+ array | value_t::array
+ discarded | value_t::discarded
@complexity Constant.
@@ -2193,6 +9119,9 @@ class basic_json
@liveexample{The following code exemplifies `type()` for all JSON
types.,type}
+ @sa @ref operator value_t() -- return the type of the JSON value (implicit)
+ @sa @ref type_name() -- return the type as string
+
@since version 1.0.0
*/
constexpr value_t type() const noexcept
@@ -2203,8 +9132,8 @@ class basic_json
/*!
@brief return whether type is primitive
- This function returns true iff the JSON type is primitive (string, number,
- boolean, or null).
+ This function returns true if and only if the JSON type is primitive
+ (string, number, boolean, or null).
@return `true` if type is primitive (string, number, boolean, or null),
`false` otherwise.
@@ -2233,8 +9162,8 @@ class basic_json
/*!
@brief return whether type is structured
- This function returns true iff the JSON type is structured (array or
- object).
+ This function returns true if and only if the JSON type is structured
+ (array or object).
@return `true` if type is structured (array or object), `false` otherwise.
@@ -2260,7 +9189,7 @@ class basic_json
/*!
@brief return whether value is null
- This function returns true iff the JSON value is null.
+ This function returns true if and only if the JSON value is null.
@return `true` if type is null, `false` otherwise.
@@ -2276,13 +9205,13 @@ class basic_json
*/
constexpr bool is_null() const noexcept
{
- return m_type == value_t::null;
+ return (m_type == value_t::null);
}
/*!
@brief return whether value is a boolean
- This function returns true iff the JSON value is a boolean.
+ This function returns true if and only if the JSON value is a boolean.
@return `true` if type is boolean, `false` otherwise.
@@ -2298,14 +9227,14 @@ class basic_json
*/
constexpr bool is_boolean() const noexcept
{
- return m_type == value_t::boolean;
+ return (m_type == value_t::boolean);
}
/*!
@brief return whether value is a number
- This function returns true iff the JSON value is a number. This includes
- both integer and floating-point values.
+ This function returns true if and only if the JSON value is a number. This
+ includes both integer (signed and unsigned) and floating-point values.
@return `true` if type is number (regardless whether integer, unsigned
integer or floating-type), `false` otherwise.
@@ -2334,8 +9263,8 @@ class basic_json
/*!
@brief return whether value is an integer number
- This function returns true iff the JSON value is an integer or unsigned
- integer number. This excludes floating-point values.
+ This function returns true if and only if the JSON value is a signed or
+ unsigned integer number. This excludes floating-point values.
@return `true` if type is an integer or unsigned integer number, `false`
otherwise.
@@ -2357,14 +9286,14 @@ class basic_json
*/
constexpr bool is_number_integer() const noexcept
{
- return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
+ return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
}
/*!
@brief return whether value is an unsigned integer number
- This function returns true iff the JSON value is an unsigned integer
- number. This excludes floating-point and (signed) integer values.
+ This function returns true if and only if the JSON value is an unsigned
+ integer number. This excludes floating-point and signed integer values.
@return `true` if type is an unsigned integer number, `false` otherwise.
@@ -2385,14 +9314,14 @@ class basic_json
*/
constexpr bool is_number_unsigned() const noexcept
{
- return m_type == value_t::number_unsigned;
+ return (m_type == value_t::number_unsigned);
}
/*!
@brief return whether value is a floating-point number
- This function returns true iff the JSON value is a floating-point number.
- This excludes integer and unsigned integer values.
+ This function returns true if and only if the JSON value is a
+ floating-point number. This excludes signed and unsigned integer values.
@return `true` if type is a floating-point number, `false` otherwise.
@@ -2413,13 +9342,13 @@ class basic_json
*/
constexpr bool is_number_float() const noexcept
{
- return m_type == value_t::number_float;
+ return (m_type == value_t::number_float);
}
/*!
@brief return whether value is an object
- This function returns true iff the JSON value is an object.
+ This function returns true if and only if the JSON value is an object.
@return `true` if type is object, `false` otherwise.
@@ -2435,13 +9364,13 @@ class basic_json
*/
constexpr bool is_object() const noexcept
{
- return m_type == value_t::object;
+ return (m_type == value_t::object);
}
/*!
@brief return whether value is an array
- This function returns true iff the JSON value is an array.
+ This function returns true if and only if the JSON value is an array.
@return `true` if type is array, `false` otherwise.
@@ -2457,13 +9386,13 @@ class basic_json
*/
constexpr bool is_array() const noexcept
{
- return m_type == value_t::array;
+ return (m_type == value_t::array);
}
/*!
@brief return whether value is a string
- This function returns true iff the JSON value is a string.
+ This function returns true if and only if the JSON value is a string.
@return `true` if type is string, `false` otherwise.
@@ -2479,14 +9408,14 @@ class basic_json
*/
constexpr bool is_string() const noexcept
{
- return m_type == value_t::string;
+ return (m_type == value_t::string);
}
/*!
@brief return whether value is discarded
- This function returns true iff the JSON value was discarded during parsing
- with a callback function (see @ref parser_callback_t).
+ This function returns true if and only if the JSON value was discarded
+ during parsing with a callback function (see @ref parser_callback_t).
@note This function will always be `false` for JSON values after parsing.
That is, discarded values can only occur during parsing, but will be
@@ -2506,7 +9435,7 @@ class basic_json
*/
constexpr bool is_discarded() const noexcept
{
- return m_type == value_t::discarded;
+ return (m_type == value_t::discarded);
}
/*!
@@ -2525,6 +9454,9 @@ class basic_json
@liveexample{The following code exemplifies the @ref value_t operator for
all JSON types.,operator__value_t}
+ @sa @ref type() -- return the type of the JSON value (explicit)
+ @sa @ref type_name() -- return the type as string
+
@since version 1.0.0
*/
constexpr operator value_t() const noexcept
@@ -2539,263 +9471,97 @@ class basic_json
// value access //
//////////////////
- /// get an object (explicit)
- template <class T, typename
- std::enable_if<
- std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
- std::is_convertible<basic_json_t, typename T::mapped_type>::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- if (is_object())
- {
- assert(m_value.object != nullptr);
- return T(m_value.object->begin(), m_value.object->end());
- }
- else
- {
- throw std::domain_error("type must be object, but is " + type_name());
- }
- }
-
- /// get an object (explicit)
- object_t get_impl(object_t*) const
- {
- if (is_object())
- {
- assert(m_value.object != nullptr);
- return *(m_value.object);
- }
- else
- {
- throw std::domain_error("type must be object, but is " + type_name());
- }
- }
-
- /// get an array (explicit)
- template <class T, typename
- std::enable_if<
- std::is_convertible<basic_json_t, typename T::value_type>::value and
- not std::is_same<basic_json_t, typename T::value_type>::value and
- not std::is_arithmetic<T>::value and
- not std::is_convertible<std::string, T>::value and
- not has_mapped_type<T>::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- if (is_array())
- {
- T to_vector;
- assert(m_value.array != nullptr);
- std::transform(m_value.array->begin(), m_value.array->end(),
- std::inserter(to_vector, to_vector.end()), [](basic_json i)
- {
- return i.get<typename T::value_type>();
- });
- return to_vector;
- }
- else
- {
- throw std::domain_error("type must be array, but is " + type_name());
- }
- }
-
- /// get an array (explicit)
- template <class T, typename
- std::enable_if<
- std::is_convertible<basic_json_t, T>::value and
- not std::is_same<basic_json_t, T>::value
- , int>::type = 0>
- std::vector<T> get_impl(std::vector<T>*) const
- {
- if (is_array())
- {
- std::vector<T> to_vector;
- assert(m_value.array != nullptr);
- to_vector.reserve(m_value.array->size());
- std::transform(m_value.array->begin(), m_value.array->end(),
- std::inserter(to_vector, to_vector.end()), [](basic_json i)
- {
- return i.get<T>();
- });
- return to_vector;
- }
- else
- {
- throw std::domain_error("type must be array, but is " + type_name());
- }
- }
-
- /// get an array (explicit)
- template <class T, typename
- std::enable_if<
- std::is_same<basic_json, typename T::value_type>::value and
- not has_mapped_type<T>::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- if (is_array())
- {
- assert(m_value.array != nullptr);
- return T(m_value.array->begin(), m_value.array->end());
- }
- else
- {
- throw std::domain_error("type must be array, but is " + type_name());
- }
- }
-
- /// get an array (explicit)
- array_t get_impl(array_t*) const
- {
- if (is_array())
- {
- assert(m_value.array != nullptr);
- return *(m_value.array);
- }
- else
- {
- throw std::domain_error("type must be array, but is " + type_name());
- }
- }
-
- /// get a string (explicit)
- template <typename T, typename
- std::enable_if<
- std::is_convertible<string_t, T>::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- if (is_string())
- {
- assert(m_value.string != nullptr);
- return *m_value.string;
- }
- else
- {
- throw std::domain_error("type must be string, but is " + type_name());
- }
- }
-
- /// get a number (explicit)
- template<typename T, typename
- std::enable_if<
- std::is_arithmetic<T>::value
- , int>::type = 0>
- T get_impl(T*) const
+ /// get a boolean (explicit)
+ boolean_t get_impl(boolean_t* /*unused*/) const
{
- switch (m_type)
+ if (JSON_LIKELY(is_boolean()))
{
- case value_t::number_integer:
- {
- return static_cast<T>(m_value.number_integer);
- }
-
- case value_t::number_unsigned:
- {
- return static_cast<T>(m_value.number_unsigned);
- }
-
- case value_t::number_float:
- {
- return static_cast<T>(m_value.number_float);
- }
-
- default:
- {
- throw std::domain_error("type must be number, but is " + type_name());
- }
+ return m_value.boolean;
}
- }
- /// get a boolean (explicit)
- constexpr boolean_t get_impl(boolean_t*) const
- {
- return is_boolean()
- ? m_value.boolean
- : throw std::domain_error("type must be boolean, but is " + type_name());
+ JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
}
/// get a pointer to the value (object)
- object_t* get_impl_ptr(object_t*) noexcept
+ object_t* get_impl_ptr(object_t* /*unused*/) noexcept
{
return is_object() ? m_value.object : nullptr;
}
/// get a pointer to the value (object)
- constexpr const object_t* get_impl_ptr(const object_t*) const noexcept
+ constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
{
return is_object() ? m_value.object : nullptr;
}
/// get a pointer to the value (array)
- array_t* get_impl_ptr(array_t*) noexcept
+ array_t* get_impl_ptr(array_t* /*unused*/) noexcept
{
return is_array() ? m_value.array : nullptr;
}
/// get a pointer to the value (array)
- constexpr const array_t* get_impl_ptr(const array_t*) const noexcept
+ constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
{
return is_array() ? m_value.array : nullptr;
}
/// get a pointer to the value (string)
- string_t* get_impl_ptr(string_t*) noexcept
+ string_t* get_impl_ptr(string_t* /*unused*/) noexcept
{
return is_string() ? m_value.string : nullptr;
}
/// get a pointer to the value (string)
- constexpr const string_t* get_impl_ptr(const string_t*) const noexcept
+ constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
{
return is_string() ? m_value.string : nullptr;
}
/// get a pointer to the value (boolean)
- boolean_t* get_impl_ptr(boolean_t*) noexcept
+ boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
{
return is_boolean() ? &m_value.boolean : nullptr;
}
/// get a pointer to the value (boolean)
- constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
+ constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
{
return is_boolean() ? &m_value.boolean : nullptr;
}
/// get a pointer to the value (integer number)
- number_integer_t* get_impl_ptr(number_integer_t*) noexcept
+ number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
{
return is_number_integer() ? &m_value.number_integer : nullptr;
}
/// get a pointer to the value (integer number)
- constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
+ constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
{
return is_number_integer() ? &m_value.number_integer : nullptr;
}
/// get a pointer to the value (unsigned number)
- number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
+ number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
{
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
}
/// get a pointer to the value (unsigned number)
- constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept
+ constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
{
return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
}
/// get a pointer to the value (floating-point number)
- number_float_t* get_impl_ptr(number_float_t*) noexcept
+ number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
{
return is_number_float() ? &m_value.number_float : nullptr;
}
/// get a pointer to the value (floating-point number)
- constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
+ constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
{
return is_number_float() ? &m_value.number_float : nullptr;
}
@@ -2803,52 +9569,84 @@ class basic_json
/*!
@brief helper function to implement get_ref()
- This funcion helps to implement get_ref() without code duplication for
+ This function helps to implement get_ref() without code duplication for
const and non-const overloads
@tparam ThisType will be deduced as `basic_json` or `const basic_json`
- @throw std::domain_error if ReferenceType does not match underlying value
+ @throw type_error.303 if ReferenceType does not match underlying value
type of the current JSON
*/
template<typename ReferenceType, typename ThisType>
static ReferenceType get_ref_impl(ThisType& obj)
{
// delegate the call to get_ptr<>()
- using PointerType = typename std::add_pointer<ReferenceType>::type;
- auto ptr = obj.template get_ptr<PointerType>();
+ auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
- if (ptr != nullptr)
+ if (JSON_LIKELY(ptr != nullptr))
{
return *ptr;
}
- else
- {
- throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " +
- obj.type_name());
- }
+
+ JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
}
public:
-
/// @name value access
+ /// Direct access to the stored value of a JSON value.
/// @{
/*!
+ @brief get special-case overload
+
+ This overloads avoids a lot of template boilerplate, it can be seen as the
+ identity method
+
+ @tparam BasicJsonType == @ref basic_json
+
+ @return a copy of *this
+
+ @complexity Constant.
+
+ @since version 2.1.0
+ */
+ template<typename BasicJsonType, detail::enable_if_t<
+ std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
+ int> = 0>
+ basic_json get() const
+ {
+ return *this;
+ }
+
+ /*!
@brief get a value (explicit)
- Explicit type conversion between the JSON value and a compatible value.
+ Explicit type conversion between the JSON value and a compatible value
+ which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
+ and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
+ The value is converted by calling the @ref json_serializer<ValueType>
+ `from_json()` method.
- @tparam ValueType non-pointer type compatible to the JSON value, for
- instance `int` for JSON integer numbers, `bool` for JSON booleans, or
- `std::vector` types for JSON arrays
+ The function is equivalent to executing
+ @code {.cpp}
+ ValueType ret;
+ JSONSerializer<ValueType>::from_json(*this, ret);
+ return ret;
+ @endcode
- @return copy of the JSON value, converted to type @a ValueType
+ This overloads is chosen if:
+ - @a ValueType is not @ref basic_json,
+ - @ref json_serializer<ValueType> has a `from_json()` method of the form
+ `void from_json(const basic_json&, ValueType&)`, and
+ - @ref json_serializer<ValueType> does not have a `from_json()` method of
+ the form `ValueType from_json(const basic_json&)`
- @throw std::domain_error in case passed type @a ValueType is incompatible
- to JSON; example: `"type must be object, but is null"`
+ @tparam ValueTypeCV the provided value type
+ @tparam ValueType the returned value type
- @complexity Linear in the size of the JSON value.
+ @return copy of the JSON value, converted to @a ValueType
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws
@liveexample{The example below shows several conversions from JSON values
to other types. There a few things to note: (1) Floating-point numbers can
@@ -2857,23 +9655,71 @@ class basic_json
associative containers such as `std::unordered_map<std::string\,
json>`.,get__ValueType_const}
- @internal
- The idea of using a casted null pointer to choose the correct
- implementation is from <http://stackoverflow.com/a/8315197/266378>.
- @endinternal
+ @since version 2.1.0
+ */
+ template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
+ detail::enable_if_t <
+ not std::is_same<basic_json_t, ValueType>::value and
+ detail::has_from_json<basic_json_t, ValueType>::value and
+ not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+ int> = 0>
+ ValueType get() const noexcept(noexcept(
+ JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
+ {
+ // we cannot static_assert on ValueTypeCV being non-const, because
+ // there is support for get<const basic_json_t>(), which is why we
+ // still need the uncvref
+ static_assert(not std::is_reference<ValueTypeCV>::value,
+ "get() cannot be used with reference types, you might want to use get_ref()");
+ static_assert(std::is_default_constructible<ValueType>::value,
+ "types must be DefaultConstructible when used with get()");
- @sa @ref operator ValueType() const for implicit conversion
- @sa @ref get() for pointer-member access
+ ValueType ret;
+ JSONSerializer<ValueType>::from_json(*this, ret);
+ return ret;
+ }
- @since version 1.0.0
+ /*!
+ @brief get a value (explicit); special case
+
+ Explicit type conversion between the JSON value and a compatible value
+ which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
+ and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
+ The value is converted by calling the @ref json_serializer<ValueType>
+ `from_json()` method.
+
+ The function is equivalent to executing
+ @code {.cpp}
+ return JSONSerializer<ValueTypeCV>::from_json(*this);
+ @endcode
+
+ This overloads is chosen if:
+ - @a ValueType is not @ref basic_json and
+ - @ref json_serializer<ValueType> has a `from_json()` method of the form
+ `ValueType from_json(const basic_json&)`
+
+ @note If @ref json_serializer<ValueType> has both overloads of
+ `from_json()`, this one is chosen.
+
+ @tparam ValueTypeCV the provided value type
+ @tparam ValueType the returned value type
+
+ @return copy of the JSON value, converted to @a ValueType
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+ @since version 2.1.0
*/
- template<typename ValueType, typename
- std::enable_if<
- not std::is_pointer<ValueType>::value
- , int>::type = 0>
- ValueType get() const
+ template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
+ detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
+ detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+ int> = 0>
+ ValueType get() const noexcept(noexcept(
+ JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
{
- return get_impl(static_cast<ValueType*>(nullptr));
+ static_assert(not std::is_reference<ValueTypeCV>::value,
+ "get() cannot be used with reference types, you might want to use get_ref()");
+ return JSONSerializer<ValueTypeCV>::from_json(*this);
}
/*!
@@ -2882,7 +9728,8 @@ class basic_json
Explicit pointer access to the internally stored JSON value. No copies are
made.
- @warning The pointer becomes invalid if the underlying JSON object changes.
+ @warning The pointer becomes invalid if the underlying JSON object
+ changes.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@@ -2902,10 +9749,8 @@ class basic_json
@since version 1.0.0
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
PointerType get() noexcept
{
// delegate the call to get_ptr
@@ -2916,10 +9761,8 @@ class basic_json
@brief get a pointer value (explicit)
@copydoc get()
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
constexpr const PointerType get() const noexcept
{
// delegate the call to get_ptr
@@ -2937,7 +9780,8 @@ class basic_json
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
- @ref number_unsigned_t, or @ref number_float_t.
+ @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
+ assertion.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@@ -2951,12 +9795,25 @@ class basic_json
@since version 1.0.0
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
PointerType get_ptr() noexcept
{
+ // get the type of the PointerType (remove pointer and const)
+ using pointee_t = typename std::remove_const<typename
+ std::remove_pointer<typename
+ std::remove_const<PointerType>::type>::type>::type;
+ // make sure the type matches the allowed types
+ static_assert(
+ std::is_same<object_t, pointee_t>::value
+ or std::is_same<array_t, pointee_t>::value
+ or std::is_same<string_t, pointee_t>::value
+ or std::is_same<boolean_t, pointee_t>::value
+ or std::is_same<number_integer_t, pointee_t>::value
+ or std::is_same<number_unsigned_t, pointee_t>::value
+ or std::is_same<number_float_t, pointee_t>::value
+ , "incompatible pointer type");
+
// delegate the call to get_impl_ptr<>()
return get_impl_ptr(static_cast<PointerType>(nullptr));
}
@@ -2965,21 +9822,34 @@ class basic_json
@brief get a pointer value (implicit)
@copydoc get_ptr()
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- and std::is_const<typename std::remove_pointer<PointerType>::type>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value and
+ std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
constexpr const PointerType get_ptr() const noexcept
{
+ // get the type of the PointerType (remove pointer and const)
+ using pointee_t = typename std::remove_const<typename
+ std::remove_pointer<typename
+ std::remove_const<PointerType>::type>::type>::type;
+ // make sure the type matches the allowed types
+ static_assert(
+ std::is_same<object_t, pointee_t>::value
+ or std::is_same<array_t, pointee_t>::value
+ or std::is_same<string_t, pointee_t>::value
+ or std::is_same<boolean_t, pointee_t>::value
+ or std::is_same<number_integer_t, pointee_t>::value
+ or std::is_same<number_unsigned_t, pointee_t>::value
+ or std::is_same<number_float_t, pointee_t>::value
+ , "incompatible pointer type");
+
// delegate the call to get_impl_ptr<>() const
- return get_impl_ptr(static_cast<const PointerType>(nullptr));
+ return get_impl_ptr(static_cast<PointerType>(nullptr));
}
/*!
@brief get a reference value (implicit)
- Implict reference access to the internally stored JSON value. No copies
+ Implicit reference access to the internally stored JSON value. No copies
are made.
@warning Writing data to the referee of the result yields an undefined
@@ -2987,14 +9857,14 @@ class basic_json
@tparam ReferenceType reference type; must be a reference to @ref array_t,
@ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
- @ref number_float_t.
+ @ref number_float_t. Enforced by static assertion.
@return reference to the internally stored JSON value if the requested
reference type @a ReferenceType fits to the JSON value; throws
- std::domain_error otherwise
+ type_error.303 otherwise
- @throw std::domain_error in case passed type @a ReferenceType is
- incompatible with the stored JSON value
+ @throw type_error.303 in case passed type @a ReferenceType is incompatible
+ with the stored JSON value; see example below
@complexity Constant.
@@ -3002,10 +9872,8 @@ class basic_json
@since version 1.1.0
*/
- template<typename ReferenceType, typename
- std::enable_if<
- std::is_reference<ReferenceType>::value
- , int>::type = 0>
+ template<typename ReferenceType, typename std::enable_if<
+ std::is_reference<ReferenceType>::value, int>::type = 0>
ReferenceType get_ref()
{
// delegate call to get_ref_impl
@@ -3016,11 +9884,9 @@ class basic_json
@brief get a reference value (implicit)
@copydoc get_ref()
*/
- template<typename ReferenceType, typename
- std::enable_if<
- std::is_reference<ReferenceType>::value
- and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
- , int>::type = 0>
+ template<typename ReferenceType, typename std::enable_if<
+ std::is_reference<ReferenceType>::value and
+ std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
ReferenceType get_ref() const
{
// delegate call to get_ref_impl
@@ -3041,8 +9907,9 @@ class basic_json
@return copy of the JSON value, converted to type @a ValueType
- @throw std::domain_error in case passed type @a ValueType is incompatible
- to JSON, thrown by @ref get() const
+ @throw type_error.302 in case passed type @a ValueType is incompatible
+ to the JSON value type (e.g., the JSON value is of type boolean, but a
+ string is requested); see example below
@complexity Linear in the size of the JSON value.
@@ -3055,13 +9922,16 @@ class basic_json
@since version 1.0.0
*/
- template < typename ValueType, typename
- std::enable_if <
- not std::is_pointer<ValueType>::value
- and not std::is_same<ValueType, typename string_t::value_type>::value
-#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
+ template < typename ValueType, typename std::enable_if <
+ not std::is_pointer<ValueType>::value and
+ not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
+ not std::is_same<ValueType, typename string_t::value_type>::value
+#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif
+#if defined(JSON_HAS_CPP_17)
+ and not std::is_same<ValueType, typename std::string_view>::value
+#endif
, int >::type = 0 >
operator ValueType() const
{
@@ -3077,6 +9947,7 @@ class basic_json
////////////////////
/// @name element access
+ /// Access to the JSON value.
/// @{
/*!
@@ -3089,37 +9960,40 @@ class basic_json
@return reference to the element at index @a idx
- @throw std::domain_error if the JSON value is not an array; example:
- `"cannot use at() with string"`
- @throw std::out_of_range if the index @a idx is out of range of the array;
- that is, `idx >= size()`; example: `"array index 7 is out of range"`
+ @throw type_error.304 if the JSON value is not an array; in this case,
+ calling `at` with an index makes no sense. See example below.
+ @throw out_of_range.401 if the index @a idx is out of range of the array;
+ that is, `idx >= size()`. See example below.
- @complexity Constant.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
- @liveexample{The example below shows how array elements can be read and
- written using `at()`.,at__size_type}
+ @complexity Constant.
@since version 1.0.0
+
+ @liveexample{The example below shows how array elements can be read and
+ written using `at()`. It also demonstrates the different exceptions that
+ can be thrown.,at__size_type}
*/
reference at(size_type idx)
{
// at only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
- try
+ JSON_TRY
{
- assert(m_value.array != nullptr);
return m_value.array->at(idx);
}
- catch (std::out_of_range&)
+ JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
}
}
else
{
- throw std::domain_error("cannot use at() with " + type_name());
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
}
}
@@ -3133,37 +10007,40 @@ class basic_json
@return const reference to the element at index @a idx
- @throw std::domain_error if the JSON value is not an array; example:
- `"cannot use at() with string"`
- @throw std::out_of_range if the index @a idx is out of range of the array;
- that is, `idx >= size()`; example: `"array index 7 is out of range"`
+ @throw type_error.304 if the JSON value is not an array; in this case,
+ calling `at` with an index makes no sense. See example below.
+ @throw out_of_range.401 if the index @a idx is out of range of the array;
+ that is, `idx >= size()`. See example below.
- @complexity Constant.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
- @liveexample{The example below shows how array elements can be read using
- `at()`.,at__size_type_const}
+ @complexity Constant.
@since version 1.0.0
+
+ @liveexample{The example below shows how array elements can be read using
+ `at()`. It also demonstrates the different exceptions that can be thrown.,
+ at__size_type_const}
*/
const_reference at(size_type idx) const
{
// at only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
- try
+ JSON_TRY
{
- assert(m_value.array != nullptr);
return m_value.array->at(idx);
}
- catch (std::out_of_range&)
+ JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
}
}
else
{
- throw std::domain_error("cannot use at() with " + type_name());
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
}
}
@@ -3177,41 +10054,44 @@ class basic_json
@return reference to the element at key @a key
- @throw std::domain_error if the JSON value is not an object; example:
- `"cannot use at() with boolean"`
- @throw std::out_of_range if the key @a key is is not stored in the object;
- that is, `find(key) == end()`; example: `"key "the fast" not found"`
+ @throw type_error.304 if the JSON value is not an object; in this case,
+ calling `at` with a key makes no sense. See example below.
+ @throw out_of_range.403 if the key @a key is is not stored in the object;
+ that is, `find(key) == end()`. See example below.
- @complexity Logarithmic in the size of the container.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
- @liveexample{The example below shows how object elements can be read and
- written using `at()`.,at__object_t_key_type}
+ @complexity Logarithmic in the size of the container.
@sa @ref operator[](const typename object_t::key_type&) for unchecked
access by reference
@sa @ref value() for access by value with a default value
@since version 1.0.0
+
+ @liveexample{The example below shows how object elements can be read and
+ written using `at()`. It also demonstrates the different exceptions that
+ can be thrown.,at__object_t_key_type}
*/
reference at(const typename object_t::key_type& key)
{
// at only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- try
+ JSON_TRY
{
- assert(m_value.object != nullptr);
return m_value.object->at(key);
}
- catch (std::out_of_range&)
+ JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- throw std::out_of_range("key '" + key + "' not found");
+ JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
}
}
else
{
- throw std::domain_error("cannot use at() with " + type_name());
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
}
}
@@ -3225,41 +10105,44 @@ class basic_json
@return const reference to the element at key @a key
- @throw std::domain_error if the JSON value is not an object; example:
- `"cannot use at() with boolean"`
- @throw std::out_of_range if the key @a key is is not stored in the object;
- that is, `find(key) == end()`; example: `"key "the fast" not found"`
+ @throw type_error.304 if the JSON value is not an object; in this case,
+ calling `at` with a key makes no sense. See example below.
+ @throw out_of_range.403 if the key @a key is is not stored in the object;
+ that is, `find(key) == end()`. See example below.
- @complexity Logarithmic in the size of the container.
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
- @liveexample{The example below shows how object elements can be read using
- `at()`.,at__object_t_key_type_const}
+ @complexity Logarithmic in the size of the container.
@sa @ref operator[](const typename object_t::key_type&) for unchecked
access by reference
@sa @ref value() for access by value with a default value
@since version 1.0.0
+
+ @liveexample{The example below shows how object elements can be read using
+ `at()`. It also demonstrates the different exceptions that can be thrown.,
+ at__object_t_key_type_const}
*/
const_reference at(const typename object_t::key_type& key) const
{
// at only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- try
+ JSON_TRY
{
- assert(m_value.object != nullptr);
return m_value.object->at(key);
}
- catch (std::out_of_range&)
+ JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- throw std::out_of_range("key '" + key + "' not found");
+ JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
}
}
else
{
- throw std::domain_error("cannot use at() with " + type_name());
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
}
}
@@ -3276,8 +10159,8 @@ class basic_json
@return reference to the element at index @a idx
- @throw std::domain_error if JSON is not an array or null; example:
- `"cannot use operator[] with string"`
+ @throw type_error.305 if the JSON value is not an array or null; in that
+ cases, using the [] operator with an index makes no sense.
@complexity Constant if @a idx is in the range of the array. Otherwise
linear in `idx - size()`.
@@ -3295,24 +10178,24 @@ class basic_json
{
m_type = value_t::array;
m_value.array = create<array_t>();
+ assert_invariant();
}
// operator[] only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
- // fill up array with null values until given idx is reached
- assert(m_value.array != nullptr);
- for (size_t i = m_value.array->size(); i <= idx; ++i)
+ // fill up array with null values if given idx is outside range
+ if (idx >= m_value.array->size())
{
- m_value.array->push_back(basic_json());
+ m_value.array->insert(m_value.array->end(),
+ idx - m_value.array->size() + 1,
+ basic_json());
}
return m_value.array->operator[](idx);
}
- else
- {
- throw std::domain_error("cannot use operator[] with " + type_name());
- }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
}
/*!
@@ -3324,8 +10207,8 @@ class basic_json
@return const reference to the element at index @a idx
- @throw std::domain_error if JSON is not an array; example: `"cannot use
- operator[] with null"`
+ @throw type_error.305 if the JSON value is not an array; in that case,
+ using the [] operator with an index makes no sense.
@complexity Constant.
@@ -3337,15 +10220,12 @@ class basic_json
const_reference operator[](size_type idx) const
{
// const operator[] only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
- assert(m_value.array != nullptr);
return m_value.array->operator[](idx);
}
- else
- {
- throw std::domain_error("cannot use operator[] with " + type_name());
- }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
}
/*!
@@ -3361,8 +10241,8 @@ class basic_json
@return reference to the element at key @a key
- @throw std::domain_error if JSON is not an object or null; example:
- `"cannot use operator[] with string"`
+ @throw type_error.305 if the JSON value is not an object or null; in that
+ cases, using the [] operator with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -3382,18 +10262,16 @@ class basic_json
{
m_type = value_t::object;
m_value.object = create<object_t>();
+ assert_invariant();
}
// operator[] only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- assert(m_value.object != nullptr);
return m_value.object->operator[](key);
}
- else
- {
- throw std::domain_error("cannot use operator[] with " + type_name());
- }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
}
/*!
@@ -3409,8 +10287,11 @@ class basic_json
@return const reference to the element at key @a key
- @throw std::domain_error if JSON is not an object; example: `"cannot use
- operator[] with null"`
+ @pre The element with key @a key must exist. **This precondition is
+ enforced with an assertion.**
+
+ @throw type_error.305 if the JSON value is not an object; in that case,
+ using the [] operator with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -3426,84 +10307,13 @@ class basic_json
const_reference operator[](const typename object_t::key_type& key) const
{
// const operator[] only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- assert(m_value.object != nullptr);
assert(m_value.object->find(key) != m_value.object->end());
return m_value.object->find(key)->second;
}
- else
- {
- throw std::domain_error("cannot use operator[] with " + type_name());
- }
- }
-
- /*!
- @brief access specified object element
-
- Returns a reference to the element at with specified key @a key.
-
- @note If @a key is not found in the object, then it is silently added to
- the object and filled with a `null` value to make `key` a valid reference.
- In case the value was `null` before, it is converted to an object.
-
- @param[in] key key of the element to access
-
- @return reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object or null; example:
- `"cannot use operator[] with string"`
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read and
- written using the `[]` operator.,operatorarray__key_type}
-
- @sa @ref at(const typename object_t::key_type&) for access by reference
- with range checking
- @sa @ref value() for access by value with a default value
-
- @since version 1.0.0
- */
- template<typename T, std::size_t n>
- reference operator[](T * (&key)[n])
- {
- return operator[](static_cast<const T>(key));
- }
-
- /*!
- @brief read-only access specified object element
-
- Returns a const reference to the element at with specified key @a key. No
- bounds checking is performed.
-
- @warning If the element with key @a key does not exist, the behavior is
- undefined.
-
- @note This function is required for compatibility reasons with Clang.
-
- @param[in] key key of the element to access
-
- @return const reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object; example: `"cannot use
- operator[] with null"`
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read using
- the `[]` operator.,operatorarray__key_type_const}
-
- @sa @ref at(const typename object_t::key_type&) for access by reference
- with range checking
- @sa @ref value() for access by value with a default value
-
- @since version 1.0.0
- */
- template<typename T, std::size_t n>
- const_reference operator[](T * (&key)[n]) const
- {
- return operator[](static_cast<const T>(key));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
}
/*!
@@ -3519,8 +10329,8 @@ class basic_json
@return reference to the element at key @a key
- @throw std::domain_error if JSON is not an object or null; example:
- `"cannot use operator[] with string"`
+ @throw type_error.305 if the JSON value is not an object or null; in that
+ cases, using the [] operator with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -3541,18 +10351,16 @@ class basic_json
{
m_type = value_t::object;
m_value = value_t::object;
+ assert_invariant();
}
// at only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- assert(m_value.object != nullptr);
return m_value.object->operator[](key);
}
- else
- {
- throw std::domain_error("cannot use operator[] with " + type_name());
- }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
}
/*!
@@ -3568,8 +10376,11 @@ class basic_json
@return const reference to the element at key @a key
- @throw std::domain_error if JSON is not an object; example: `"cannot use
- operator[] with null"`
+ @pre The element with key @a key must exist. **This precondition is
+ enforced with an assertion.**
+
+ @throw type_error.305 if the JSON value is not an object; in that case,
+ using the [] operator with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -3586,29 +10397,26 @@ class basic_json
const_reference operator[](T* key) const
{
// at only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- assert(m_value.object != nullptr);
assert(m_value.object->find(key) != m_value.object->end());
return m_value.object->find(key)->second;
}
- else
- {
- throw std::domain_error("cannot use operator[] with " + type_name());
- }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
}
/*!
@brief access specified object element with default value
- Returns either a copy of an object's element at the specified key @a key or
- a given default value if no element with key @a key exists.
+ Returns either a copy of an object's element at the specified key @a key
+ or a given default value if no element with key @a key exists.
The function is basically equivalent to executing
@code {.cpp}
try {
return at(key);
- } catch(std::out_of_range) {
+ } catch(out_of_range) {
return default_value;
}
@endcode
@@ -3631,8 +10439,8 @@ class basic_json
@return copy of the element at key @a key or @a default_value if @a key
is not found
- @throw std::domain_error if JSON is not an object; example: `"cannot use
- value() with null"`
+ @throw type_error.306 if the JSON value is not an object; in that case,
+ using `value()` with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -3646,14 +10454,12 @@ class basic_json
@since version 1.0.0
*/
- template <class ValueType, typename
- std::enable_if<
- std::is_convertible<basic_json_t, ValueType>::value
- , int>::type = 0>
- ValueType value(const typename object_t::key_type& key, ValueType default_value) const
+ template<class ValueType, typename std::enable_if<
+ std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
+ ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
{
// at only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
// if key is found, return value and given default value otherwise
const auto it = find(key);
@@ -3661,24 +10467,91 @@ class basic_json
{
return *it;
}
- else
+
+ return default_value;
+ }
+
+ JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
+ }
+
+ /*!
+ @brief overload for a default value of type const char*
+ @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const
+ */
+ string_t value(const typename object_t::key_type& key, const char* default_value) const
+ {
+ return value(key, string_t(default_value));
+ }
+
+ /*!
+ @brief access specified object element via JSON Pointer with default value
+
+ Returns either a copy of an object's element at the specified key @a key
+ or a given default value if no element with key @a key exists.
+
+ The function is basically equivalent to executing
+ @code {.cpp}
+ try {
+ return at(ptr);
+ } catch(out_of_range) {
+ return default_value;
+ }
+ @endcode
+
+ @note Unlike @ref at(const json_pointer&), this function does not throw
+ if the given key @a key was not found.
+
+ @param[in] ptr a JSON pointer to the element to access
+ @param[in] default_value the value to return if @a ptr found no value
+
+ @tparam ValueType type compatible to JSON values, for instance `int` for
+ JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+ JSON arrays. Note the type of the expected value at @a key and the default
+ value @a default_value must be compatible.
+
+ @return copy of the element at key @a key or @a default_value if @a key
+ is not found
+
+ @throw type_error.306 if the JSON value is not an objec; in that case,
+ using `value()` with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be queried
+ with a default value.,basic_json__value_ptr}
+
+ @sa @ref operator[](const json_pointer&) for unchecked access by reference
+
+ @since version 2.0.2
+ */
+ template<class ValueType, typename std::enable_if<
+ std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
+ ValueType value(const json_pointer& ptr, const ValueType& default_value) const
+ {
+ // at only works for objects
+ if (JSON_LIKELY(is_object()))
+ {
+ // if pointer resolves a value, return it or use default value
+ JSON_TRY
+ {
+ return ptr.get_checked(this);
+ }
+ JSON_CATCH (out_of_range&)
{
return default_value;
}
}
- else
- {
- throw std::domain_error("cannot use value() with " + type_name());
- }
+
+ JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
}
/*!
@brief overload for a default value of type const char*
- @copydoc basic_json::value()
+ @copydoc basic_json::value(const json_pointer&, ValueType) const
*/
- string_t value(const typename object_t::key_type& key, const char* default_value) const
+ string_t value(const json_pointer& ptr, const char* default_value) const
{
- return value(key, string_t(default_value));
+ return value(ptr, string_t(default_value));
}
/*!
@@ -3688,16 +10561,17 @@ class basic_json
container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
@return In case of a structured type (array or object), a reference to the
- first element is returned. In cast of number, string, or boolean values, a
+ first element is returned. In case of number, string, or boolean values, a
reference to the value is returned.
@complexity Constant.
@pre The JSON value must not be `null` (would throw `std::out_of_range`)
- or an empty array or object (undefined behavior, guarded by assertions).
+ or an empty array or object (undefined behavior, **guarded by
+ assertions**).
@post The JSON value remains unchanged.
- @throw std::out_of_range when called on `null` value
+ @throw invalid_iterator.214 when called on `null` value
@liveexample{The following code shows an example for `front()`.,front}
@@ -3730,16 +10604,18 @@ class basic_json
@endcode
@return In case of a structured type (array or object), a reference to the
- last element is returned. In cast of number, string, or boolean values, a
+ last element is returned. In case of number, string, or boolean values, a
reference to the value is returned.
@complexity Constant.
@pre The JSON value must not be `null` (would throw `std::out_of_range`)
- or an empty array or object (undefined behavior, guarded by assertions).
+ or an empty array or object (undefined behavior, **guarded by
+ assertions**).
@post The JSON value remains unchanged.
- @throw std::out_of_range when called on `null` value.
+ @throw invalid_iterator.214 when called on a `null` value. See example
+ below.
@liveexample{The following code shows an example for `back()`.,back}
@@ -3778,29 +10654,30 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
pos refers to the last element, the `end()` iterator is returned.
- @tparam InteratorType an @ref iterator or @ref const_iterator
+ @tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
- @throw std::domain_error if called on a `null` value; example: `"cannot
- use erase() with null"`
- @throw std::domain_error if called on an iterator which does not belong to
- the current JSON value; example: `"iterator does not fit current value"`
- @throw std::out_of_range if called on a primitive type with invalid
+ @throw type_error.307 if called on a `null` value; example: `"cannot use
+ erase() with null"`
+ @throw invalid_iterator.202 if called on an iterator which does not belong
+ to the current JSON value; example: `"iterator does not fit current
+ value"`
+ @throw invalid_iterator.205 if called on a primitive type with invalid
iterator (i.e., any iterator which is not `begin()`); example: `"iterator
out of range"`
@complexity The complexity depends on the type:
- objects: amortized constant
- - arrays: linear in distance between pos and the end of the container
+ - arrays: linear in distance between @a pos and the end of the container
- strings: linear in the length of the string
- other types: constant
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType}
- @sa @ref erase(InteratorType, InteratorType) -- removes the elements in
+ @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@@ -3809,21 +10686,19 @@ class basic_json
@since version 1.0.0
*/
- template <class InteratorType, typename
- std::enable_if<
- std::is_same<InteratorType, typename basic_json_t::iterator>::value or
- std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
- , int>::type
- = 0>
- InteratorType erase(InteratorType pos)
+ template<class IteratorType, typename std::enable_if<
+ std::is_same<IteratorType, typename basic_json_t::iterator>::value or
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
+ = 0>
+ IteratorType erase(IteratorType pos)
{
// make sure iterator fits the current value
- if (this != pos.m_object)
+ if (JSON_UNLIKELY(this != pos.m_object))
{
- throw std::domain_error("iterator does not fit current value");
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
}
- InteratorType result = end();
+ IteratorType result = end();
switch (m_type)
{
@@ -3833,39 +10708,38 @@ class basic_json
case value_t::number_unsigned:
case value_t::string:
{
- if (not pos.m_it.primitive_iterator.is_begin())
+ if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
{
- throw std::out_of_range("iterator out of range");
+ JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
}
if (is_string())
{
- delete m_value.string;
+ AllocatorType<string_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
m_value.string = nullptr;
}
m_type = value_t::null;
+ assert_invariant();
break;
}
case value_t::object:
{
- assert(m_value.object != nullptr);
result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
break;
}
case value_t::array:
{
- assert(m_value.array != nullptr);
result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
break;
}
default:
- {
- throw std::domain_error("cannot use erase() with " + type_name());
- }
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
}
return result;
@@ -3886,16 +10760,16 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
second refers to the last element, the `end()` iterator is returned.
- @tparam InteratorType an @ref iterator or @ref const_iterator
+ @tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
- @throw std::domain_error if called on a `null` value; example: `"cannot
- use erase() with null"`
- @throw std::domain_error if called on iterators which does not belong to
- the current JSON value; example: `"iterators do not fit current value"`
- @throw std::out_of_range if called on a primitive type with invalid
+ @throw type_error.307 if called on a `null` value; example: `"cannot use
+ erase() with null"`
+ @throw invalid_iterator.203 if called on iterators which does not belong
+ to the current JSON value; example: `"iterators do not fit current value"`
+ @throw invalid_iterator.204 if called on a primitive type with invalid
iterators (i.e., if `first != begin()` and `last != end()`); example:
`"iterators out of range"`
@@ -3909,7 +10783,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType_IteratorType}
- @sa @ref erase(InteratorType) -- removes the element at a given position
+ @sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@sa @ref erase(const size_type) -- removes the element from an array at
@@ -3917,21 +10791,19 @@ class basic_json
@since version 1.0.0
*/
- template <class InteratorType, typename
- std::enable_if<
- std::is_same<InteratorType, typename basic_json_t::iterator>::value or
- std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
- , int>::type
- = 0>
- InteratorType erase(InteratorType first, InteratorType last)
+ template<class IteratorType, typename std::enable_if<
+ std::is_same<IteratorType, typename basic_json_t::iterator>::value or
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
+ = 0>
+ IteratorType erase(IteratorType first, IteratorType last)
{
// make sure iterator fits the current value
- if (this != first.m_object or this != last.m_object)
+ if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
{
- throw std::domain_error("iterators do not fit current value");
+ JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
}
- InteratorType result = end();
+ IteratorType result = end();
switch (m_type)
{
@@ -3941,24 +10813,27 @@ class basic_json
case value_t::number_unsigned:
case value_t::string:
{
- if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
+ if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
+ or not last.m_it.primitive_iterator.is_end()))
{
- throw std::out_of_range("iterators out of range");
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
}
if (is_string())
{
- delete m_value.string;
+ AllocatorType<string_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
m_value.string = nullptr;
}
m_type = value_t::null;
+ assert_invariant();
break;
}
case value_t::object:
{
- assert(m_value.object != nullptr);
result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
last.m_it.object_iterator);
break;
@@ -3966,16 +10841,13 @@ class basic_json
case value_t::array:
{
- assert(m_value.array != nullptr);
result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
last.m_it.array_iterator);
break;
}
default:
- {
- throw std::domain_error("cannot use erase() with " + type_name());
- }
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
}
return result;
@@ -3995,15 +10867,15 @@ class basic_json
@post References and iterators to the erased elements are invalidated.
Other references and iterators are not affected.
- @throw std::domain_error when called on a type other than JSON object;
+ @throw type_error.307 when called on a type other than JSON object;
example: `"cannot use erase() with null"`
@complexity `log(size()) + count(key)`
@liveexample{The example shows the effect of `erase()`.,erase__key_type}
- @sa @ref erase(InteratorType) -- removes the element at a given position
- @sa @ref erase(InteratorType, InteratorType) -- removes the elements in
+ @sa @ref erase(IteratorType) -- removes the element at a given position
+ @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const size_type) -- removes the element from an array at
the given index
@@ -4013,15 +10885,12 @@ class basic_json
size_type erase(const typename object_t::key_type& key)
{
// this erase only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- assert(m_value.object != nullptr);
return m_value.object->erase(key);
}
- else
- {
- throw std::domain_error("cannot use erase() with " + type_name());
- }
+
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
}
/*!
@@ -4031,17 +10900,17 @@ class basic_json
@param[in] idx index of the element to remove
- @throw std::domain_error when called on a type other than JSON array;
+ @throw type_error.307 when called on a type other than JSON object;
example: `"cannot use erase() with null"`
- @throw std::out_of_range when `idx >= size()`; example: `"array index 17
+ @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
is out of range"`
@complexity Linear in distance between @a idx and the end of the container.
@liveexample{The example shows the effect of `erase()`.,erase__size_type}
- @sa @ref erase(InteratorType) -- removes the element at a given position
- @sa @ref erase(InteratorType, InteratorType) -- removes the elements in
+ @sa @ref erase(IteratorType) -- removes the element at a given position
+ @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@@ -4051,19 +10920,18 @@ class basic_json
void erase(const size_type idx)
{
// this erase only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
- if (idx >= size())
+ if (JSON_UNLIKELY(idx >= size()))
{
- throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
}
- assert(m_value.array != nullptr);
m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
}
else
{
- throw std::domain_error("cannot use erase() with " + type_name());
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
}
}
@@ -4084,10 +10952,14 @@ class basic_json
element is not found or the JSON value is not an object, end() is
returned.
- @param[in] key key value of the element to search for
+ @note This method always returns @ref end() when executed on a JSON type
+ that is not an object.
+
+ @param[in] key key value of the element to search for.
@return Iterator to an element with key equivalent to @a key. If no such
- element is found, past-the-end (see end()) iterator is returned.
+ element is found or the JSON value is not an object, past-the-end (see
+ @ref end()) iterator is returned.
@complexity Logarithmic in the size of the JSON object.
@@ -4095,14 +10967,14 @@ class basic_json
@since version 1.0.0
*/
- iterator find(typename object_t::key_type key)
+ template<typename KeyT>
+ iterator find(KeyT&& key)
{
auto result = end();
if (is_object())
{
- assert(m_value.object != nullptr);
- result.m_it.object_iterator = m_value.object->find(key);
+ result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
}
return result;
@@ -4110,16 +10982,16 @@ class basic_json
/*!
@brief find an element in a JSON object
- @copydoc find(typename object_t::key_type)
+ @copydoc find(KeyT&&)
*/
- const_iterator find(typename object_t::key_type key) const
+ template<typename KeyT>
+ const_iterator find(KeyT&& key) const
{
auto result = cend();
if (is_object())
{
- assert(m_value.object != nullptr);
- result.m_it.object_iterator = m_value.object->find(key);
+ result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
}
return result;
@@ -4132,6 +11004,9 @@ class basic_json
default `std::map` type, the return value will always be `0` (@a key was
not found) or `1` (@a key was found).
+ @note This method always returns `0` when executed on a JSON type that is
+ not an object.
+
@param[in] key key value of the element to count
@return Number of elements with key @a key. If the JSON value is not an
@@ -4143,11 +11018,11 @@ class basic_json
@since version 1.0.0
*/
- size_type count(typename object_t::key_type key) const
+ template<typename KeyT>
+ size_type count(KeyT&& key) const
{
// return 0 for all nonobject types
- assert(not is_object() or m_value.object != nullptr);
- return is_object() ? m_value.object->count(key) : 0;
+ return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
}
/// @}
@@ -4433,10 +11308,6 @@ class basic_json
return const_reverse_iterator(cbegin());
}
- private:
- // forward declaration
- template<typename IteratorType> class iteration_proxy;
-
public:
/*!
@brief wrapper to access iterator member functions in range-based for
@@ -4446,20 +11317,62 @@ class basic_json
reference to the JSON values is returned, so there is no access to the
underlying iterator.
+ For loop without iterator_wrapper:
+
+ @code{cpp}
+ for (auto it = j_object.begin(); it != j_object.end(); ++it)
+ {
+ std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+ }
+ @endcode
+
+ Range-based for loop without iterator proxy:
+
+ @code{cpp}
+ for (auto it : j_object)
+ {
+ // "it" is of type json::reference and has no key() member
+ std::cout << "value: " << it << '\n';
+ }
+ @endcode
+
+ Range-based for loop with iterator proxy:
+
+ @code{cpp}
+ for (auto it : json::iterator_wrapper(j_object))
+ {
+ std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+ }
+ @endcode
+
+ @note When iterating over an array, `key()` will return the index of the
+ element as string (see example).
+
+ @param[in] ref reference to a JSON value
+ @return iteration proxy object wrapping @a ref with an interface to use in
+ range-based for loops
+
+ @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
@note The name of this function is not yet final and may change in the
future.
*/
- static iteration_proxy<iterator> iterator_wrapper(reference cont)
+ static iteration_proxy<iterator> iterator_wrapper(reference ref)
{
- return iteration_proxy<iterator>(cont);
+ return iteration_proxy<iterator>(ref);
}
/*!
@copydoc iterator_wrapper(reference)
*/
- static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
+ static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref)
{
- return iteration_proxy<const_iterator>(cont);
+ return iteration_proxy<const_iterator>(ref);
}
/// @}
@@ -4473,9 +11386,9 @@ class basic_json
/// @{
/*!
- @brief checks whether the container is empty
+ @brief checks whether the container is empty.
- Checks if a JSON value has no elements.
+ Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
@return The return value depends on the different types and is
defined as follows:
@@ -4488,19 +11401,27 @@ class basic_json
object | result of function `object_t::empty()`
array | result of function `array_t::empty()`
+ @liveexample{The following code uses `empty()` to check if a JSON
+ object contains any elements.,empty}
+
@complexity Constant, as long as @ref array_t and @ref object_t satisfy
the Container concept; that is, their `empty()` functions have constant
complexity.
+ @iterators No changes.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @note This function does not return whether a string stored as JSON value
+ is empty - it returns whether the JSON container itself is empty which is
+ false in the case of a string.
+
@requirement This function helps `basic_json` satisfying the
[Container](http://en.cppreference.com/w/cpp/concept/Container)
requirements:
- The complexity is constant.
- Has the semantics of `begin() == end()`.
- @liveexample{The following code uses `empty()` to check if a JSON
- object contains any elements.,empty}
-
@sa @ref size() -- returns the number of elements
@since version 1.0.0
@@ -4517,13 +11438,13 @@ class basic_json
case value_t::array:
{
- assert(m_value.array != nullptr);
+ // delegate call to array_t::empty()
return m_value.array->empty();
}
case value_t::object:
{
- assert(m_value.object != nullptr);
+ // delegate call to object_t::empty()
return m_value.object->empty();
}
@@ -4551,19 +11472,27 @@ class basic_json
object | result of function object_t::size()
array | result of function array_t::size()
+ @liveexample{The following code calls `size()` on the different value
+ types.,size}
+
@complexity Constant, as long as @ref array_t and @ref object_t satisfy
the Container concept; that is, their size() functions have constant
complexity.
+ @iterators No changes.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @note This function does not return the length of a string stored as JSON
+ value - it returns the number of elements in the JSON value which is 1 in
+ the case of a string.
+
@requirement This function helps `basic_json` satisfying the
[Container](http://en.cppreference.com/w/cpp/concept/Container)
requirements:
- The complexity is constant.
- Has the semantics of `std::distance(begin(), end())`.
- @liveexample{The following code calls `size()` on the different value
- types.,size}
-
@sa @ref empty() -- checks whether the container is empty
@sa @ref max_size() -- returns the maximal number of elements
@@ -4581,13 +11510,13 @@ class basic_json
case value_t::array:
{
- assert(m_value.array != nullptr);
+ // delegate call to array_t::size()
return m_value.array->size();
}
case value_t::object:
{
- assert(m_value.object != nullptr);
+ // delegate call to object_t::size()
return m_value.object->size();
}
@@ -4617,10 +11546,17 @@ class basic_json
object | result of function `object_t::max_size()`
array | result of function `array_t::max_size()`
+ @liveexample{The following code calls `max_size()` on the different value
+ types. Note the output is implementation specific.,max_size}
+
@complexity Constant, as long as @ref array_t and @ref object_t satisfy
the Container concept; that is, their `max_size()` functions have constant
complexity.
+ @iterators No changes.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@requirement This function helps `basic_json` satisfying the
[Container](http://en.cppreference.com/w/cpp/concept/Container)
requirements:
@@ -4628,9 +11564,6 @@ class basic_json
- Has the semantics of returning `b.size()` where `b` is the largest
possible JSON value.
- @liveexample{The following code calls `max_size()` on the different value
- types. Note the output is implementation specific.,max_size}
-
@sa @ref size() -- returns the number of elements
@since version 1.0.0
@@ -4641,13 +11574,13 @@ class basic_json
{
case value_t::array:
{
- assert(m_value.array != nullptr);
+ // delegate call to array_t::max_size()
return m_value.array->max_size();
}
case value_t::object:
{
- assert(m_value.object != nullptr);
+ // delegate call to object_t::max_size()
return m_value.object->max_size();
}
@@ -4673,7 +11606,8 @@ class basic_json
@brief clears the contents
Clears the content of a JSON value and resets it to the default value as
- if @ref basic_json(value_t) would have been called:
+ if @ref basic_json(value_t) would have been called with the current value
+ type from @ref type():
Value type | initial value
----------- | -------------
@@ -4684,14 +11618,24 @@ class basic_json
object | `{}`
array | `[]`
- @note Floating-point numbers are set to `0.0` which will be serialized to
- `0`. The vale type remains @ref number_float_t.
-
- @complexity Linear in the size of the JSON value.
+ @post Has the same effect as calling
+ @code {.cpp}
+ *this = basic_json(type());
+ @endcode
@liveexample{The example below shows the effect of `clear()` to different
JSON types.,clear}
+ @complexity Linear in the size of the JSON value.
+
+ @iterators All iterators, pointers and references related to this container
+ are invalidated.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @sa @ref basic_json(value_t) -- constructor that creates an object with the
+ same value than calling `clear()`
+
@since version 1.0.0
*/
void clear() noexcept
@@ -4724,29 +11668,24 @@ class basic_json
case value_t::string:
{
- assert(m_value.string != nullptr);
m_value.string->clear();
break;
}
case value_t::array:
{
- assert(m_value.array != nullptr);
m_value.array->clear();
break;
}
case value_t::object:
{
- assert(m_value.object != nullptr);
m_value.object->clear();
break;
}
default:
- {
break;
- }
}
}
@@ -4759,7 +11698,7 @@ class basic_json
@param[in] val the value to add to the JSON array
- @throw std::domain_error when called on a type other than JSON array or
+ @throw type_error.308 when called on a type other than JSON array or
null; example: `"cannot use push_back() with number"`
@complexity Amortized constant.
@@ -4773,9 +11712,9 @@ class basic_json
void push_back(basic_json&& val)
{
// push_back only works for null objects or arrays
- if (not(is_null() or is_array()))
+ if (JSON_UNLIKELY(not(is_null() or is_array())))
{
- throw std::domain_error("cannot use push_back() with " + type_name());
+ JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
}
// transform null object into an array
@@ -4783,10 +11722,10 @@ class basic_json
{
m_type = value_t::array;
m_value = value_t::array;
+ assert_invariant();
}
// add element to array (move semantics)
- assert(m_value.array != nullptr);
m_value.array->push_back(std::move(val));
// invalidate object
val.m_type = value_t::null;
@@ -4809,9 +11748,9 @@ class basic_json
void push_back(const basic_json& val)
{
// push_back only works for null objects or arrays
- if (not(is_null() or is_array()))
+ if (JSON_UNLIKELY(not(is_null() or is_array())))
{
- throw std::domain_error("cannot use push_back() with " + type_name());
+ JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
}
// transform null object into an array
@@ -4819,10 +11758,10 @@ class basic_json
{
m_type = value_t::array;
m_value = value_t::array;
+ assert_invariant();
}
// add element to array
- assert(m_value.array != nullptr);
m_value.array->push_back(val);
}
@@ -4845,7 +11784,7 @@ class basic_json
@param[in] val the value to add to the JSON object
- @throw std::domain_error when called on a type other than JSON object or
+ @throw type_error.308 when called on a type other than JSON object or
null; example: `"cannot use push_back() with number"`
@complexity Logarithmic in the size of the container, O(log(`size()`)).
@@ -4859,9 +11798,9 @@ class basic_json
void push_back(const typename object_t::value_type& val)
{
// push_back only works for null objects or objects
- if (not(is_null() or is_object()))
+ if (JSON_UNLIKELY(not(is_null() or is_object())))
{
- throw std::domain_error("cannot use push_back() with " + type_name());
+ JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
}
// transform null object into an object
@@ -4869,10 +11808,10 @@ class basic_json
{
m_type = value_t::object;
m_value = value_t::object;
+ assert_invariant();
}
// add element to array
- assert(m_value.object != nullptr);
m_value.object->insert(val);
}
@@ -4899,7 +11838,7 @@ class basic_json
@ref push_back(const typename object_t::value_type&). Otherwise, @a init
is converted to a JSON value and added using @ref push_back(basic_json&&).
- @param init an initializer list
+ @param[in] init an initializer list
@complexity Linear in the size of the initializer list @a init.
@@ -4911,12 +11850,13 @@ class basic_json
@liveexample{The example shows how initializer lists are treated as
objects when possible.,push_back__initializer_list}
*/
- void push_back(std::initializer_list<basic_json> init)
+ void push_back(initializer_list_t init)
{
- if (is_object() and init.size() == 2 and init.begin()->is_string())
+ if (is_object() and init.size() == 2 and (*init.begin())->is_string())
{
- const string_t key = *init.begin();
- push_back(typename object_t::value_type(key, *(init.begin() + 1)));
+ basic_json&& key = init.begin()->moved_or_copied();
+ push_back(typename object_t::value_type(
+ std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
}
else
{
@@ -4926,15 +11866,111 @@ class basic_json
/*!
@brief add an object to an object
- @copydoc push_back(std::initializer_list<basic_json>)
+ @copydoc push_back(initializer_list_t)
*/
- reference operator+=(std::initializer_list<basic_json> init)
+ reference operator+=(initializer_list_t init)
{
push_back(init);
return *this;
}
/*!
+ @brief add an object to an array
+
+ Creates a JSON value from the passed parameters @a args to the end of the
+ JSON value. If the function is called on a JSON null value, an empty array
+ is created before appending the value created from @a args.
+
+ @param[in] args arguments to forward to a constructor of @ref basic_json
+ @tparam Args compatible types to create a @ref basic_json object
+
+ @throw type_error.311 when called on a type other than JSON array or
+ null; example: `"cannot use emplace_back() with number"`
+
+ @complexity Amortized constant.
+
+ @liveexample{The example shows how `push_back()` can be used to add
+ elements to a JSON array. Note how the `null` value was silently converted
+ to a JSON array.,emplace_back}
+
+ @since version 2.0.8
+ */
+ template<class... Args>
+ void emplace_back(Args&& ... args)
+ {
+ // emplace_back only works for null objects or arrays
+ if (JSON_UNLIKELY(not(is_null() or is_array())))
+ {
+ JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
+ }
+
+ // transform null object into an array
+ if (is_null())
+ {
+ m_type = value_t::array;
+ m_value = value_t::array;
+ assert_invariant();
+ }
+
+ // add element to array (perfect forwarding)
+ m_value.array->emplace_back(std::forward<Args>(args)...);
+ }
+
+ /*!
+ @brief add an object to an object if key does not exist
+
+ Inserts a new element into a JSON object constructed in-place with the
+ given @a args if there is no element with the key in the container. If the
+ function is called on a JSON null value, an empty object is created before
+ appending the value created from @a args.
+
+ @param[in] args arguments to forward to a constructor of @ref basic_json
+ @tparam Args compatible types to create a @ref basic_json object
+
+ @return a pair consisting of an iterator to the inserted element, or the
+ already-existing element if no insertion happened, and a bool
+ denoting whether the insertion took place.
+
+ @throw type_error.311 when called on a type other than JSON object or
+ null; example: `"cannot use emplace() with number"`
+
+ @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+ @liveexample{The example shows how `emplace()` can be used to add elements
+ to a JSON object. Note how the `null` value was silently converted to a
+ JSON object. Further note how no value is added if there was already one
+ value stored with the same key.,emplace}
+
+ @since version 2.0.8
+ */
+ template<class... Args>
+ std::pair<iterator, bool> emplace(Args&& ... args)
+ {
+ // emplace only works for null objects or arrays
+ if (JSON_UNLIKELY(not(is_null() or is_object())))
+ {
+ JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
+ }
+
+ // transform null object into an object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value = value_t::object;
+ assert_invariant();
+ }
+
+ // add element to array (perfect forwarding)
+ auto res = m_value.object->emplace(std::forward<Args>(args)...);
+ // create result iterator and set iterator to the result of emplace
+ auto it = begin();
+ it.m_it.object_iterator = res.first;
+
+ // return pair of iterator and boolean
+ return {it, res.second};
+ }
+
+ /*!
@brief inserts element
Inserts element @a val before iterator @a pos.
@@ -4944,13 +11980,13 @@ class basic_json
@param[in] val element to insert
@return iterator pointing to the inserted @a val.
- @throw std::domain_error if called on JSON values other than arrays;
+ @throw type_error.309 if called on JSON values other than arrays;
example: `"cannot use insert() with string"`
- @throw std::domain_error if @a pos is not an iterator of *this; example:
- `"iterator does not fit current value"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
- @complexity Constant plus linear in the distance between pos and end of the
- container.
+ @complexity Constant plus linear in the distance between @a pos and end of
+ the container.
@liveexample{The example shows how `insert()` is used.,insert}
@@ -4959,24 +11995,21 @@ class basic_json
iterator insert(const_iterator pos, const basic_json& val)
{
// insert only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
// check if iterator pos fits to this JSON value
- if (pos.m_object != this)
+ if (JSON_UNLIKELY(pos.m_object != this))
{
- throw std::domain_error("iterator does not fit current value");
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
}
// insert to array and return iterator
iterator result(this);
- assert(m_value.array != nullptr);
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
return result;
}
- else
- {
- throw std::domain_error("cannot use insert() with " + type_name());
- }
+
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
}
/*!
@@ -5000,10 +12033,10 @@ class basic_json
@return iterator pointing to the first element inserted, or @a pos if
`cnt==0`
- @throw std::domain_error if called on JSON values other than arrays;
- example: `"cannot use insert() with string"`
- @throw std::domain_error if @a pos is not an iterator of *this; example:
- `"iterator does not fit current value"`
+ @throw type_error.309 if called on JSON values other than arrays; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
@complexity Linear in @a cnt plus linear in the distance between @a pos
and end of the container.
@@ -5015,24 +12048,21 @@ class basic_json
iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
{
// insert only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
// check if iterator pos fits to this JSON value
- if (pos.m_object != this)
+ if (JSON_UNLIKELY(pos.m_object != this))
{
- throw std::domain_error("iterator does not fit current value");
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
}
// insert to array and return iterator
iterator result(this);
- assert(m_value.array != nullptr);
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
return result;
}
- else
- {
- throw std::domain_error("cannot use insert() with " + type_name());
- }
+
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
}
/*!
@@ -5045,13 +12075,13 @@ class basic_json
@param[in] first begin of the range of elements to insert
@param[in] last end of the range of elements to insert
- @throw std::domain_error if called on JSON values other than arrays;
- example: `"cannot use insert() with string"`
- @throw std::domain_error if @a pos is not an iterator of *this; example:
- `"iterator does not fit current value"`
- @throw std::domain_error if @a first and @a last do not belong to the same
- JSON value; example: `"iterators do not fit"`
- @throw std::domain_error if @a first or @a last are iterators into
+ @throw type_error.309 if called on JSON values other than arrays; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
+ @throw invalid_iterator.210 if @a first and @a last do not belong to the
+ same JSON value; example: `"iterators do not fit"`
+ @throw invalid_iterator.211 if @a first or @a last are iterators into
container for which insert is called; example: `"passed iterators may not
belong to container"`
@@ -5068,31 +12098,30 @@ class basic_json
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
{
// insert only works for arrays
- if (not is_array())
+ if (JSON_UNLIKELY(not is_array()))
{
- throw std::domain_error("cannot use insert() with " + type_name());
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
}
// check if iterator pos fits to this JSON value
- if (pos.m_object != this)
+ if (JSON_UNLIKELY(pos.m_object != this))
{
- throw std::domain_error("iterator does not fit current value");
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
}
// check if range iterators belong to the same JSON object
- if (first.m_object != last.m_object)
+ if (JSON_UNLIKELY(first.m_object != last.m_object))
{
- throw std::domain_error("iterators do not fit");
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
}
- if (first.m_object == this or last.m_object == this)
+ if (JSON_UNLIKELY(first.m_object == this))
{
- throw std::domain_error("passed iterators may not belong to container");
+ JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
}
// insert to array and return iterator
iterator result(this);
- assert(m_value.array != nullptr);
result.m_it.array_iterator = m_value.array->insert(
pos.m_it.array_iterator,
first.m_it.array_iterator,
@@ -5109,10 +12138,10 @@ class basic_json
the end() iterator
@param[in] ilist initializer list to insert the values from
- @throw std::domain_error if called on JSON values other than arrays;
- example: `"cannot use insert() with string"`
- @throw std::domain_error if @a pos is not an iterator of *this; example:
- `"iterator does not fit current value"`
+ @throw type_error.309 if called on JSON values other than arrays; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
@return iterator pointing to the first element inserted, or @a pos if
`ilist` is empty
@@ -5124,28 +12153,177 @@ class basic_json
@since version 1.0.0
*/
- iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
+ iterator insert(const_iterator pos, initializer_list_t ilist)
{
// insert only works for arrays
- if (not is_array())
+ if (JSON_UNLIKELY(not is_array()))
{
- throw std::domain_error("cannot use insert() with " + type_name());
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
}
// check if iterator pos fits to this JSON value
- if (pos.m_object != this)
+ if (JSON_UNLIKELY(pos.m_object != this))
{
- throw std::domain_error("iterator does not fit current value");
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
}
// insert to array and return iterator
iterator result(this);
- assert(m_value.array != nullptr);
- result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
+ result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
return result;
}
/*!
+ @brief inserts elements
+
+ Inserts elements from range `[first, last)`.
+
+ @param[in] first begin of the range of elements to insert
+ @param[in] last end of the range of elements to insert
+
+ @throw type_error.309 if called on JSON values other than objects; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if iterator @a first or @a last does does not
+ point to an object; example: `"iterators first and last must point to
+ objects"`
+ @throw invalid_iterator.210 if @a first and @a last do not belong to the
+ same JSON value; example: `"iterators do not fit"`
+
+ @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
+ of elements to insert.
+
+ @liveexample{The example shows how `insert()` is used.,insert__range_object}
+
+ @since version 3.0.0
+ */
+ void insert(const_iterator first, const_iterator last)
+ {
+ // insert only works for objects
+ if (JSON_UNLIKELY(not is_object()))
+ {
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
+ }
+
+ // check if range iterators belong to the same JSON object
+ if (JSON_UNLIKELY(first.m_object != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
+ }
+
+ // passed iterators must belong to objects
+ if (JSON_UNLIKELY(not first.m_object->is_object()))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
+ }
+
+ m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
+ }
+
+ /*!
+ @brief updates a JSON object from another object, overwriting existing keys
+
+ Inserts all values from JSON object @a j and overwrites existing keys.
+
+ @param[in] j JSON object to read values from
+
+ @throw type_error.312 if called on JSON values other than objects; example:
+ `"cannot use update() with string"`
+
+ @complexity O(N*log(size() + N)), where N is the number of elements to
+ insert.
+
+ @liveexample{The example shows how `update()` is used.,update}
+
+ @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+ @since version 3.0.0
+ */
+ void update(const_reference j)
+ {
+ // implicitly convert null value to an empty object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value.object = create<object_t>();
+ assert_invariant();
+ }
+
+ if (JSON_UNLIKELY(not is_object()))
+ {
+ JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
+ }
+ if (JSON_UNLIKELY(not j.is_object()))
+ {
+ JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
+ }
+
+ for (auto it = j.cbegin(); it != j.cend(); ++it)
+ {
+ m_value.object->operator[](it.key()) = it.value();
+ }
+ }
+
+ /*!
+ @brief updates a JSON object from another object, overwriting existing keys
+
+ Inserts all values from from range `[first, last)` and overwrites existing
+ keys.
+
+ @param[in] first begin of the range of elements to insert
+ @param[in] last end of the range of elements to insert
+
+ @throw type_error.312 if called on JSON values other than objects; example:
+ `"cannot use update() with string"`
+ @throw invalid_iterator.202 if iterator @a first or @a last does does not
+ point to an object; example: `"iterators first and last must point to
+ objects"`
+ @throw invalid_iterator.210 if @a first and @a last do not belong to the
+ same JSON value; example: `"iterators do not fit"`
+
+ @complexity O(N*log(size() + N)), where N is the number of elements to
+ insert.
+
+ @liveexample{The example shows how `update()` is used__range.,update}
+
+ @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+ @since version 3.0.0
+ */
+ void update(const_iterator first, const_iterator last)
+ {
+ // implicitly convert null value to an empty object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value.object = create<object_t>();
+ assert_invariant();
+ }
+
+ if (JSON_UNLIKELY(not is_object()))
+ {
+ JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
+ }
+
+ // check if range iterators belong to the same JSON object
+ if (JSON_UNLIKELY(first.m_object != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
+ }
+
+ // passed iterators must belong to objects
+ if (JSON_UNLIKELY(not first.m_object->is_object()
+ or not first.m_object->is_object()))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
+ }
+
+ for (auto it = first; it != last; ++it)
+ {
+ m_value.object->operator[](it.key()) = it.value();
+ }
+ }
+
+ /*!
@brief exchanges the values
Exchanges the contents of the JSON value with those of @a other. Does not
@@ -5171,6 +12349,7 @@ class basic_json
{
std::swap(m_type, other.m_type);
std::swap(m_value, other.m_value);
+ assert_invariant();
}
/*!
@@ -5183,7 +12362,7 @@ class basic_json
@param[in,out] other array to exchange the contents with
- @throw std::domain_error when JSON value is not an array; example: `"cannot
+ @throw type_error.310 when JSON value is not an array; example: `"cannot
use swap() with string"`
@complexity Constant.
@@ -5196,14 +12375,13 @@ class basic_json
void swap(array_t& other)
{
// swap only works for arrays
- if (is_array())
+ if (JSON_LIKELY(is_array()))
{
- assert(m_value.array != nullptr);
std::swap(*(m_value.array), other);
}
else
{
- throw std::domain_error("cannot use swap() with " + type_name());
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
}
}
@@ -5217,7 +12395,7 @@ class basic_json
@param[in,out] other object to exchange the contents with
- @throw std::domain_error when JSON value is not an object; example:
+ @throw type_error.310 when JSON value is not an object; example:
`"cannot use swap() with string"`
@complexity Constant.
@@ -5230,14 +12408,13 @@ class basic_json
void swap(object_t& other)
{
// swap only works for objects
- if (is_object())
+ if (JSON_LIKELY(is_object()))
{
- assert(m_value.object != nullptr);
std::swap(*(m_value.object), other);
}
else
{
- throw std::domain_error("cannot use swap() with " + type_name());
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
}
}
@@ -5251,7 +12428,7 @@ class basic_json
@param[in,out] other string to exchange the contents with
- @throw std::domain_error when JSON value is not a string; example: `"cannot
+ @throw type_error.310 when JSON value is not a string; example: `"cannot
use swap() with boolean"`
@complexity Constant.
@@ -5264,20 +12441,19 @@ class basic_json
void swap(string_t& other)
{
// swap only works for strings
- if (is_string())
+ if (JSON_LIKELY(is_string()))
{
- assert(m_value.string != nullptr);
std::swap(*(m_value.string), other);
}
else
{
- throw std::domain_error("cannot use swap() with " + type_name());
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
}
}
/// @}
-
+ public:
//////////////////////////////////////////
// lexicographical comparison operators //
//////////////////////////////////////////
@@ -5285,56 +12461,38 @@ class basic_json
/// @name lexicographical comparison operators
/// @{
- private:
- /*!
- @brief comparison operator for JSON types
-
- Returns an ordering that is similar to Python:
- - order: null < boolean < number < object < array < string
- - furthermore, each type is not smaller than itself
-
- @since version 1.0.0
- */
- friend bool operator<(const value_t lhs, const value_t rhs) noexcept
- {
- static constexpr std::array<uint8_t, 8> order = {{
- 0, // null
- 3, // object
- 4, // array
- 5, // string
- 1, // boolean
- 2, // integer
- 2, // unsigned
- 2, // float
- }
- };
-
- // discarded values are not comparable
- if (lhs == value_t::discarded or rhs == value_t::discarded)
- {
- return false;
- }
-
- return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
- }
-
- public:
/*!
@brief comparison: equal
Compares two JSON values for equality according to the following rules:
- Two JSON values are equal if (1) they are from the same type and (2)
- their stored values are the same.
+ their stored values are the same according to their respective
+ `operator==`.
- Integer and floating-point numbers are automatically converted before
- comparison. Floating-point numbers are compared indirectly: two
- floating-point numbers `f1` and `f2` are considered equal if neither
- `f1 > f2` nor `f2 > f1` holds.
+ comparison. Note than two NaN values are always treated as unequal.
- Two JSON null values are equal.
+ @note Floating-point inside JSON values numbers are compared with
+ `json::number_float_t::operator==` which is `double::operator==` by
+ default. To compare floating-point while respecting an epsilon, an alternative
+ [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
+ could be used, for instance
+ @code {.cpp}
+ template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
+ inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
+ {
+ return std::abs(a - b) <= epsilon;
+ }
+ @endcode
+
+ @note NaN values never compare equal to themselves or to other NaN values.
+
@param[in] lhs first JSON value to consider
@param[in] rhs second JSON value to consider
@return whether the values @a lhs and @a rhs are equal
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@complexity Linear.
@liveexample{The example demonstrates comparing several JSON
@@ -5352,72 +12510,56 @@ class basic_json
switch (lhs_type)
{
case value_t::array:
- {
- assert(lhs.m_value.array != nullptr);
- assert(rhs.m_value.array != nullptr);
- return *lhs.m_value.array == *rhs.m_value.array;
- }
+ return (*lhs.m_value.array == *rhs.m_value.array);
+
case value_t::object:
- {
- assert(lhs.m_value.object != nullptr);
- assert(rhs.m_value.object != nullptr);
- return *lhs.m_value.object == *rhs.m_value.object;
- }
+ return (*lhs.m_value.object == *rhs.m_value.object);
+
case value_t::null:
- {
return true;
- }
+
case value_t::string:
- {
- assert(lhs.m_value.string != nullptr);
- assert(rhs.m_value.string != nullptr);
- return *lhs.m_value.string == *rhs.m_value.string;
- }
+ return (*lhs.m_value.string == *rhs.m_value.string);
+
case value_t::boolean:
- {
- return lhs.m_value.boolean == rhs.m_value.boolean;
- }
+ return (lhs.m_value.boolean == rhs.m_value.boolean);
+
case value_t::number_integer:
- {
- return lhs.m_value.number_integer == rhs.m_value.number_integer;
- }
+ return (lhs.m_value.number_integer == rhs.m_value.number_integer);
+
case value_t::number_unsigned:
- {
- return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
- }
+ return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
+
case value_t::number_float:
- {
- return lhs.m_value.number_float == rhs.m_value.number_float;
- }
+ return (lhs.m_value.number_float == rhs.m_value.number_float);
+
default:
- {
return false;
- }
}
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
{
- return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
+ return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
}
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
{
- return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
+ return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
}
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
{
- return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
+ return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
}
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
{
- return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
+ return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
}
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
{
- return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+ return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
{
- return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+ return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
}
return false;
@@ -5425,34 +12567,24 @@ class basic_json
/*!
@brief comparison: equal
-
- The functions compares the given JSON value against a null pointer. As the
- null pointer can be used to initialize a JSON value to null, a comparison
- of JSON value @a v with a null pointer should be equivalent to call
- `v.is_null()`.
-
- @param[in] v JSON value to consider
- @return whether @a v is null
-
- @complexity Constant.
-
- @liveexample{The example compares several JSON types to the null pointer.
- ,operator__equal__nullptr_t}
-
- @since version 1.0.0
+ @copydoc operator==(const_reference, const_reference)
*/
- friend bool operator==(const_reference v, std::nullptr_t) noexcept
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
{
- return v.is_null();
+ return (lhs == basic_json(rhs));
}
/*!
@brief comparison: equal
- @copydoc operator==(const_reference, std::nullptr_t)
+ @copydoc operator==(const_reference, const_reference)
*/
- friend bool operator==(std::nullptr_t, const_reference v) noexcept
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
{
- return v.is_null();
+ return (basic_json(lhs) == rhs);
}
/*!
@@ -5466,6 +12598,8 @@ class basic_json
@complexity Linear.
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@liveexample{The example demonstrates comparing several JSON
types.,operator__notequal}
@@ -5478,34 +12612,24 @@ class basic_json
/*!
@brief comparison: not equal
-
- The functions compares the given JSON value against a null pointer. As the
- null pointer can be used to initialize a JSON value to null, a comparison
- of JSON value @a v with a null pointer should be equivalent to call
- `not v.is_null()`.
-
- @param[in] v JSON value to consider
- @return whether @a v is not null
-
- @complexity Constant.
-
- @liveexample{The example compares several JSON types to the null pointer.
- ,operator__notequal__nullptr_t}
-
- @since version 1.0.0
+ @copydoc operator!=(const_reference, const_reference)
*/
- friend bool operator!=(const_reference v, std::nullptr_t) noexcept
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
{
- return not v.is_null();
+ return (lhs != basic_json(rhs));
}
/*!
@brief comparison: not equal
- @copydoc operator!=(const_reference, std::nullptr_t)
+ @copydoc operator!=(const_reference, const_reference)
*/
- friend bool operator!=(std::nullptr_t, const_reference v) noexcept
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
{
- return not v.is_null();
+ return (basic_json(lhs) != rhs);
}
/*!
@@ -5527,6 +12651,8 @@ class basic_json
@complexity Linear.
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@liveexample{The example demonstrates comparing several JSON
types.,operator__less}
@@ -5542,47 +12668,31 @@ class basic_json
switch (lhs_type)
{
case value_t::array:
- {
- assert(lhs.m_value.array != nullptr);
- assert(rhs.m_value.array != nullptr);
- return *lhs.m_value.array < *rhs.m_value.array;
- }
+ return (*lhs.m_value.array) < (*rhs.m_value.array);
+
case value_t::object:
- {
- assert(lhs.m_value.object != nullptr);
- assert(rhs.m_value.object != nullptr);
return *lhs.m_value.object < *rhs.m_value.object;
- }
+
case value_t::null:
- {
return false;
- }
+
case value_t::string:
- {
- assert(lhs.m_value.string != nullptr);
- assert(rhs.m_value.string != nullptr);
return *lhs.m_value.string < *rhs.m_value.string;
- }
+
case value_t::boolean:
- {
return lhs.m_value.boolean < rhs.m_value.boolean;
- }
+
case value_t::number_integer:
- {
return lhs.m_value.number_integer < rhs.m_value.number_integer;
- }
+
case value_t::number_unsigned:
- {
return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
- }
+
case value_t::number_float:
- {
return lhs.m_value.number_float < rhs.m_value.number_float;
- }
+
default:
- {
return false;
- }
}
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
@@ -5617,6 +12727,28 @@ class basic_json
}
/*!
+ @brief comparison: less than
+ @copydoc operator<(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
+ {
+ return (lhs < basic_json(rhs));
+ }
+
+ /*!
+ @brief comparison: less than
+ @copydoc operator<(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
+ {
+ return (basic_json(lhs) < rhs);
+ }
+
+ /*!
@brief comparison: less than or equal
Compares whether one JSON value @a lhs is less than or equal to another
@@ -5628,6 +12760,8 @@ class basic_json
@complexity Linear.
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@liveexample{The example demonstrates comparing several JSON
types.,operator__greater}
@@ -5639,6 +12773,28 @@ class basic_json
}
/*!
+ @brief comparison: less than or equal
+ @copydoc operator<=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
+ {
+ return (lhs <= basic_json(rhs));
+ }
+
+ /*!
+ @brief comparison: less than or equal
+ @copydoc operator<=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
+ {
+ return (basic_json(lhs) <= rhs);
+ }
+
+ /*!
@brief comparison: greater than
Compares whether one JSON value @a lhs is greater than another
@@ -5650,6 +12806,8 @@ class basic_json
@complexity Linear.
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@liveexample{The example demonstrates comparing several JSON
types.,operator__lessequal}
@@ -5661,6 +12819,28 @@ class basic_json
}
/*!
+ @brief comparison: greater than
+ @copydoc operator>(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
+ {
+ return (lhs > basic_json(rhs));
+ }
+
+ /*!
+ @brief comparison: greater than
+ @copydoc operator>(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
+ {
+ return (basic_json(lhs) > rhs);
+ }
+
+ /*!
@brief comparison: greater than or equal
Compares whether one JSON value @a lhs is greater than or equal to another
@@ -5672,6 +12852,8 @@ class basic_json
@complexity Linear.
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
@liveexample{The example demonstrates comparing several JSON
types.,operator__greaterequal}
@@ -5682,8 +12864,29 @@ class basic_json
return not (lhs < rhs);
}
- /// @}
+ /*!
+ @brief comparison: greater than or equal
+ @copydoc operator>=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
+ {
+ return (lhs >= basic_json(rhs));
+ }
+
+ /*!
+ @brief comparison: greater than or equal
+ @copydoc operator>=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
+ {
+ return (basic_json(lhs) >= rhs);
+ }
+ /// @}
///////////////////
// serialization //
@@ -5696,23 +12899,32 @@ class basic_json
@brief serialize to stream
Serialize the given JSON value @a j to the output stream @a o. The JSON
- value will be serialized using the @ref dump member function. The
- indentation of the output can be controlled with the member variable
- `width` of the output stream @a o. For instance, using the manipulator
- `std::setw(4)` on @a o sets the indentation level to `4` and the
- serialization result is the same as calling `dump(4)`.
+ value will be serialized using the @ref dump member function.
+
+ - The indentation of the output can be controlled with the member variable
+ `width` of the output stream @a o. For instance, using the manipulator
+ `std::setw(4)` on @a o sets the indentation level to `4` and the
+ serialization result is the same as calling `dump(4)`.
+
+ - The indentation character can be controlled with the member variable
+ `fill` of the output stream @a o. For instance, the manipulator
+ `std::setfill('\\t')` sets indentation to use a tab character rather than
+ the default space character.
@param[in,out] o stream to serialize to
@param[in] j JSON value to serialize
@return the stream @a o
+ @throw type_error.316 if a string stored inside the JSON value is not
+ UTF-8 encoded
+
@complexity Linear.
@liveexample{The example below shows the serialization with different
parameters to `width` to adjust the indentation level.,operator_serialize}
- @since version 1.0.0
+ @since version 1.0.0; indentation character added in version 3.0.0
*/
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
{
@@ -5724,14 +12936,20 @@ class basic_json
o.width(0);
// do the actual serialization
- j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
+ serializer s(detail::output_adapter<char>(o), o.fill());
+ s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
return o;
}
/*!
@brief serialize to stream
- @copydoc operator<<(std::ostream&, const basic_json&)
+ @deprecated This stream operator is deprecated and will be removed in a
+ future version of the library. Please use
+ @ref operator<<(std::ostream&, const basic_json&)
+ instead; that is, replace calls like `j >> o;` with `o << j;`.
+ @since version 1.0.0; deprecated since version 3.0.0
*/
+ JSON_DEPRECATED
friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
{
return o << j;
@@ -5748,69 +12966,179 @@ class basic_json
/// @{
/*!
- @brief deserialize from string
-
- @param[in] s string to read a serialized JSON value from
- @param[in] cb a parser callback function of type @ref parser_callback_t
+ @brief deserialize from a compatible input
+
+ This function reads from a compatible input. Examples are:
+ - an array of 1-byte values
+ - strings with character/literal type with size of 1 byte
+ - input streams
+ - container with contiguous storage of 1-byte values. Compatible container
+ types include `std::vector`, `std::string`, `std::array`,
+ `std::valarray`, and `std::initializer_list`. Furthermore, C-style
+ arrays can be used with `std::begin()`/`std::end()`. User-defined
+ containers can be used as long as they implement random-access iterators
+ and a contiguous storage.
+
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @pre The container storage is contiguous. Violating this precondition
+ yields undefined behavior. **This precondition is enforced with an
+ assertion.**
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @warning There is no way to enforce all preconditions at compile-time. If
+ the function is called with a noncompliant container and with
+ assertions switched off, the behavior is undefined and will most
+ likely yield segmentation violation.
+
+ @param[in] i input to read from
+ @param[in] cb a parser callback function of type @ref parser_callback_t
which is used to control the deserialization by filtering unwanted values
(optional)
@return result of the deserialization
+ @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+ of input; expected string literal""`
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
@complexity Linear in the length of the input. The parser is a predictive
LL(1) parser. The complexity can be higher if the parser callback function
@a cb has a super-linear complexity.
@note A UTF-8 byte order mark is silently ignored.
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from an array.,parse__array__parser_callback_t}
+
@liveexample{The example below demonstrates the `parse()` function with
and without callback function.,parse__string__parser_callback_t}
- @sa @ref parse(std::istream&, parser_callback_t) for a version that reads
- from an input stream
+ @liveexample{The example below demonstrates the `parse()` function with
+ and without callback function.,parse__istream__parser_callback_t}
+
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
- @since version 1.0.0
+ @since version 2.0.3 (contiguous containers)
*/
- static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
+ static basic_json parse(detail::input_adapter i,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions = true)
{
- return parser(s, cb).parse();
+ basic_json result;
+ parser(i, cb, allow_exceptions).parse(true, result);
+ return result;
}
/*!
- @brief deserialize from stream
+ @copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
+ */
+ static basic_json parse(detail::input_adapter& i,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ parser(i, cb, allow_exceptions).parse(true, result);
+ return result;
+ }
+
+ static bool accept(detail::input_adapter i)
+ {
+ return parser(i).accept(true);
+ }
+
+ static bool accept(detail::input_adapter& i)
+ {
+ return parser(i).accept(true);
+ }
- @param[in,out] i stream to read a serialized JSON value from
- @param[in] cb a parser callback function of type @ref parser_callback_t
+ /*!
+ @brief deserialize from an iterator range with contiguous storage
+
+ This function reads from an iterator range of a container with contiguous
+ storage of 1-byte values. Compatible container types include
+ `std::vector`, `std::string`, `std::array`, `std::valarray`, and
+ `std::initializer_list`. Furthermore, C-style arrays can be used with
+ `std::begin()`/`std::end()`. User-defined containers can be used as long
+ as they implement random-access iterators and a contiguous storage.
+
+ @pre The iterator range is contiguous. Violating this precondition yields
+ undefined behavior. **This precondition is enforced with an assertion.**
+ @pre Each element in the range has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @warning There is no way to enforce all preconditions at compile-time. If
+ the function is called with noncompliant iterators and with
+ assertions switched off, the behavior is undefined and will most
+ likely yield segmentation violation.
+
+ @tparam IteratorType iterator of container with contiguous storage
+ @param[in] first begin of the range to parse (included)
+ @param[in] last end of the range to parse (excluded)
+ @param[in] cb a parser callback function of type @ref parser_callback_t
which is used to control the deserialization by filtering unwanted values
(optional)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
@return result of the deserialization
+ @throw parse_error.101 in case of an unexpected token
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
@complexity Linear in the length of the input. The parser is a predictive
LL(1) parser. The complexity can be higher if the parser callback function
@a cb has a super-linear complexity.
@note A UTF-8 byte order mark is silently ignored.
- @liveexample{The example below demonstrates the `parse()` function with
- and without callback function.,parse__istream__parser_callback_t}
-
- @sa @ref parse(const string_t&, parser_callback_t) for a version that
- reads from a string
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from an iterator range.,parse__iteratortype__parser_callback_t}
- @since version 1.0.0
+ @since version 2.0.3
*/
- static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
+ template<class IteratorType, typename std::enable_if<
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+ static basic_json parse(IteratorType first, IteratorType last,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
+ return result;
+ }
+
+ template<class IteratorType, typename std::enable_if<
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+ static bool accept(IteratorType first, IteratorType last)
{
- return parser(i, cb).parse();
+ return parser(detail::input_adapter(first, last)).accept(true);
}
/*!
- @copydoc parse(std::istream&, parser_callback_t)
+ @brief deserialize from stream
+ @deprecated This stream operator is deprecated and will be removed in a
+ future version of the library. Please use
+ @ref operator>>(std::istream&, basic_json&)
+ instead; that is, replace calls like `j << i;` with `i >> j;`.
+ @since version 1.0.0; deprecated since version 3.0.0
*/
- static basic_json parse(std::istream&& i, parser_callback_t cb = nullptr)
+ JSON_DEPRECATED
+ friend std::istream& operator<<(basic_json& j, std::istream& i)
{
- return parser(i, cb).parse();
+ return operator>>(i, j);
}
/*!
@@ -5821,7 +13149,9 @@ class basic_json
@param[in,out] i input stream to read a serialized JSON value from
@param[in,out] j JSON value to write the deserialized input to
- @throw std::invalid_argument in case of parse errors
+ @throw parse_error.101 in case of an unexpected token
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
@complexity Linear in the length of the input. The parser is a predictive
LL(1) parser.
@@ -5831,448 +13161,76 @@ class basic_json
@liveexample{The example below shows how a JSON value is constructed by
reading a serialization from a stream.,operator_deserialize}
- @sa parse(std::istream&, parser_callback_t) for a variant with a parser
- callback function to filter values while parsing
+ @sa parse(std::istream&, const parser_callback_t) for a variant with a
+ parser callback function to filter values while parsing
@since version 1.0.0
*/
- friend std::istream& operator<<(basic_json& j, std::istream& i)
- {
- j = parser(i).parse();
- return i;
- }
-
- /*!
- @brief deserialize from stream
- @copydoc operator<<(basic_json&, std::istream&)
- */
friend std::istream& operator>>(std::istream& i, basic_json& j)
{
- j = parser(i).parse();
+ parser(detail::input_adapter(i)).parse(false, j);
return i;
}
/// @}
-
- private:
///////////////////////////
// convenience functions //
///////////////////////////
- /// return the type as string
- string_t type_name() const noexcept
- {
- switch (m_type)
- {
- case value_t::null:
- return "null";
- case value_t::object:
- return "object";
- case value_t::array:
- return "array";
- case value_t::string:
- return "string";
- case value_t::boolean:
- return "boolean";
- case value_t::discarded:
- return "discarded";
- default:
- return "number";
- }
- }
-
/*!
- @brief calculates the extra space to escape a JSON string
-
- @param[in] s the string to escape
- @return the number of characters required to escape string @a s
-
- @complexity Linear in the length of string @a s.
- */
- static std::size_t extra_space(const string_t& s) noexcept
- {
- std::size_t result = 0;
+ @brief return the type as string
- for (const auto& c : s)
- {
- switch (c)
- {
- case '"':
- case '\\':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- {
- // from c (1 byte) to \x (2 bytes)
- result += 1;
- break;
- }
+ Returns the type name as string to be used in error messages - usually to
+ indicate that a function was called on a wrong JSON type.
- default:
- {
- if (c >= 0x00 and c <= 0x1f)
- {
- // from c (1 byte) to \uxxxx (6 bytes)
- result += 5;
- }
- break;
- }
- }
- }
+ @return a string representation of a the @a m_type member:
+ Value type | return value
+ ----------- | -------------
+ null | `"null"`
+ boolean | `"boolean"`
+ string | `"string"`
+ number | `"number"` (for all number types)
+ object | `"object"`
+ array | `"array"`
+ discarded | `"discarded"`
- return result;
- }
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
- /*!
- @brief escape a string
+ @complexity Constant.
- Escape a string by replacing certain special characters by a sequence of
- an escape character (backslash) and another character and other control
- characters by a sequence of "\u" followed by a four-digit hex
- representation.
+ @liveexample{The following code exemplifies `type_name()` for all JSON
+ types.,type_name}
- @param[in] s the string to escape
- @return the escaped string
+ @sa @ref type() -- return the type of the JSON value
+ @sa @ref operator value_t() -- return the type of the JSON value (implicit)
- @complexity Linear in the length of string @a s.
+ @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
+ since 3.0.0
*/
- static string_t escape_string(const string_t& s)
+ const char* type_name() const noexcept
{
- const auto space = extra_space(s);
- if (space == 0)
{
- return s;
- }
-
- // create a result string of necessary size
- string_t result(s.size() + space, '\\');
- std::size_t pos = 0;
-
- for (const auto& c : s)
- {
- switch (c)
+ switch (m_type)
{
- // quotation mark (0x22)
- case '"':
- {
- result[pos + 1] = '"';
- pos += 2;
- break;
- }
-
- // reverse solidus (0x5c)
- case '\\':
- {
- // nothing to change
- pos += 2;
- break;
- }
-
- // backspace (0x08)
- case '\b':
- {
- result[pos + 1] = 'b';
- pos += 2;
- break;
- }
-
- // formfeed (0x0c)
- case '\f':
- {
- result[pos + 1] = 'f';
- pos += 2;
- break;
- }
-
- // newline (0x0a)
- case '\n':
- {
- result[pos + 1] = 'n';
- pos += 2;
- break;
- }
-
- // carriage return (0x0d)
- case '\r':
- {
- result[pos + 1] = 'r';
- pos += 2;
- break;
- }
-
- // horizontal tab (0x09)
- case '\t':
- {
- result[pos + 1] = 't';
- pos += 2;
- break;
- }
-
+ case value_t::null:
+ return "null";
+ case value_t::object:
+ return "object";
+ case value_t::array:
+ return "array";
+ case value_t::string:
+ return "string";
+ case value_t::boolean:
+ return "boolean";
+ case value_t::discarded:
+ return "discarded";
default:
- {
- if (c >= 0x00 and c <= 0x1f)
- {
- // convert a number 0..15 to its hex representation
- // (0..f)
- const auto hexify = [](const int v) -> char
- {
- return (v < 10)
- ? ('0' + static_cast<char>(v))
- : ('a' + static_cast<char>((v - 10) & 0x1f));
- };
-
- // print character c as \uxxxx
- for (const char m :
- { 'u', '0', '0', hexify(c >> 4), hexify(c & 0x0f)
- })
- {
- result[++pos] = m;
- }
-
- ++pos;
- }
- else
- {
- // all other characters are added as-is
- result[pos++] = c;
- }
- break;
- }
+ return "number";
}
}
-
- return result;
}
- /*!
- @brief internal implementation of the serialization function
-
- This function is called by the public member function dump and organizes
- the serialization internally. The indentation level is propagated as
- additional parameter. In case of arrays and objects, the function is
- called recursively. Note that
-
- - strings and object keys are escaped using `escape_string()`
- - integer numbers are converted implicitly via `operator<<`
- - floating-point numbers are converted to a string using `"%g"` format
-
- @param[out] o stream to write to
- @param[in] pretty_print whether the output shall be pretty-printed
- @param[in] indent_step the indent level
- @param[in] current_indent the current indent level (only used internally)
- */
- void dump(std::ostream& o,
- const bool pretty_print,
- const unsigned int indent_step,
- const unsigned int current_indent = 0) const
- {
- // variable to hold indentation for recursive calls
- unsigned int new_indent = current_indent;
-
- switch (m_type)
- {
- case value_t::object:
- {
- assert(m_value.object != nullptr);
-
- if (m_value.object->empty())
- {
- o << "{}";
- return;
- }
-
- o << "{";
-
- // increase indentation
- if (pretty_print)
- {
- new_indent += indent_step;
- o << "\n";
- }
-
- for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
- {
- if (i != m_value.object->cbegin())
- {
- o << (pretty_print ? ",\n" : ",");
- }
- o << string_t(new_indent, ' ') << "\""
- << escape_string(i->first) << "\":"
- << (pretty_print ? " " : "");
- i->second.dump(o, pretty_print, indent_step, new_indent);
- }
-
- // decrease indentation
- if (pretty_print)
- {
- new_indent -= indent_step;
- o << "\n";
- }
-
- o << string_t(new_indent, ' ') + "}";
- return;
- }
-
- case value_t::array:
- {
- assert(m_value.array != nullptr);
-
- if (m_value.array->empty())
- {
- o << "[]";
- return;
- }
-
- o << "[";
-
- // increase indentation
- if (pretty_print)
- {
- new_indent += indent_step;
- o << "\n";
- }
-
- for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
- {
- if (i != m_value.array->cbegin())
- {
- o << (pretty_print ? ",\n" : ",");
- }
- o << string_t(new_indent, ' ');
- i->dump(o, pretty_print, indent_step, new_indent);
- }
-
- // decrease indentation
- if (pretty_print)
- {
- new_indent -= indent_step;
- o << "\n";
- }
-
- o << string_t(new_indent, ' ') << "]";
- return;
- }
-
- case value_t::string:
- {
- assert(m_value.string != nullptr);
- o << string_t("\"") << escape_string(*m_value.string) << "\"";
- return;
- }
-
- case value_t::boolean:
- {
- o << (m_value.boolean ? "true" : "false");
- return;
- }
-
- case value_t::number_integer:
- {
- o << m_value.number_integer;
- return;
- }
-
- case value_t::number_unsigned:
- {
- o << m_value.number_unsigned;
- return;
- }
-
- case value_t::number_float:
- {
- // check if number was parsed from a string
- if (m_type.bits.parsed)
- {
- // check if parsed number had an exponent given
- if (m_type.bits.has_exp)
- {
- // buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
- char buf[263];
- int len;
-
- // handle capitalization of the exponent
- if (m_type.bits.exp_cap)
- {
- len = snprintf(buf, sizeof(buf), "%.*E",
- m_type.bits.precision, m_value.number_float) + 1;
- }
- else
- {
- len = snprintf(buf, sizeof(buf), "%.*e",
- m_type.bits.precision, m_value.number_float) + 1;
- }
-
- // remove '+' sign from the exponent if necessary
- if (not m_type.bits.exp_plus)
- {
- if (len > static_cast<int>(sizeof(buf)))
- {
- len = sizeof(buf);
- }
- for (int i = 0; i < len; i++)
- {
- if (buf[i] == '+')
- {
- for (; i + 1 < len; i++)
- {
- buf[i] = buf[i + 1];
- }
- }
- }
- }
-
- o << buf;
- }
- else
- {
- // no exponent - output as a decimal
- std::stringstream ss;
- ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
- ss << std::setprecision(m_type.bits.precision)
- << std::fixed << m_value.number_float;
- o << ss.str();
- }
- }
- else
- {
- if (m_value.number_float == 0)
- {
- // special case for zero to get "0.0"/"-0.0"
- o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
- }
- else
- {
- // Otherwise 6, 15 or 16 digits of precision allows
- // round-trip IEEE 754 string->float->string,
- // string->double->string or string->long
- // double->string; to be safe, we read this value from
- // std::numeric_limits<number_float_t>::digits10
- std::stringstream ss;
- ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
- ss << std::setprecision(std::numeric_limits<double>::digits10)
- << m_value.number_float;
- o << ss.str();
- }
- }
- return;
- }
-
- case value_t::discarded:
- {
- o << "<discarded>";
- return;
- }
-
- case value_t::null:
- {
- o << "null";
- return;
- }
- }
- }
private:
//////////////////////
@@ -6280,3163 +13238,412 @@ class basic_json
//////////////////////
/// the type of the current element
- type_data_t m_type = value_t::null;
+ value_t m_type = value_t::null;
/// the value of the current element
json_value m_value = {};
+ //////////////////////////////////////////
+ // binary serialization/deserialization //
+ //////////////////////////////////////////
- private:
- ///////////////
- // iterators //
- ///////////////
+ /// @name binary serialization/deserialization support
+ /// @{
+ public:
/*!
- @brief an iterator for primitive JSON types
-
- This class models an iterator for primitive JSON types (boolean, number,
- string). It's only purpose is to allow the iterator/const_iterator classes
- to "iterate" over primitive values. Internally, the iterator is modeled by
- a `difference_type` variable. Value begin_value (`0`) models the begin,
- end_value (`1`) models past the end.
- */
- class primitive_iterator_t
- {
- public:
- /// set iterator to a defined beginning
- void set_begin() noexcept
- {
- m_it = begin_value;
- }
-
- /// set iterator to a defined past the end
- void set_end() noexcept
- {
- m_it = end_value;
- }
-
- /// return whether the iterator can be dereferenced
- constexpr bool is_begin() const noexcept
- {
- return (m_it == begin_value);
- }
-
- /// return whether the iterator is at end
- constexpr bool is_end() const noexcept
- {
- return (m_it == end_value);
- }
+ @brief create a CBOR serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+ Binary Object Representation) serialization format. CBOR is a binary
+ serialization format which aims to be more compact than JSON itself, yet
+ more efficient to parse.
+
+ The library uses the following mapping from JSON values types to
+ CBOR types according to the CBOR specification (RFC 7049):
+
+ JSON value type | value/range | CBOR type | first byte
+ --------------- | ------------------------------------------ | ---------------------------------- | ---------------
+ null | `null` | Null | 0xF6
+ boolean | `true` | True | 0xF5
+ boolean | `false` | False | 0xF4
+ number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B
+ number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A
+ number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39
+ number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38
+ number_integer | -24..-1 | Negative integer | 0x20..0x37
+ number_integer | 0..23 | Integer | 0x00..0x17
+ number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18
+ number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
+ number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
+ number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
+ number_unsigned | 0..23 | Integer | 0x00..0x17
+ number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18
+ number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
+ number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
+ number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
+ number_float | *any value* | Double-Precision Float | 0xFB
+ string | *length*: 0..23 | UTF-8 string | 0x60..0x77
+ string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
+ string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
+ string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A
+ string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B
+ array | *size*: 0..23 | array | 0x80..0x97
+ array | *size*: 23..255 | array (1 byte follow) | 0x98
+ array | *size*: 256..65535 | array (2 bytes follow) | 0x99
+ array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A
+ array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B
+ object | *size*: 0..23 | map | 0xA0..0xB7
+ object | *size*: 23..255 | map (1 byte follow) | 0xB8
+ object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
+ object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
+ object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
+
+ @note The mapping is **complete** in the sense that any JSON value type
+ can be converted to a CBOR value.
+
+ @note If NaN or Infinity are stored inside a JSON number, they are
+ serialized properly. This behavior differs from the @ref dump()
+ function which serializes NaN or Infinity to `null`.
+
+ @note The following CBOR types are not used in the conversion:
+ - byte strings (0x40..0x5F)
+ - UTF-8 strings terminated by "break" (0x7F)
+ - arrays terminated by "break" (0x9F)
+ - maps terminated by "break" (0xBF)
+ - date/time (0xC0..0xC1)
+ - bignum (0xC2..0xC3)
+ - decimal fraction (0xC4)
+ - bigfloat (0xC5)
+ - tagged items (0xC6..0xD4, 0xD8..0xDB)
+ - expected conversions (0xD5..0xD7)
+ - simple values (0xE0..0xF3, 0xF8)
+ - undefined (0xF7)
+ - half and single-precision floats (0xF9-0xFA)
+ - break (0xFF)
- /// return reference to the value to change and compare
- operator difference_type& () noexcept
- {
- return m_it;
- }
-
- /// return value to compare
- constexpr operator difference_type () const noexcept
- {
- return m_it;
- }
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
- private:
- static constexpr difference_type begin_value = 0;
- static constexpr difference_type end_value = begin_value + 1;
+ @complexity Linear in the size of the JSON value @a j.
- /// iterator as signed integer type
- difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
- };
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in CBOR format.,to_cbor}
- /*!
- @brief an iterator value
+ @sa http://cbor.io
+ @sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the
+ analogous deserialization
+ @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
- @note This structure could easily be a union, but MSVC currently does not
- allow unions members with complex constructors, see
- https://github.com/nlohmann/json/pull/105.
+ @since version 2.0.9
*/
- struct internal_iterator
- {
- /// iterator for JSON objects
- typename object_t::iterator object_iterator;
- /// iterator for JSON arrays
- typename array_t::iterator array_iterator;
- /// generic iterator for all other types
- primitive_iterator_t primitive_iterator;
-
- /// create an uninitialized internal_iterator
- internal_iterator() noexcept
- : object_iterator(), array_iterator(), primitive_iterator()
- {}
- };
-
- /// proxy class for the iterator_wrapper functions
- template<typename IteratorType>
- class iteration_proxy
+ static std::vector<uint8_t> to_cbor(const basic_json& j)
{
- private:
- /// helper class for iteration
- class iteration_proxy_internal
- {
- private:
- /// the iterator
- IteratorType anchor;
- /// an index for arrays (used to create key names)
- size_t array_index = 0;
-
- public:
- explicit iteration_proxy_internal(IteratorType it) noexcept
- : anchor(it)
- {}
-
- /// dereference operator (needed for range-based for)
- iteration_proxy_internal& operator*()
- {
- return *this;
- }
-
- /// increment operator (needed for range-based for)
- iteration_proxy_internal& operator++()
- {
- ++anchor;
- ++array_index;
-
- return *this;
- }
-
- /// inequality operator (needed for range-based for)
- bool operator!= (const iteration_proxy_internal& o) const
- {
- return anchor != o.anchor;
- }
-
- /// return key of the iterator
- typename basic_json::string_t key() const
- {
- assert(anchor.m_object != nullptr);
-
- switch (anchor.m_object->type())
- {
- // use integer array index as key
- case value_t::array:
- {
- return std::to_string(array_index);
- }
-
- // use key from the object
- case value_t::object:
- {
- return anchor.key();
- }
-
- // use an empty key for all primitive types
- default:
- {
- return "";
- }
- }
- }
-
- /// return value of the iterator
- typename IteratorType::reference value() const
- {
- return anchor.value();
- }
- };
-
- /// the container to iterate
- typename IteratorType::reference container;
-
- public:
- /// construct iteration proxy from a container
- explicit iteration_proxy(typename IteratorType::reference cont)
- : container(cont)
- {}
-
- /// return iterator begin (needed for range-based for)
- iteration_proxy_internal begin() noexcept
- {
- return iteration_proxy_internal(container.begin());
- }
-
- /// return iterator end (needed for range-based for)
- iteration_proxy_internal end() noexcept
- {
- return iteration_proxy_internal(container.end());
- }
- };
-
- public:
- /*!
- @brief a const random access iterator for the @ref basic_json class
-
- This class implements a const iterator for the @ref basic_json class. From
- this class, the @ref iterator class is derived.
-
- @requirement The class satisfies the following concept requirements:
- - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
- The iterator that can be moved to point (forward and backward) to any
- element in constant time.
+ std::vector<uint8_t> result;
+ to_cbor(j, result);
+ return result;
+ }
- @since version 1.0.0
- */
- class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
+ static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
{
- /// allow basic_json to access private members
- friend class basic_json;
-
- public:
- /// the type of the values when the iterator is dereferenced
- using value_type = typename basic_json::value_type;
- /// a type to represent differences between iterators
- using difference_type = typename basic_json::difference_type;
- /// defines a pointer to the type iterated over (value_type)
- using pointer = typename basic_json::const_pointer;
- /// defines a reference to the type iterated over (value_type)
- using reference = typename basic_json::const_reference;
- /// the category of the iterator
- using iterator_category = std::bidirectional_iterator_tag;
-
- /// default constructor
- const_iterator() = default;
-
- /// constructor for a given JSON instance
- explicit const_iterator(pointer object) noexcept
- : m_object(object)
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- m_it.object_iterator = typename object_t::iterator();
- break;
- }
-
- case basic_json::value_t::array:
- {
- m_it.array_iterator = typename array_t::iterator();
- break;
- }
-
- default:
- {
- m_it.primitive_iterator = primitive_iterator_t();
- break;
- }
- }
- }
-
- /// copy constructor given a nonconst iterator
- explicit const_iterator(const iterator& other) noexcept
- : m_object(other.m_object)
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- m_it.object_iterator = other.m_it.object_iterator;
- break;
- }
-
- case basic_json::value_t::array:
- {
- m_it.array_iterator = other.m_it.array_iterator;
- break;
- }
-
- default:
- {
- m_it.primitive_iterator = other.m_it.primitive_iterator;
- break;
- }
- }
- }
-
- /// copy constructor
- const_iterator(const const_iterator& other) noexcept
- : m_object(other.m_object), m_it(other.m_it)
- {}
-
- /// copy assignment
- const_iterator& operator=(const_iterator other) noexcept(
- std::is_nothrow_move_constructible<pointer>::value and
- std::is_nothrow_move_assignable<pointer>::value and
- std::is_nothrow_move_constructible<internal_iterator>::value and
- std::is_nothrow_move_assignable<internal_iterator>::value
- )
- {
- std::swap(m_object, other.m_object);
- std::swap(m_it, other.m_it);
- return *this;
- }
-
- private:
- /// set the iterator to the first value
- void set_begin() noexcept
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- assert(m_object->m_value.object != nullptr);
- m_it.object_iterator = m_object->m_value.object->begin();
- break;
- }
-
- case basic_json::value_t::array:
- {
- assert(m_object->m_value.array != nullptr);
- m_it.array_iterator = m_object->m_value.array->begin();
- break;
- }
-
- case basic_json::value_t::null:
- {
- // set to end so begin()==end() is true: null is empty
- m_it.primitive_iterator.set_end();
- break;
- }
-
- default:
- {
- m_it.primitive_iterator.set_begin();
- break;
- }
- }
- }
-
- /// set the iterator past the last value
- void set_end() noexcept
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- assert(m_object->m_value.object != nullptr);
- m_it.object_iterator = m_object->m_value.object->end();
- break;
- }
-
- case basic_json::value_t::array:
- {
- assert(m_object->m_value.array != nullptr);
- m_it.array_iterator = m_object->m_value.array->end();
- break;
- }
-
- default:
- {
- m_it.primitive_iterator.set_end();
- break;
- }
- }
- }
-
- public:
- /// return a reference to the value pointed to by the iterator
- reference operator*() const
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- assert(m_object->m_value.object);
- assert(m_it.object_iterator != m_object->m_value.object->end());
- return m_it.object_iterator->second;
- }
-
- case basic_json::value_t::array:
- {
- assert(m_object->m_value.array);
- assert(m_it.array_iterator != m_object->m_value.array->end());
- return *m_it.array_iterator;
- }
-
- case basic_json::value_t::null:
- {
- throw std::out_of_range("cannot get value");
- }
-
- default:
- {
- if (m_it.primitive_iterator.is_begin())
- {
- return *m_object;
- }
- else
- {
- throw std::out_of_range("cannot get value");
- }
- }
- }
- }
-
- /// dereference the iterator
- pointer operator->() const
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- assert(m_object->m_value.object);
- assert(m_it.object_iterator != m_object->m_value.object->end());
- return &(m_it.object_iterator->second);
- }
-
- case basic_json::value_t::array:
- {
- assert(m_object->m_value.array);
- assert(m_it.array_iterator != m_object->m_value.array->end());
- return &*m_it.array_iterator;
- }
-
- default:
- {
- if (m_it.primitive_iterator.is_begin())
- {
- return m_object;
- }
- else
- {
- throw std::out_of_range("cannot get value");
- }
- }
- }
- }
-
- /// post-increment (it++)
- const_iterator operator++(int)
- {
- auto result = *this;
- ++(*this);
- return result;
- }
-
- /// pre-increment (++it)
- const_iterator& operator++()
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- ++m_it.object_iterator;
- break;
- }
-
- case basic_json::value_t::array:
- {
- ++m_it.array_iterator;
- break;
- }
-
- default:
- {
- ++m_it.primitive_iterator;
- break;
- }
- }
-
- return *this;
- }
-
- /// post-decrement (it--)
- const_iterator operator--(int)
- {
- auto result = *this;
- --(*this);
- return result;
- }
-
- /// pre-decrement (--it)
- const_iterator& operator--()
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- --m_it.object_iterator;
- break;
- }
-
- case basic_json::value_t::array:
- {
- --m_it.array_iterator;
- break;
- }
-
- default:
- {
- --m_it.primitive_iterator;
- break;
- }
- }
-
- return *this;
- }
-
- /// comparison: equal
- bool operator==(const const_iterator& other) const
- {
- // if objects are not the same, the comparison is undefined
- if (m_object != other.m_object)
- {
- throw std::domain_error("cannot compare iterators of different containers");
- }
-
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- return (m_it.object_iterator == other.m_it.object_iterator);
- }
-
- case basic_json::value_t::array:
- {
- return (m_it.array_iterator == other.m_it.array_iterator);
- }
-
- default:
- {
- return (m_it.primitive_iterator == other.m_it.primitive_iterator);
- }
- }
- }
-
- /// comparison: not equal
- bool operator!=(const const_iterator& other) const
- {
- return not operator==(other);
- }
-
- /// comparison: smaller
- bool operator<(const const_iterator& other) const
- {
- // if objects are not the same, the comparison is undefined
- if (m_object != other.m_object)
- {
- throw std::domain_error("cannot compare iterators of different containers");
- }
-
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- throw std::domain_error("cannot compare order of object iterators");
- }
-
- case basic_json::value_t::array:
- {
- return (m_it.array_iterator < other.m_it.array_iterator);
- }
-
- default:
- {
- return (m_it.primitive_iterator < other.m_it.primitive_iterator);
- }
- }
- }
-
- /// comparison: less than or equal
- bool operator<=(const const_iterator& other) const
- {
- return not other.operator < (*this);
- }
-
- /// comparison: greater than
- bool operator>(const const_iterator& other) const
- {
- return not operator<=(other);
- }
-
- /// comparison: greater than or equal
- bool operator>=(const const_iterator& other) const
- {
- return not operator<(other);
- }
-
- /// add to iterator
- const_iterator& operator+=(difference_type i)
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- throw std::domain_error("cannot use offsets with object iterators");
- }
-
- case basic_json::value_t::array:
- {
- m_it.array_iterator += i;
- break;
- }
-
- default:
- {
- m_it.primitive_iterator += i;
- break;
- }
- }
-
- return *this;
- }
-
- /// subtract from iterator
- const_iterator& operator-=(difference_type i)
- {
- return operator+=(-i);
- }
-
- /// add to iterator
- const_iterator operator+(difference_type i)
- {
- auto result = *this;
- result += i;
- return result;
- }
-
- /// subtract from iterator
- const_iterator operator-(difference_type i)
- {
- auto result = *this;
- result -= i;
- return result;
- }
-
- /// return difference
- difference_type operator-(const const_iterator& other) const
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- throw std::domain_error("cannot use offsets with object iterators");
- }
-
- case basic_json::value_t::array:
- {
- return m_it.array_iterator - other.m_it.array_iterator;
- }
-
- default:
- {
- return m_it.primitive_iterator - other.m_it.primitive_iterator;
- }
- }
- }
-
- /// access to successor
- reference operator[](difference_type n) const
- {
- assert(m_object != nullptr);
-
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- throw std::domain_error("cannot use operator[] for object iterators");
- }
-
- case basic_json::value_t::array:
- {
- return *(m_it.array_iterator + n);
- }
-
- case basic_json::value_t::null:
- {
- throw std::out_of_range("cannot get value");
- }
-
- default:
- {
- if (m_it.primitive_iterator == -n)
- {
- return *m_object;
- }
- else
- {
- throw std::out_of_range("cannot get value");
- }
- }
- }
- }
-
- /// return the key of an object iterator
- typename object_t::key_type key() const
- {
- assert(m_object != nullptr);
-
- if (m_object->is_object())
- {
- return m_it.object_iterator->first;
- }
- else
- {
- throw std::domain_error("cannot use key() for non-object iterators");
- }
- }
-
- /// return the value of an iterator
- reference value() const
- {
- return operator*();
- }
-
- private:
- /// associated JSON instance
- pointer m_object = nullptr;
- /// the actual iterator of the associated instance
- internal_iterator m_it = internal_iterator();
- };
-
- /*!
- @brief a mutable random access iterator for the @ref basic_json class
-
- @requirement The class satisfies the following concept requirements:
- - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
- The iterator that can be moved to point (forward and backward) to any
- element in constant time.
- - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
- It is possible to write to the pointed-to element.
+ binary_writer<uint8_t>(o).write_cbor(j);
+ }
- @since version 1.0.0
- */
- class iterator : public const_iterator
+ static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
{
- public:
- using base_iterator = const_iterator;
- using pointer = typename basic_json::pointer;
- using reference = typename basic_json::reference;
-
- /// default constructor
- iterator() = default;
-
- /// constructor for a given JSON instance
- explicit iterator(pointer object) noexcept
- : base_iterator(object)
- {}
-
- /// copy constructor
- iterator(const iterator& other) noexcept
- : base_iterator(other)
- {}
-
- /// copy assignment
- iterator& operator=(iterator other) noexcept(
- std::is_nothrow_move_constructible<pointer>::value and
- std::is_nothrow_move_assignable<pointer>::value and
- std::is_nothrow_move_constructible<internal_iterator>::value and
- std::is_nothrow_move_assignable<internal_iterator>::value
- )
- {
- base_iterator::operator=(other);
- return *this;
- }
-
- /// return a reference to the value pointed to by the iterator
- reference operator*() const
- {
- return const_cast<reference>(base_iterator::operator*());
- }
-
- /// dereference the iterator
- pointer operator->() const
- {
- return const_cast<pointer>(base_iterator::operator->());
- }
-
- /// post-increment (it++)
- iterator operator++(int)
- {
- iterator result = *this;
- base_iterator::operator++();
- return result;
- }
-
- /// pre-increment (++it)
- iterator& operator++()
- {
- base_iterator::operator++();
- return *this;
- }
-
- /// post-decrement (it--)
- iterator operator--(int)
- {
- iterator result = *this;
- base_iterator::operator--();
- return result;
- }
-
- /// pre-decrement (--it)
- iterator& operator--()
- {
- base_iterator::operator--();
- return *this;
- }
-
- /// add to iterator
- iterator& operator+=(difference_type i)
- {
- base_iterator::operator+=(i);
- return *this;
- }
-
- /// subtract from iterator
- iterator& operator-=(difference_type i)
- {
- base_iterator::operator-=(i);
- return *this;
- }
-
- /// add to iterator
- iterator operator+(difference_type i)
- {
- auto result = *this;
- result += i;
- return result;
- }
-
- /// subtract from iterator
- iterator operator-(difference_type i)
- {
- auto result = *this;
- result -= i;
- return result;
- }
-
- /// return difference
- difference_type operator-(const iterator& other) const
- {
- return base_iterator::operator-(other);
- }
-
- /// access to successor
- reference operator[](difference_type n) const
- {
- return const_cast<reference>(base_iterator::operator[](n));
- }
-
- /// return the value of an iterator
- reference value() const
- {
- return const_cast<reference>(base_iterator::value());
- }
- };
+ binary_writer<char>(o).write_cbor(j);
+ }
/*!
- @brief a template for a reverse iterator class
-
- @tparam Base the base iterator type to reverse. Valid types are @ref
- iterator (to create @ref reverse_iterator) and @ref const_iterator (to
- create @ref const_reverse_iterator).
-
- @requirement The class satisfies the following concept requirements:
- - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
- The iterator that can be moved to point (forward and backward) to any
- element in constant time.
- - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
- It is possible to write to the pointed-to element (only if @a Base is
- @ref iterator).
-
- @since version 1.0.0
- */
- template<typename Base>
- class json_reverse_iterator : public std::reverse_iterator<Base>
- {
- public:
- /// shortcut to the reverse iterator adaptor
- using base_iterator = std::reverse_iterator<Base>;
- /// the reference type for the pointed-to element
- using reference = typename Base::reference;
-
- /// create reverse iterator from iterator
- json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
- : base_iterator(it)
- {}
-
- /// create reverse iterator from base class
- json_reverse_iterator(const base_iterator& it) noexcept
- : base_iterator(it)
- {}
+ @brief create a MessagePack serialization of a given JSON value
- /// post-increment (it++)
- json_reverse_iterator operator++(int)
- {
- return base_iterator::operator++(1);
- }
+ Serializes a given JSON value @a j to a byte vector using the MessagePack
+ serialization format. MessagePack is a binary serialization format which
+ aims to be more compact than JSON itself, yet more efficient to parse.
- /// pre-increment (++it)
- json_reverse_iterator& operator++()
- {
- base_iterator::operator++();
- return *this;
- }
+ The library uses the following mapping from JSON values types to
+ MessagePack types according to the MessagePack specification:
- /// post-decrement (it--)
- json_reverse_iterator operator--(int)
- {
- return base_iterator::operator--(1);
- }
+ JSON value type | value/range | MessagePack type | first byte
+ --------------- | --------------------------------- | ---------------- | ----------
+ null | `null` | nil | 0xC0
+ boolean | `true` | true | 0xC3
+ boolean | `false` | false | 0xC2
+ number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3
+ number_integer | -2147483648..-32769 | int32 | 0xD2
+ number_integer | -32768..-129 | int16 | 0xD1
+ number_integer | -128..-33 | int8 | 0xD0
+ number_integer | -32..-1 | negative fixint | 0xE0..0xFF
+ number_integer | 0..127 | positive fixint | 0x00..0x7F
+ number_integer | 128..255 | uint 8 | 0xCC
+ number_integer | 256..65535 | uint 16 | 0xCD
+ number_integer | 65536..4294967295 | uint 32 | 0xCE
+ number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF
+ number_unsigned | 0..127 | positive fixint | 0x00..0x7F
+ number_unsigned | 128..255 | uint 8 | 0xCC
+ number_unsigned | 256..65535 | uint 16 | 0xCD
+ number_unsigned | 65536..4294967295 | uint 32 | 0xCE
+ number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
+ number_float | *any value* | float 64 | 0xCB
+ string | *length*: 0..31 | fixstr | 0xA0..0xBF
+ string | *length*: 32..255 | str 8 | 0xD9
+ string | *length*: 256..65535 | str 16 | 0xDA
+ string | *length*: 65536..4294967295 | str 32 | 0xDB
+ array | *size*: 0..15 | fixarray | 0x90..0x9F
+ array | *size*: 16..65535 | array 16 | 0xDC
+ array | *size*: 65536..4294967295 | array 32 | 0xDD
+ object | *size*: 0..15 | fix map | 0x80..0x8F
+ object | *size*: 16..65535 | map 16 | 0xDE
+ object | *size*: 65536..4294967295 | map 32 | 0xDF
- /// pre-decrement (--it)
- json_reverse_iterator& operator--()
- {
- base_iterator::operator--();
- return *this;
- }
+ @note The mapping is **complete** in the sense that any JSON value type
+ can be converted to a MessagePack value.
- /// add to iterator
- json_reverse_iterator& operator+=(difference_type i)
- {
- base_iterator::operator+=(i);
- return *this;
- }
+ @note The following values can **not** be converted to a MessagePack value:
+ - strings with more than 4294967295 bytes
+ - arrays with more than 4294967295 elements
+ - objects with more than 4294967295 elements
- /// add to iterator
- json_reverse_iterator operator+(difference_type i) const
- {
- auto result = *this;
- result += i;
- return result;
- }
+ @note The following MessagePack types are not used in the conversion:
+ - bin 8 - bin 32 (0xC4..0xC6)
+ - ext 8 - ext 32 (0xC7..0xC9)
+ - float 32 (0xCA)
+ - fixext 1 - fixext 16 (0xD4..0xD8)
- /// subtract from iterator
- json_reverse_iterator operator-(difference_type i) const
- {
- auto result = *this;
- result -= i;
- return result;
- }
+ @note Any MessagePack output created @ref to_msgpack can be successfully
+ parsed by @ref from_msgpack.
- /// return difference
- difference_type operator-(const json_reverse_iterator& other) const
- {
- return this->base() - other.base();
- }
+ @note If NaN or Infinity are stored inside a JSON number, they are
+ serialized properly. This behavior differs from the @ref dump()
+ function which serializes NaN or Infinity to `null`.
- /// access to successor
- reference operator[](difference_type n) const
- {
- return *(this->operator+(n));
- }
-
- /// return the key of an object iterator
- typename object_t::key_type key() const
- {
- auto it = --this->base();
- return it.key();
- }
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
- /// return the value of an iterator
- reference value() const
- {
- auto it = --this->base();
- return it.operator * ();
- }
- };
+ @complexity Linear in the size of the JSON value @a j.
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in MessagePack format.,to_msgpack}
- private:
- //////////////////////
- // lexer and parser //
- //////////////////////
+ @sa http://msgpack.org
+ @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
+ analogous deserialization
+ @sa @ref to_cbor(const basic_json& for the related CBOR format
- /*!
- @brief lexical analysis
-
- This class organizes the lexical analysis during JSON deserialization. The
- core of it is a scanner generated by [re2c](http://re2c.org) that
- processes a buffer and recognizes tokens according to RFC 7159.
+ @since version 2.0.9
*/
- class lexer
+ static std::vector<uint8_t> to_msgpack(const basic_json& j)
{
- public:
- /// token types for the parser
- enum class token_type
- {
- uninitialized, ///< indicating the scanner is uninitialized
- literal_true, ///< the `true` literal
- literal_false, ///< the `false` literal
- literal_null, ///< the `null` literal
- value_string, ///< a string -- use get_string() for actual value
- value_number, ///< a number -- use get_number() for actual value
- begin_array, ///< the character for array begin `[`
- begin_object, ///< the character for object begin `{`
- end_array, ///< the character for array end `]`
- end_object, ///< the character for object end `}`
- name_separator, ///< the name separator `:`
- value_separator, ///< the value separator `,`
- parse_error, ///< indicating a parse error
- end_of_input ///< indicating the end of the input buffer
- };
-
- /// the char type to use in the lexer
- using lexer_char_t = unsigned char;
-
- /// constructor with a given buffer
- explicit lexer(const string_t& s) noexcept
- : m_stream(nullptr), m_buffer(s)
- {
- m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
- assert(m_content != nullptr);
- m_start = m_cursor = m_content;
- m_limit = m_content + s.size();
- }
-
- /// constructor with a given stream
- explicit lexer(std::istream* s) noexcept
- : m_stream(s), m_buffer()
- {
- assert(m_stream != nullptr);
- getline(*m_stream, m_buffer);
- m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
- assert(m_content != nullptr);
- m_start = m_cursor = m_content;
- m_limit = m_content + m_buffer.size();
- }
-
- /// default constructor
- lexer() = default;
-
- // switch off unwanted functions
- lexer(const lexer&) = delete;
- lexer operator=(const lexer&) = delete;
-
- /*!
- @brief create a string from a Unicode code point
-
- @param[in] codepoint1 the code point (can be high surrogate)
- @param[in] codepoint2 the code point (can be low surrogate or 0)
-
- @return string representation of the code point
-
- @throw std::out_of_range if code point is > 0x10ffff; example: `"code
- points above 0x10FFFF are invalid"`
- @throw std::invalid_argument if the low surrogate is invalid; example:
- `""missing or wrong low surrogate""`
-
- @see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
- */
- static string_t to_unicode(const std::size_t codepoint1,
- const std::size_t codepoint2 = 0)
- {
- // calculate the codepoint from the given code points
- std::size_t codepoint = codepoint1;
-
- // check if codepoint1 is a high surrogate
- if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
- {
- // check if codepoint2 is a low surrogate
- if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
- {
- codepoint =
- // high surrogate occupies the most significant 22 bits
- (codepoint1 << 10)
- // low surrogate occupies the least significant 15 bits
- + codepoint2
- // there is still the 0xD800, 0xDC00 and 0x10000 noise
- // in the result so we have to subtract with:
- // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- - 0x35FDC00;
- }
- else
- {
- throw std::invalid_argument("missing or wrong low surrogate");
- }
- }
-
- string_t result;
-
- if (codepoint < 0x80)
- {
- // 1-byte characters: 0xxxxxxx (ASCII)
- result.append(1, static_cast<typename string_t::value_type>(codepoint));
- }
- else if (codepoint <= 0x7ff)
- {
- // 2-byte characters: 110xxxxx 10xxxxxx
- result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
- result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
- }
- else if (codepoint <= 0xffff)
- {
- // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
- result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
- result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
- result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
- }
- else if (codepoint <= 0x10ffff)
- {
- // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
- result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
- result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
- result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
- }
- else
- {
- throw std::out_of_range("code points above 0x10FFFF are invalid");
- }
-
- return result;
- }
-
- /// return name of values of type token_type (only used for errors)
- static std::string token_type_name(token_type t)
- {
- switch (t)
- {
- case token_type::uninitialized:
- return "<uninitialized>";
- case token_type::literal_true:
- return "true literal";
- case token_type::literal_false:
- return "false literal";
- case token_type::literal_null:
- return "null literal";
- case token_type::value_string:
- return "string literal";
- case token_type::value_number:
- return "number literal";
- case token_type::begin_array:
- return "'['";
- case token_type::begin_object:
- return "'{'";
- case token_type::end_array:
- return "']'";
- case token_type::end_object:
- return "'}'";
- case token_type::name_separator:
- return "':'";
- case token_type::value_separator:
- return "','";
- case token_type::parse_error:
- return "<parse error>";
- case token_type::end_of_input:
- return "end of input";
- default:
- {
- // catch non-enum values
- return "unknown token"; // LCOV_EXCL_LINE
- }
- }
- }
-
- /*!
- This function implements a scanner for JSON. It is specified using
- regular expressions that try to follow RFC 7159 as close as possible.
- These regular expressions are then translated into a minimized
- deterministic finite automaton (DFA) by the tool
- [re2c](http://re2c.org). As a result, the translated code for this
- function consists of a large block of code with `goto` jumps.
-
- @return the class of the next token read from the buffer
- */
- token_type scan() noexcept
- {
- // pointer for backtracking information
- m_marker = nullptr;
-
- // remember the begin of the token
- m_start = m_cursor;
- assert(m_start != nullptr);
-
-
- {
- lexer_char_t yych;
- unsigned int yyaccept = 0;
- static const unsigned char yybm[] =
- {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 32, 32, 0, 0, 32, 0, 0,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 160, 128, 0, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 192, 192, 192, 192, 192, 192, 192, 192,
- 192, 192, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 0, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- };
- if ((m_limit - m_cursor) < 5)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yybm[0 + yych] & 32)
- {
- goto basic_json_parser_6;
- }
- if (yych <= '\\')
- {
- if (yych <= '-')
- {
- if (yych <= '"')
- {
- if (yych <= 0x00)
- {
- goto basic_json_parser_2;
- }
- if (yych <= '!')
- {
- goto basic_json_parser_4;
- }
- goto basic_json_parser_9;
- }
- else
- {
- if (yych <= '+')
- {
- goto basic_json_parser_4;
- }
- if (yych <= ',')
- {
- goto basic_json_parser_10;
- }
- goto basic_json_parser_12;
- }
- }
- else
- {
- if (yych <= '9')
- {
- if (yych <= '/')
- {
- goto basic_json_parser_4;
- }
- if (yych <= '0')
- {
- goto basic_json_parser_13;
- }
- goto basic_json_parser_15;
- }
- else
- {
- if (yych <= ':')
- {
- goto basic_json_parser_17;
- }
- if (yych == '[')
- {
- goto basic_json_parser_19;
- }
- goto basic_json_parser_4;
- }
- }
- }
- else
- {
- if (yych <= 't')
- {
- if (yych <= 'f')
- {
- if (yych <= ']')
- {
- goto basic_json_parser_21;
- }
- if (yych <= 'e')
- {
- goto basic_json_parser_4;
- }
- goto basic_json_parser_23;
- }
- else
- {
- if (yych == 'n')
- {
- goto basic_json_parser_24;
- }
- if (yych <= 's')
- {
- goto basic_json_parser_4;
- }
- goto basic_json_parser_25;
- }
- }
- else
- {
- if (yych <= '|')
- {
- if (yych == '{')
- {
- goto basic_json_parser_26;
- }
- goto basic_json_parser_4;
- }
- else
- {
- if (yych <= '}')
- {
- goto basic_json_parser_28;
- }
- if (yych == 0xEF)
- {
- goto basic_json_parser_30;
- }
- goto basic_json_parser_4;
- }
- }
- }
-basic_json_parser_2:
- ++m_cursor;
- {
- return token_type::end_of_input;
- }
-basic_json_parser_4:
- ++m_cursor;
-basic_json_parser_5:
- {
- return token_type::parse_error;
- }
-basic_json_parser_6:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yybm[0 + yych] & 32)
- {
- goto basic_json_parser_6;
- }
- {
- return scan();
- }
-basic_json_parser_9:
- yyaccept = 0;
- yych = *(m_marker = ++m_cursor);
- if (yych <= 0x0F)
- {
- goto basic_json_parser_5;
- }
- goto basic_json_parser_32;
-basic_json_parser_10:
- ++m_cursor;
- {
- return token_type::value_separator;
- }
-basic_json_parser_12:
- yych = *++m_cursor;
- if (yych <= '/')
- {
- goto basic_json_parser_5;
- }
- if (yych <= '0')
- {
- goto basic_json_parser_13;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_15;
- }
- goto basic_json_parser_5;
-basic_json_parser_13:
- yyaccept = 1;
- yych = *(m_marker = ++m_cursor);
- if (yych <= 'D')
- {
- if (yych == '.')
- {
- goto basic_json_parser_37;
- }
- }
- else
- {
- if (yych <= 'E')
- {
- goto basic_json_parser_38;
- }
- if (yych == 'e')
- {
- goto basic_json_parser_38;
- }
- }
-basic_json_parser_14:
- {
- return token_type::value_number;
- }
-basic_json_parser_15:
- yyaccept = 1;
- m_marker = ++m_cursor;
- if ((m_limit - m_cursor) < 3)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yybm[0 + yych] & 64)
- {
- goto basic_json_parser_15;
- }
- if (yych <= 'D')
- {
- if (yych == '.')
- {
- goto basic_json_parser_37;
- }
- goto basic_json_parser_14;
- }
- else
- {
- if (yych <= 'E')
- {
- goto basic_json_parser_38;
- }
- if (yych == 'e')
- {
- goto basic_json_parser_38;
- }
- goto basic_json_parser_14;
- }
-basic_json_parser_17:
- ++m_cursor;
- {
- return token_type::name_separator;
- }
-basic_json_parser_19:
- ++m_cursor;
- {
- return token_type::begin_array;
- }
-basic_json_parser_21:
- ++m_cursor;
- {
- return token_type::end_array;
- }
-basic_json_parser_23:
- yyaccept = 0;
- yych = *(m_marker = ++m_cursor);
- if (yych == 'a')
- {
- goto basic_json_parser_39;
- }
- goto basic_json_parser_5;
-basic_json_parser_24:
- yyaccept = 0;
- yych = *(m_marker = ++m_cursor);
- if (yych == 'u')
- {
- goto basic_json_parser_40;
- }
- goto basic_json_parser_5;
-basic_json_parser_25:
- yyaccept = 0;
- yych = *(m_marker = ++m_cursor);
- if (yych == 'r')
- {
- goto basic_json_parser_41;
- }
- goto basic_json_parser_5;
-basic_json_parser_26:
- ++m_cursor;
- {
- return token_type::begin_object;
- }
-basic_json_parser_28:
- ++m_cursor;
- {
- return token_type::end_object;
- }
-basic_json_parser_30:
- yyaccept = 0;
- yych = *(m_marker = ++m_cursor);
- if (yych == 0xBB)
- {
- goto basic_json_parser_42;
- }
- goto basic_json_parser_5;
-basic_json_parser_31:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
-basic_json_parser_32:
- if (yybm[0 + yych] & 128)
- {
- goto basic_json_parser_31;
- }
- if (yych <= 0x0F)
- {
- goto basic_json_parser_33;
- }
- if (yych <= '"')
- {
- goto basic_json_parser_34;
- }
- goto basic_json_parser_36;
-basic_json_parser_33:
- m_cursor = m_marker;
- if (yyaccept == 0)
- {
- goto basic_json_parser_5;
- }
- else
- {
- goto basic_json_parser_14;
- }
-basic_json_parser_34:
- ++m_cursor;
- {
- return token_type::value_string;
- }
-basic_json_parser_36:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= 'e')
- {
- if (yych <= '/')
- {
- if (yych == '"')
- {
- goto basic_json_parser_31;
- }
- if (yych <= '.')
- {
- goto basic_json_parser_33;
- }
- goto basic_json_parser_31;
- }
- else
- {
- if (yych <= '\\')
- {
- if (yych <= '[')
- {
- goto basic_json_parser_33;
- }
- goto basic_json_parser_31;
- }
- else
- {
- if (yych == 'b')
- {
- goto basic_json_parser_31;
- }
- goto basic_json_parser_33;
- }
- }
- }
- else
- {
- if (yych <= 'q')
- {
- if (yych <= 'f')
- {
- goto basic_json_parser_31;
- }
- if (yych == 'n')
- {
- goto basic_json_parser_31;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= 's')
- {
- if (yych <= 'r')
- {
- goto basic_json_parser_31;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= 't')
- {
- goto basic_json_parser_31;
- }
- if (yych <= 'u')
- {
- goto basic_json_parser_43;
- }
- goto basic_json_parser_33;
- }
- }
- }
-basic_json_parser_37:
- yych = *++m_cursor;
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_44;
- }
- goto basic_json_parser_33;
-basic_json_parser_38:
- yych = *++m_cursor;
- if (yych <= ',')
- {
- if (yych == '+')
- {
- goto basic_json_parser_46;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= '-')
- {
- goto basic_json_parser_46;
- }
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_47;
- }
- goto basic_json_parser_33;
- }
-basic_json_parser_39:
- yych = *++m_cursor;
- if (yych == 'l')
- {
- goto basic_json_parser_49;
- }
- goto basic_json_parser_33;
-basic_json_parser_40:
- yych = *++m_cursor;
- if (yych == 'l')
- {
- goto basic_json_parser_50;
- }
- goto basic_json_parser_33;
-basic_json_parser_41:
- yych = *++m_cursor;
- if (yych == 'u')
- {
- goto basic_json_parser_51;
- }
- goto basic_json_parser_33;
-basic_json_parser_42:
- yych = *++m_cursor;
- if (yych == 0xBF)
- {
- goto basic_json_parser_52;
- }
- goto basic_json_parser_33;
-basic_json_parser_43:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= '@')
- {
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_54;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= 'F')
- {
- goto basic_json_parser_54;
- }
- if (yych <= '`')
- {
- goto basic_json_parser_33;
- }
- if (yych <= 'f')
- {
- goto basic_json_parser_54;
- }
- goto basic_json_parser_33;
- }
-basic_json_parser_44:
- yyaccept = 1;
- m_marker = ++m_cursor;
- if ((m_limit - m_cursor) < 3)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= 'D')
- {
- if (yych <= '/')
- {
- goto basic_json_parser_14;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_44;
- }
- goto basic_json_parser_14;
- }
- else
- {
- if (yych <= 'E')
- {
- goto basic_json_parser_38;
- }
- if (yych == 'e')
- {
- goto basic_json_parser_38;
- }
- goto basic_json_parser_14;
- }
-basic_json_parser_46:
- yych = *++m_cursor;
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych >= ':')
- {
- goto basic_json_parser_33;
- }
-basic_json_parser_47:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= '/')
- {
- goto basic_json_parser_14;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_47;
- }
- goto basic_json_parser_14;
-basic_json_parser_49:
- yych = *++m_cursor;
- if (yych == 's')
- {
- goto basic_json_parser_55;
- }
- goto basic_json_parser_33;
-basic_json_parser_50:
- yych = *++m_cursor;
- if (yych == 'l')
- {
- goto basic_json_parser_56;
- }
- goto basic_json_parser_33;
-basic_json_parser_51:
- yych = *++m_cursor;
- if (yych == 'e')
- {
- goto basic_json_parser_58;
- }
- goto basic_json_parser_33;
-basic_json_parser_52:
- ++m_cursor;
- {
- return scan();
- }
-basic_json_parser_54:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= '@')
- {
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_60;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= 'F')
- {
- goto basic_json_parser_60;
- }
- if (yych <= '`')
- {
- goto basic_json_parser_33;
- }
- if (yych <= 'f')
- {
- goto basic_json_parser_60;
- }
- goto basic_json_parser_33;
- }
-basic_json_parser_55:
- yych = *++m_cursor;
- if (yych == 'e')
- {
- goto basic_json_parser_61;
- }
- goto basic_json_parser_33;
-basic_json_parser_56:
- ++m_cursor;
- {
- return token_type::literal_null;
- }
-basic_json_parser_58:
- ++m_cursor;
- {
- return token_type::literal_true;
- }
-basic_json_parser_60:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= '@')
- {
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_63;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= 'F')
- {
- goto basic_json_parser_63;
- }
- if (yych <= '`')
- {
- goto basic_json_parser_33;
- }
- if (yych <= 'f')
- {
- goto basic_json_parser_63;
- }
- goto basic_json_parser_33;
- }
-basic_json_parser_61:
- ++m_cursor;
- {
- return token_type::literal_false;
- }
-basic_json_parser_63:
- ++m_cursor;
- if (m_limit <= m_cursor)
- {
- yyfill(); // LCOV_EXCL_LINE;
- }
- yych = *m_cursor;
- if (yych <= '@')
- {
- if (yych <= '/')
- {
- goto basic_json_parser_33;
- }
- if (yych <= '9')
- {
- goto basic_json_parser_31;
- }
- goto basic_json_parser_33;
- }
- else
- {
- if (yych <= 'F')
- {
- goto basic_json_parser_31;
- }
- if (yych <= '`')
- {
- goto basic_json_parser_33;
- }
- if (yych <= 'f')
- {
- goto basic_json_parser_31;
- }
- goto basic_json_parser_33;
- }
- }
-
- }
-
- /// append data from the stream to the internal buffer
- void yyfill() noexcept
- {
- if (m_stream == nullptr or not * m_stream)
- {
- return;
- }
-
- const auto offset_start = m_start - m_content;
- const auto offset_marker = m_marker - m_start;
- const auto offset_cursor = m_cursor - m_start;
-
- m_buffer.erase(0, static_cast<size_t>(offset_start));
- std::string line;
- assert(m_stream != nullptr);
- std::getline(*m_stream, line);
- m_buffer += "\n" + line; // add line with newline symbol
-
- m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
- assert(m_content != nullptr);
- m_start = m_content;
- m_marker = m_start + offset_marker;
- m_cursor = m_start + offset_cursor;
- m_limit = m_start + m_buffer.size() - 1;
- }
-
- /// return string representation of last read token
- string_t get_token() const
- {
- assert(m_start != nullptr);
- return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
- static_cast<size_t>(m_cursor - m_start));
- }
-
- /*!
- @brief return string value for string tokens
-
- The function iterates the characters between the opening and closing
- quotes of the string value. The complete string is the range
- [m_start,m_cursor). Consequently, we iterate from m_start+1 to
- m_cursor-1.
-
- We differentiate two cases:
-
- 1. Escaped characters. In this case, a new character is constructed
- according to the nature of the escape. Some escapes create new
- characters (e.g., `"\\n"` is replaced by `"\n"`), some are copied
- as is (e.g., `"\\\\"`). Furthermore, Unicode escapes of the shape
- `"\\uxxxx"` need special care. In this case, to_unicode takes care
- of the construction of the values.
- 2. Unescaped characters are copied as is.
-
- @return string value of current token without opening and closing
- quotes
- @throw std::out_of_range if to_unicode fails
- */
- string_t get_string() const
- {
- string_t result;
- result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
-
- // iterate the result between the quotes
- for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
- {
- // process escaped characters
- if (*i == '\\')
- {
- // read next character
- ++i;
-
- switch (*i)
- {
- // the default escapes
- case 't':
- {
- result += "\t";
- break;
- }
- case 'b':
- {
- result += "\b";
- break;
- }
- case 'f':
- {
- result += "\f";
- break;
- }
- case 'n':
- {
- result += "\n";
- break;
- }
- case 'r':
- {
- result += "\r";
- break;
- }
- case '\\':
- {
- result += "\\";
- break;
- }
- case '/':
- {
- result += "/";
- break;
- }
- case '"':
- {
- result += "\"";
- break;
- }
-
- // unicode
- case 'u':
- {
- // get code xxxx from uxxxx
- auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
- 4).c_str(), nullptr, 16);
-
- // check if codepoint is a high surrogate
- if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
- {
- // make sure there is a subsequent unicode
- if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
- {
- throw std::invalid_argument("missing low surrogate");
- }
-
- // get code yyyy from uxxxx\uyyyy
- auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
- (i + 7), 4).c_str(), nullptr, 16);
- result += to_unicode(codepoint, codepoint2);
- // skip the next 10 characters (xxxx\uyyyy)
- i += 10;
- }
- else
- {
- // add unicode character(s)
- result += to_unicode(codepoint);
- // skip the next four characters (xxxx)
- i += 4;
- }
- break;
- }
- }
- }
- else
- {
- // all other characters are just copied to the end of the
- // string
- result.append(1, static_cast<typename string_t::value_type>(*i));
- }
- }
-
- return result;
- }
-
- /*!
- @brief parse floating point number
-
- This function (and its overloads) serves to select the most approprate
- standard floating point number parsing function based on the type
- supplied via the first parameter. Set this to @a
- static_cast<number_float_t*>(nullptr).
-
- @param[in] type the @ref number_float_t in use
-
- @param[in,out] endptr recieves a pointer to the first character after
- the number
-
- @return the floating point number
-
- @bug This function uses `std::strtof`, `std::strtod`, or `std::strtold`
- which use the current C locale to determine which character is used as
- decimal point character. This may yield to parse errors if the locale
- does not used `.`.
- */
- long double str_to_float_t(long double* /* type */, char** endptr) const
- {
- return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
- }
-
- /*!
- @brief parse floating point number
-
- This function (and its overloads) serves to select the most approprate
- standard floating point number parsing function based on the type
- supplied via the first parameter. Set this to @a
- static_cast<number_float_t*>(nullptr).
-
- @param[in] type the @ref number_float_t in use
-
- @param[in,out] endptr recieves a pointer to the first character after
- the number
-
- @return the floating point number
- */
- double str_to_float_t(double* /* type */, char** endptr) const
- {
- return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
- }
-
- /*!
- @brief parse floating point number
-
- This function (and its overloads) serves to select the most approprate
- standard floating point number parsing function based on the type
- supplied via the first parameter. Set this to @a
- static_cast<number_float_t*>(nullptr).
-
- @param[in] type the @ref number_float_t in use
-
- @param[in,out] endptr recieves a pointer to the first character after
- the number
-
- @return the floating point number
- */
- float str_to_float_t(float* /* type */, char** endptr) const
- {
- return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
- }
-
- /*!
- @brief return number value for number tokens
-
- This function translates the last token into the most appropriate
- number type (either integer, unsigned integer or floating point),
- which is passed back to the caller via the result parameter.
-
- This function parses the integer component up to the radix point or
- exponent while collecting information about the 'floating point
- representation', which it stores in the result parameter. If there is
- no radix point or exponent, and the number can fit into a @ref
- number_integer_t or @ref number_unsigned_t then it sets the result
- parameter accordingly.
-
- The 'floating point representation' includes the number of significant
- figures after the radix point, whether the number is in exponential or
- decimal form, the capitalization of the exponent marker, and if the
- optional '+' is present in the exponent. This information is necessary
- to perform accurate round trips of floating point numbers.
-
- If the number is a floating point number the number is then parsed
- using @a std:strtod (or @a std:strtof or @a std::strtold).
-
- @param[out] result @ref basic_json object to receive the number, or
- NAN if the conversion read past the current token. The latter case
- needs to be treated by the caller function.
- */
- void get_number(basic_json& result) const
- {
- assert(m_start != nullptr);
-
- const lexer::lexer_char_t* curptr = m_start;
-
- // remember this number was parsed (for later serialization)
- result.m_type.bits.parsed = true;
+ std::vector<uint8_t> result;
+ to_msgpack(j, result);
+ return result;
+ }
- // 'found_radix_point' will be set to 0xFF upon finding a radix
- // point and later used to mask in/out the precision depending
- // whether a radix is found i.e. 'precision &= found_radix_point'
- uint8_t found_radix_point = 0;
- uint8_t precision = 0;
+ static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
+ {
+ binary_writer<uint8_t>(o).write_msgpack(j);
+ }
+
+ static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
+ {
+ binary_writer<char>(o).write_msgpack(j);
+ }
+
+ /*!
+ @brief create a JSON value from an input in CBOR format
+
+ Deserializes a given input @a i to a JSON value using the CBOR (Concise
+ Binary Object Representation) serialization format.
- // accumulate the integer conversion result (unsigned for now)
- number_unsigned_t value = 0;
+ The library maps CBOR types to JSON value types as follows:
- // maximum absolute value of the relevant integer type
- number_unsigned_t max;
+ CBOR type | JSON value type | first byte
+ ---------------------- | --------------- | ----------
+ Integer | number_unsigned | 0x00..0x17
+ Unsigned integer | number_unsigned | 0x18
+ Unsigned integer | number_unsigned | 0x19
+ Unsigned integer | number_unsigned | 0x1A
+ Unsigned integer | number_unsigned | 0x1B
+ Negative integer | number_integer | 0x20..0x37
+ Negative integer | number_integer | 0x38
+ Negative integer | number_integer | 0x39
+ Negative integer | number_integer | 0x3A
+ Negative integer | number_integer | 0x3B
+ Negative integer | number_integer | 0x40..0x57
+ UTF-8 string | string | 0x60..0x77
+ UTF-8 string | string | 0x78
+ UTF-8 string | string | 0x79
+ UTF-8 string | string | 0x7A
+ UTF-8 string | string | 0x7B
+ UTF-8 string | string | 0x7F
+ array | array | 0x80..0x97
+ array | array | 0x98
+ array | array | 0x99
+ array | array | 0x9A
+ array | array | 0x9B
+ array | array | 0x9F
+ map | object | 0xA0..0xB7
+ map | object | 0xB8
+ map | object | 0xB9
+ map | object | 0xBA
+ map | object | 0xBB
+ map | object | 0xBF
+ False | `false` | 0xF4
+ True | `true` | 0xF5
+ Nill | `null` | 0xF6
+ Half-Precision Float | number_float | 0xF9
+ Single-Precision Float | number_float | 0xFA
+ Double-Precision Float | number_float | 0xFB
+
+ @warning The mapping is **incomplete** in the sense that not all CBOR
+ types can be converted to a JSON value. The following CBOR types
+ are not supported and will yield parse errors (parse_error.112):
+ - byte strings (0x40..0x5F)
+ - date/time (0xC0..0xC1)
+ - bignum (0xC2..0xC3)
+ - decimal fraction (0xC4)
+ - bigfloat (0xC5)
+ - tagged items (0xC6..0xD4, 0xD8..0xDB)
+ - expected conversions (0xD5..0xD7)
+ - simple values (0xE0..0xF3, 0xF8)
+ - undefined (0xF7)
+
+ @warning CBOR allows map keys of any type, whereas JSON only allows
+ strings as keys in object values. Therefore, CBOR maps with keys
+ other than UTF-8 strings are rejected (parse_error.113).
+
+ @note Any CBOR output created @ref to_cbor can be successfully parsed by
+ @ref from_cbor.
+
+ @param[in] i an input in CBOR format convertible to an input adapter
+ @param[in] strict whether to expect the input to be consumed until EOF
+ (true by default)
+ @return deserialized JSON value
+
+ @throw parse_error.110 if the given input ends prematurely or the end of
+ file was not reached when @a strict was set to true
+ @throw parse_error.112 if unsupported features from CBOR were
+ used in the given input @a v or if the input is not valid CBOR
+ @throw parse_error.113 if a string was expected as map key, but not found
+
+ @complexity Linear in the size of the input @a i.
+
+ @liveexample{The example shows the deserialization of a byte vector in CBOR
+ format to a JSON value.,from_cbor}
+
+ @sa http://cbor.io
+ @sa @ref to_cbor(const basic_json&) for the analogous serialization
+ @sa @ref from_msgpack(detail::input_adapter, const bool) for the
+ related MessagePack format
+
+ @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+ consume input adapters, removed start_index parameter, and added
+ @a strict parameter since 3.0.0
+ */
+ static basic_json from_cbor(detail::input_adapter i,
+ const bool strict = true)
+ {
+ return binary_reader(i).parse_cbor(strict);
+ }
+
+ /*!
+ @copydoc from_cbor(detail::input_adapter, const bool)
+ */
+ template<typename A1, typename A2,
+ detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
+ static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true)
+ {
+ return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);
+ }
+
+ /*!
+ @brief create a JSON value from an input in MessagePack format
+
+ Deserializes a given input @a i to a JSON value using the MessagePack
+ serialization format.
+
+ The library maps MessagePack types to JSON value types as follows:
+
+ MessagePack type | JSON value type | first byte
+ ---------------- | --------------- | ----------
+ positive fixint | number_unsigned | 0x00..0x7F
+ fixmap | object | 0x80..0x8F
+ fixarray | array | 0x90..0x9F
+ fixstr | string | 0xA0..0xBF
+ nil | `null` | 0xC0
+ false | `false` | 0xC2
+ true | `true` | 0xC3
+ float 32 | number_float | 0xCA
+ float 64 | number_float | 0xCB
+ uint 8 | number_unsigned | 0xCC
+ uint 16 | number_unsigned | 0xCD
+ uint 32 | number_unsigned | 0xCE
+ uint 64 | number_unsigned | 0xCF
+ int 8 | number_integer | 0xD0
+ int 16 | number_integer | 0xD1
+ int 32 | number_integer | 0xD2
+ int 64 | number_integer | 0xD3
+ str 8 | string | 0xD9
+ str 16 | string | 0xDA
+ str 32 | string | 0xDB
+ array 16 | array | 0xDC
+ array 32 | array | 0xDD
+ map 16 | object | 0xDE
+ map 32 | object | 0xDF
+ negative fixint | number_integer | 0xE0-0xFF
- // temporarily store the type to avoid unecessary bitfield access
- value_t type;
+ @warning The mapping is **incomplete** in the sense that not all
+ MessagePack types can be converted to a JSON value. The following
+ MessagePack types are not supported and will yield parse errors:
+ - bin 8 - bin 32 (0xC4..0xC6)
+ - ext 8 - ext 32 (0xC7..0xC9)
+ - fixext 1 - fixext 16 (0xD4..0xD8)
- // look for sign
- if (*curptr == '-')
- {
- type = value_t::number_integer;
- max = static_cast<uint64_t>((std::numeric_limits<number_integer_t>::max)()) + 1;
- curptr++;
- }
- else
- {
- type = value_t::number_unsigned;
- max = static_cast<uint64_t>((std::numeric_limits<number_unsigned_t>::max)());
- }
+ @note Any MessagePack output created @ref to_msgpack can be successfully
+ parsed by @ref from_msgpack.
- // count the significant figures
- for (; curptr < m_cursor; curptr++)
- {
- // quickly skip tests if a digit
- if (*curptr < '0' || *curptr > '9')
- {
- if (*curptr == '.')
- {
- // don't count '.' but change to float
- type = value_t::number_float;
+ @param[in] i an input in MessagePack format convertible to an input
+ adapter
+ @param[in] strict whether to expect the input to be consumed until EOF
+ (true by default)
- // reset precision count
- precision = 0;
- found_radix_point = 0xFF;
- continue;
- }
- // assume exponent (if not then will fail parse): change to
- // float, stop counting and record exponent details
- type = value_t::number_float;
- result.m_type.bits.has_exp = true;
+ @throw parse_error.110 if the given input ends prematurely or the end of
+ file was not reached when @a strict was set to true
+ @throw parse_error.112 if unsupported features from MessagePack were
+ used in the given input @a i or if the input is not valid MessagePack
+ @throw parse_error.113 if a string was expected as map key, but not found
- // exponent capitalization
- result.m_type.bits.exp_cap = (*curptr == 'E');
+ @complexity Linear in the size of the input @a i.
- // exponent '+' sign
- result.m_type.bits.exp_plus = (*(++curptr) == '+');
- break;
- }
+ @liveexample{The example shows the deserialization of a byte vector in
+ MessagePack format to a JSON value.,from_msgpack}
- // skip if definitely not an integer
- if (type != value_t::number_float)
- {
- // multiply last value by ten and add the new digit
- auto temp = value * 10 + *curptr - 0x30;
+ @sa http://msgpack.org
+ @sa @ref to_msgpack(const basic_json&) for the analogous serialization
+ @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
+ format
- // test for overflow
- if (temp < value || temp > max)
- {
- // overflow
- type = value_t::number_float;
- }
- else
- {
- // no overflow - save it
- value = temp;
- }
- }
- ++precision;
- }
-
- // If no radix point was found then precision would now be set to
- // the number of digits, which is wrong - clear it.
- result.m_type.bits.precision = precision & found_radix_point;
-
- // save the value (if not a float)
- if (type == value_t::number_unsigned)
- {
- result.m_value.number_unsigned = value;
- }
- else if (type == value_t::number_integer)
- {
- result.m_value.number_integer = -static_cast<number_integer_t>(value);
- }
- else
- {
- // parse with strtod
- result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
- }
-
- // save the type
- result.m_type = type;
- }
-
- private:
- /// optional input stream
- std::istream* m_stream = nullptr;
- /// the buffer
- string_t m_buffer;
- /// the buffer pointer
- const lexer_char_t* m_content = nullptr;
- /// pointer to the beginning of the current symbol
- const lexer_char_t* m_start = nullptr;
- /// pointer for backtracking information
- const lexer_char_t* m_marker = nullptr;
- /// pointer to the current symbol
- const lexer_char_t* m_cursor = nullptr;
- /// pointer to the end of the buffer
- const lexer_char_t* m_limit = nullptr;
- };
-
- /*!
- @brief syntax analysis
-
- This class implements a recursive decent parser.
+ @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+ consume input adapters, removed start_index parameter, and added
+ @a strict parameter since 3.0.0
*/
- class parser
+ static basic_json from_msgpack(detail::input_adapter i,
+ const bool strict = true)
{
- public:
- /// constructor for strings
- parser(const string_t& s, parser_callback_t cb = nullptr) noexcept
- : callback(cb), m_lexer(s)
- {
- // read first token
- get_token();
- }
-
- /// a parser reading from an input stream
- parser(std::istream& _is, parser_callback_t cb = nullptr) noexcept
- : callback(cb), m_lexer(&_is)
- {
- // read first token
- get_token();
- }
-
- /// public parser interface
- basic_json parse()
- {
- basic_json result = parse_internal(true);
-
- expect(lexer::token_type::end_of_input);
-
- // return parser result and replace it with null in case the
- // top-level value was discarded by the callback function
- return result.is_discarded() ? basic_json() : result;
- }
-
- private:
- /// the actual parser
- basic_json parse_internal(bool keep)
- {
- auto result = basic_json(value_t::discarded);
-
- switch (last_token)
- {
- case lexer::token_type::begin_object:
- {
- if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
- {
- // explicitly set result to object to cope with {}
- result.m_type = value_t::object;
- result.m_value = json_value(value_t::object);
- }
-
- // read next token
- get_token();
-
- // closing } -> we are done
- if (last_token == lexer::token_type::end_object)
- {
- get_token();
- if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
- {
- result = basic_json(value_t::discarded);
- }
- return result;
- }
-
- // no comma is expected here
- unexpect(lexer::token_type::value_separator);
-
- // otherwise: parse key-value pairs
- do
- {
- // ugly, but could be fixed with loop reorganization
- if (last_token == lexer::token_type::value_separator)
- {
- get_token();
- }
-
- // store key
- expect(lexer::token_type::value_string);
- const auto key = m_lexer.get_string();
-
- bool keep_tag = false;
- if (keep)
- {
- if (callback)
- {
- basic_json k(key);
- keep_tag = callback(depth, parse_event_t::key, k);
- }
- else
- {
- keep_tag = true;
- }
- }
-
- // parse separator (:)
- get_token();
- expect(lexer::token_type::name_separator);
-
- // parse and add value
- get_token();
- auto value = parse_internal(keep);
- if (keep and keep_tag and not value.is_discarded())
- {
- result[key] = std::move(value);
- }
- }
- while (last_token == lexer::token_type::value_separator);
-
- // closing }
- expect(lexer::token_type::end_object);
- get_token();
- if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
- {
- result = basic_json(value_t::discarded);
- }
-
- return result;
- }
-
- case lexer::token_type::begin_array:
- {
- if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
- {
- // explicitly set result to object to cope with []
- result.m_type = value_t::array;
- result.m_value = json_value(value_t::array);
- }
-
- // read next token
- get_token();
-
- // closing ] -> we are done
- if (last_token == lexer::token_type::end_array)
- {
- get_token();
- if (callback and not callback(--depth, parse_event_t::array_end, result))
- {
- result = basic_json(value_t::discarded);
- }
- return result;
- }
-
- // no comma is expected here
- unexpect(lexer::token_type::value_separator);
-
- // otherwise: parse values
- do
- {
- // ugly, but could be fixed with loop reorganization
- if (last_token == lexer::token_type::value_separator)
- {
- get_token();
- }
-
- // parse value
- auto value = parse_internal(keep);
- if (keep and not value.is_discarded())
- {
- result.push_back(std::move(value));
- }
- }
- while (last_token == lexer::token_type::value_separator);
-
- // closing ]
- expect(lexer::token_type::end_array);
- get_token();
- if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
- {
- result = basic_json(value_t::discarded);
- }
-
- return result;
- }
-
- case lexer::token_type::literal_null:
- {
- get_token();
- result.m_type = value_t::null;
- break;
- }
-
- case lexer::token_type::value_string:
- {
- const auto s = m_lexer.get_string();
- get_token();
- result = basic_json(s);
- break;
- }
-
- case lexer::token_type::literal_true:
- {
- get_token();
- result.m_type = value_t::boolean;
- result.m_value = true;
- break;
- }
-
- case lexer::token_type::literal_false:
- {
- get_token();
- result.m_type = value_t::boolean;
- result.m_value = false;
- break;
- }
-
- case lexer::token_type::value_number:
- {
- m_lexer.get_number(result);
- get_token();
- break;
- }
-
- default:
- {
- // the last token was unexpected
- unexpect(last_token);
- }
- }
-
- if (keep and callback and not callback(depth, parse_event_t::value, result))
- {
- result = basic_json(value_t::discarded);
- }
- return result;
- }
-
- /// get next token from lexer
- typename lexer::token_type get_token() noexcept
- {
- last_token = m_lexer.scan();
- return last_token;
- }
-
- void expect(typename lexer::token_type t) const
- {
- if (t != last_token)
- {
- std::string error_msg = "parse error - unexpected ";
- error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
- lexer::token_type_name(last_token));
- error_msg += "; expected " + lexer::token_type_name(t);
- throw std::invalid_argument(error_msg);
- }
- }
-
- void unexpect(typename lexer::token_type t) const
- {
- if (t == last_token)
- {
- std::string error_msg = "parse error - unexpected ";
- error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
- lexer::token_type_name(last_token));
- throw std::invalid_argument(error_msg);
- }
- }
-
- private:
- /// current level of recursion
- int depth = 0;
- /// callback function
- parser_callback_t callback;
- /// the type of the last read token
- typename lexer::token_type last_token = lexer::token_type::uninitialized;
- /// the lexer
- lexer m_lexer;
- };
+ return binary_reader(i).parse_msgpack(strict);
+ }
- public:
/*!
- @brief JSON Pointer
-
- A JSON pointer defines a string syntax for identifying a specific value
- within a JSON document. It can be used with functions `at` and
- `operator[]`. Furthermore, JSON pointers are the base for JSON patches.
-
- @sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
-
- @since version 2.0.0
+ @copydoc from_msgpack(detail::input_adapter, const bool)
*/
- class json_pointer
+ template<typename A1, typename A2,
+ detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
+ static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true)
{
- /// allow basic_json to access private members
- friend class basic_json;
-
- public:
- /*!
- @brief create JSON pointer
-
- Create a JSON pointer according to the syntax described in
- [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
-
- @param[in] s string representing the JSON pointer; if omitted, the
- empty string is assumed which references the whole JSON
- value
-
- @throw std::domain_error if reference token is nonempty and does not
- begin with a slash (`/`); example: `"JSON pointer must be empty or
- begin with /"`
- @throw std::domain_error if a tilde (`~`) is not followed by `0`
- (representing `~`) or `1` (representing `/`); example: `"escape error:
- ~ must be followed with 0 or 1"`
-
- @liveexample{The example shows the construction several valid JSON
- pointers as well as the exceptional behavior.,json_pointer}
-
- @since version 2.0.0
- */
- explicit json_pointer(const std::string& s = "")
- : reference_tokens(split(s))
- {}
-
- /*!
- @brief return a string representation of the JSON pointer
-
- @invariant For each JSON pointer `ptr`, it holds:
- @code {.cpp}
- ptr == json_pointer(ptr.to_string());
- @endcode
-
- @return a string representation of the JSON pointer
-
- @liveexample{The example shows the result of `to_string`.,
- json_pointer__to_string}
-
- @since version 2.0.0
- */
- std::string to_string() const noexcept
- {
- std::string result;
-
- for (const auto& reference_token : reference_tokens)
- {
- result += "/" + escape(reference_token);
- }
-
- return result;
- }
-
- /// @copydoc to_string()
- operator std::string() const
- {
- return to_string();
- }
-
- private:
- /// remove and return last reference pointer
- std::string pop_back()
- {
- if (is_root())
- {
- throw std::domain_error("JSON pointer has no parent");
- }
-
- auto last = reference_tokens.back();
- reference_tokens.pop_back();
- return last;
- }
-
- /// return whether pointer points to the root document
- bool is_root() const
- {
- return reference_tokens.empty();
- }
-
- json_pointer top() const
- {
- if (is_root())
- {
- throw std::domain_error("JSON pointer has no parent");
- }
-
- json_pointer result = *this;
- result.reference_tokens = {reference_tokens[0]};
- return result;
- }
-
- /*!
- @brief create and return a reference to the pointed to value
- */
- reference get_and_create(reference j) const
- {
- pointer result = &j;
-
- // in case no reference tokens exist, return a reference to the
- // JSON value j which will be overwritten by a primitive value
- for (const auto& reference_token : reference_tokens)
- {
- switch (result->m_type)
- {
- case value_t::null:
- {
- if (reference_token == "0")
- {
- // start a new array if reference token is 0
- result = &result->operator[](0);
- }
- else
- {
- // start a new object otherwise
- result = &result->operator[](reference_token);
- }
- break;
- }
-
- case value_t::object:
- {
- // create an entry in the object
- result = &result->operator[](reference_token);
- break;
- }
-
- case value_t::array:
- {
- // create an entry in the array
- result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
- break;
- }
-
- /*
- The following code is only reached if there exists a
- reference token _and_ the current value is primitive. In
- this case, we have an error situation, because primitive
- values may only occur as single value; that is, with an
- empty list of reference tokens.
- */
- default:
- {
- throw std::domain_error("invalid value to unflatten");
- }
- }
- }
-
- return *result;
- }
-
- /*!
- @brief return a reference to the pointed to value
-
- @param[in] ptr a JSON value
-
- @return reference to the JSON value pointed to by the JSON pointer
-
- @complexity Linear in the length of the JSON pointer.
-
- @throw std::out_of_range if the JSON pointer can not be resolved
- @throw std::domain_error if an array index begins with '0'
- @throw std::invalid_argument if an array index was not a number
- */
- reference get_unchecked(pointer ptr) const
- {
- for (const auto& reference_token : reference_tokens)
- {
- switch (ptr->m_type)
- {
- case value_t::object:
- {
- // use unchecked object access
- ptr = &ptr->operator[](reference_token);
- break;
- }
-
- case value_t::array:
- {
- // error condition (cf. RFC 6901, Sect. 4)
- if (reference_token.size() > 1 and reference_token[0] == '0')
- {
- throw std::domain_error("array index must not begin with '0'");
- }
-
- if (reference_token == "-")
- {
- // explicityly treat "-" as index beyond the end
- ptr = &ptr->operator[](ptr->m_value.array->size());
- }
- else
- {
- // convert array index to number; unchecked access
- ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
- }
- break;
- }
-
- default:
- {
- throw std::out_of_range("unresolved reference token '" + reference_token + "'");
- }
- }
- }
-
- return *ptr;
- }
-
- reference get_checked(pointer ptr) const
- {
- for (const auto& reference_token : reference_tokens)
- {
- switch (ptr->m_type)
- {
- case value_t::object:
- {
- // note: at performs range check
- ptr = &ptr->at(reference_token);
- break;
- }
-
- case value_t::array:
- {
- if (reference_token == "-")
- {
- // "-" always fails the range check
- throw std::out_of_range("array index '-' (" +
- std::to_string(ptr->m_value.array->size()) +
- ") is out of range");
- }
-
- // error condition (cf. RFC 6901, Sect. 4)
- if (reference_token.size() > 1 and reference_token[0] == '0')
- {
- throw std::domain_error("array index must not begin with '0'");
- }
-
- // note: at performs range check
- ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
- break;
- }
-
- default:
- {
- throw std::out_of_range("unresolved reference token '" + reference_token + "'");
- }
- }
- }
-
- return *ptr;
- }
-
- /*!
- @brief return a const reference to the pointed to value
-
- @param[in] ptr a JSON value
-
- @return const reference to the JSON value pointed to by the JSON
- pointer
- */
- const_reference get_unchecked(const_pointer ptr) const
- {
- for (const auto& reference_token : reference_tokens)
- {
- switch (ptr->m_type)
- {
- case value_t::object:
- {
- // use unchecked object access
- ptr = &ptr->operator[](reference_token);
- break;
- }
-
- case value_t::array:
- {
- if (reference_token == "-")
- {
- // "-" cannot be used for const access
- throw std::out_of_range("array index '-' (" +
- std::to_string(ptr->m_value.array->size()) +
- ") is out of range");
- }
-
- // error condition (cf. RFC 6901, Sect. 4)
- if (reference_token.size() > 1 and reference_token[0] == '0')
- {
- throw std::domain_error("array index must not begin with '0'");
- }
-
- // use unchecked array access
- ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token)));
- break;
- }
-
- default:
- {
- throw std::out_of_range("unresolved reference token '" + reference_token + "'");
- }
- }
- }
-
- return *ptr;
- }
-
- const_reference get_checked(const_pointer ptr) const
- {
- for (const auto& reference_token : reference_tokens)
- {
- switch (ptr->m_type)
- {
- case value_t::object:
- {
- // note: at performs range check
- ptr = &ptr->at(reference_token);
- break;
- }
-
- case value_t::array:
- {
- if (reference_token == "-")
- {
- // "-" always fails the range check
- throw std::out_of_range("array index '-' (" +
- std::to_string(ptr->m_value.array->size()) +
- ") is out of range");
- }
-
- // error condition (cf. RFC 6901, Sect. 4)
- if (reference_token.size() > 1 and reference_token[0] == '0')
- {
- throw std::domain_error("array index must not begin with '0'");
- }
-
- // note: at performs range check
- ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
- break;
- }
-
- default:
- {
- throw std::out_of_range("unresolved reference token '" + reference_token + "'");
- }
- }
- }
-
- return *ptr;
- }
-
- /// split the string input to reference tokens
- static std::vector<std::string> split(std::string reference_string)
- {
- std::vector<std::string> result;
-
- // special case: empty reference string -> no reference tokens
- if (reference_string.empty())
- {
- return result;
- }
-
- // check if nonempty reference string begins with slash
- if (reference_string[0] != '/')
- {
- throw std::domain_error("JSON pointer must be empty or begin with '/'");
- }
-
- // extract the reference tokens:
- // - slash: position of the last read slash (or end of string)
- // - start: position after the previous slash
- for (
- // search for the first slash after the first character
- size_t slash = reference_string.find_first_of("/", 1),
- // set the beginning of the first reference token
- start = 1;
- // we can stop if start == string::npos+1 = 0
- start != 0;
- // set the beginning of the next reference token
- // (will eventually be 0 if slash == std::string::npos)
- start = slash + 1,
- // find next slash
- slash = reference_string.find_first_of("/", start))
- {
- // use the text between the beginning of the reference token
- // (start) and the last slash (slash).
- auto reference_token = reference_string.substr(start, slash - start);
-
- // check reference tokens are properly escaped
- for (size_t pos = reference_token.find_first_of("~");
- pos != std::string::npos;
- pos = reference_token.find_first_of("~", pos + 1))
- {
- assert(reference_token[pos] == '~');
-
- // ~ must be followed by 0 or 1
- if (pos == reference_token.size() - 1 or
- (reference_token[pos + 1] != '0' and
- reference_token[pos + 1] != '1'))
- {
- throw std::domain_error("escape error: '~' must be followed with '0' or '1'");
- }
- }
-
- // finally, store the reference token
- unescape(reference_token);
- result.push_back(reference_token);
- }
-
- return result;
- }
-
- private:
- /*!
- @brief replace all occurrences of a substring by another string
-
- @param[in,out] s the string to manipulate
- @param[in] f the substring to replace with @a t
- @param[out] t the string to replace @a f
-
- @return The string @a s where all occurrences of @a f are replaced
- with @a t.
-
- @pre The search string @a f must not be empty.
-
- @since version 2.0.0
- */
- static void replace_substring(std::string& s,
- const std::string& f,
- const std::string& t)
- {
- assert(not f.empty());
-
- for (
- size_t pos = s.find(f); // find first occurrence of f
- pos != std::string::npos; // make sure f was found
- s.replace(pos, f.size(), t), // replace with t
- pos = s.find(f, pos + t.size()) // find next occurrence of f
- );
- }
-
- /// escape tilde and slash
- static std::string escape(std::string s)
- {
- // escape "~"" to "~0" and "/" to "~1"
- replace_substring(s, "~", "~0");
- replace_substring(s, "/", "~1");
- return s;
- }
-
- /// unescape tilde and slash
- static void unescape(std::string& s)
- {
- // first transform any occurrence of the sequence '~1' to '/'
- replace_substring(s, "~1", "/");
- // then transform any occurrence of the sequence '~0' to '~'
- replace_substring(s, "~0", "~");
- }
-
- /*!
- @param[in] reference_string the reference string to the current value
- @param[in] value the value to consider
- @param[in,out] result the result object to insert values to
-
- @note Empty objects or arrays are flattened to `null`.
- */
- static void flatten(const std::string& reference_string,
- const basic_json& value,
- basic_json& result)
- {
- switch (value.m_type)
- {
- case value_t::array:
- {
- if (value.m_value.array->empty())
- {
- // flatten empty array as null
- result[reference_string] = nullptr;
- }
- else
- {
- // iterate array and use index as reference string
- for (size_t i = 0; i < value.m_value.array->size(); ++i)
- {
- flatten(reference_string + "/" + std::to_string(i),
- value.m_value.array->operator[](i), result);
- }
- }
- break;
- }
-
- case value_t::object:
- {
- if (value.m_value.object->empty())
- {
- // flatten empty object as null
- result[reference_string] = nullptr;
- }
- else
- {
- // iterate object and use keys as reference string
- for (const auto& element : *value.m_value.object)
- {
- flatten(reference_string + "/" + escape(element.first),
- element.second, result);
- }
- }
- break;
- }
-
- default:
- {
- // add primitive value with its reference string
- result[reference_string] = value;
- break;
- }
- }
- }
-
- /*!
- @param[in] value flattened JSON
-
- @return unflattened JSON
- */
- static basic_json unflatten(const basic_json& value)
- {
- if (not value.is_object())
- {
- throw std::domain_error("only objects can be unflattened");
- }
-
- basic_json result;
-
- // iterate the JSON object values
- for (const auto& element : *value.m_value.object)
- {
- if (not element.second.is_primitive())
- {
- throw std::domain_error("values in object must be primitive");
- }
-
- // assign value to reference pointed to by JSON pointer; Note
- // that if the JSON pointer is "" (i.e., points to the whole
- // value), function get_and_create returns a reference to
- // result itself. An assignment will then create a primitive
- // value.
- json_pointer(element.first).get_and_create(result) = element.second;
- }
-
- return result;
- }
+ return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
+ }
- private:
- /// the reference tokens
- std::vector<std::string> reference_tokens {};
- };
+ /// @}
//////////////////////////
// JSON Pointer support //
@@ -9470,9 +13677,9 @@ basic_json_parser_63:
@complexity Constant.
- @throw std::out_of_range if the JSON pointer can not be resolved
- @throw std::domain_error if an array index begins with '0'
- @throw std::invalid_argument if an array index was not a number
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.404 if the JSON pointer can not be resolved
@liveexample{The behavior is shown in the example.,operatorjson_pointer}
@@ -9497,9 +13704,10 @@ basic_json_parser_63:
@complexity Constant.
- @throw std::out_of_range if the JSON pointer can not be resolved
- @throw std::domain_error if an array index begins with '0'
- @throw std::invalid_argument if an array index was not a number
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
@liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
@@ -9520,15 +13728,33 @@ basic_json_parser_63:
@return reference to the element pointed to by @a ptr
- @complexity Constant.
+ @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+ begins with '0'. See example below.
- @throw std::out_of_range if the JSON pointer can not be resolved
- @throw std::domain_error if an array index begins with '0'
- @throw std::invalid_argument if an array index was not a number
+ @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+ is not a number. See example below.
- @liveexample{The behavior is shown in the example.,at_json_pointer}
+ @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+ is out of range. See example below.
+
+ @throw out_of_range.402 if the array index '-' is used in the passed JSON
+ pointer @a ptr. As `at` provides checked access (and no elements are
+ implicitly inserted), the index '-' is always invalid. See example below.
+
+ @throw out_of_range.403 if the JSON pointer describes a key of an object
+ which cannot be found. See example below.
+
+ @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+ See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
@since version 2.0.0
+
+ @liveexample{The behavior is shown in the example.,at_json_pointer}
*/
reference at(const json_pointer& ptr)
{
@@ -9545,15 +13771,33 @@ basic_json_parser_63:
@return reference to the element pointed to by @a ptr
- @complexity Constant.
+ @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+ begins with '0'. See example below.
- @throw std::out_of_range if the JSON pointer can not be resolved
- @throw std::domain_error if an array index begins with '0'
- @throw std::invalid_argument if an array index was not a number
+ @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+ is not a number. See example below.
- @liveexample{The behavior is shown in the example.,at_json_pointer_const}
+ @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+ is out of range. See example below.
+
+ @throw out_of_range.402 if the array index '-' is used in the passed JSON
+ pointer @a ptr. As `at` provides checked access (and no elements are
+ implicitly inserted), the index '-' is always invalid. See example below.
+
+ @throw out_of_range.403 if the JSON pointer describes a key of an object
+ which cannot be found. See example below.
+
+ @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+ See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
@since version 2.0.0
+
+ @liveexample{The behavior is shown in the example.,at_json_pointer_const}
*/
const_reference at(const json_pointer& ptr) const
{
@@ -9568,7 +13812,7 @@ basic_json_parser_63:
primitive. The original JSON value can be restored using the @ref
unflatten() function.
- @return an object that maps JSON pointers to primitve values
+ @return an object that maps JSON pointers to primitive values
@note Empty objects and arrays are flattened to `null` and will not be
reconstructed correctly by the @ref unflatten() function.
@@ -9609,6 +13853,9 @@ basic_json_parser_63:
@complexity Linear in the size the JSON value.
+ @throw type_error.314 if value is not an object
+ @throw type_error.315 if object values are not primitive
+
@liveexample{The following code shows how a flattened JSON object is
unflattened into the original nested JSON object.,unflatten}
@@ -9635,7 +13882,7 @@ basic_json_parser_63:
[JSON Patch](http://jsonpatch.com) defines a JSON document structure for
expressing a sequence of operations to apply to a JSON) document. With
- this funcion, a JSON Patch is applied to the current JSON value by
+ this function, a JSON Patch is applied to the current JSON value by
executing all operations from the patch.
@param[in] json_patch JSON patch document
@@ -9646,12 +13893,23 @@ basic_json_parser_63:
any case, the original value is not changed: the patch is applied
to a copy of the value.
- @throw std::out_of_range if a JSON pointer inside the patch could not
- be resolved successfully in the current JSON value; example: `"key baz
- not found"`
- @throw invalid_argument if the JSON patch is malformed (e.g., mandatory
+ @throw parse_error.104 if the JSON patch does not consist of an array of
+ objects
+
+ @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
attributes are missing); example: `"operation add must have member path"`
+ @throw out_of_range.401 if an array index is out of range.
+
+ @throw out_of_range.403 if a JSON pointer inside the patch could not be
+ resolved successfully in the current JSON value; example: `"key baz not
+ found"`
+
+ @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
+ "move")
+
+ @throw other_error.501 if "test" operation was unsuccessful
+
@complexity Linear in the size of the JSON value and the length of the
JSON patch. As usually only a fraction of the JSON value is affected by
the patch, the complexity can usually be neglected.
@@ -9674,7 +13932,7 @@ basic_json_parser_63:
// the valid JSON Patch operations
enum class patch_operations {add, remove, replace, move, copy, test, invalid};
- const auto get_op = [](const std::string op)
+ const auto get_op = [](const std::string & op)
{
if (op == "add")
{
@@ -9718,7 +13976,7 @@ basic_json_parser_63:
json_pointer top_pointer = ptr.top();
if (top_pointer != ptr)
{
- basic_json& x = result.at(top_pointer);
+ result.at(top_pointer);
}
// get reference to parent of JSON pointer ptr
@@ -9744,11 +14002,11 @@ basic_json_parser_63:
}
else
{
- const auto idx = std::stoi(last_path);
- if (static_cast<size_type>(idx) > parent.size())
+ const auto idx = json_pointer::array_index(last_path);
+ if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
{
// avoid undefined behavior
- throw std::out_of_range("array index " + std::to_string(idx) + " is out of range");
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
}
else
{
@@ -9780,30 +14038,29 @@ basic_json_parser_63:
{
// perform range check
auto it = parent.find(last_path);
- if (it != parent.end())
+ if (JSON_LIKELY(it != parent.end()))
{
parent.erase(it);
}
else
{
- throw std::out_of_range("key '" + last_path + "' not found");
+ JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
}
}
else if (parent.is_array())
{
// note erase performs range check
- parent.erase(static_cast<size_type>(std::stoi(last_path)));
+ parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
}
};
- // type check
- if (not json_patch.is_array())
+ // type check: top level value must be an array
+ if (JSON_UNLIKELY(not json_patch.is_array()))
{
- // a JSON patch must be an array of objects
- throw std::invalid_argument("JSON patch must be an array of objects");
+ JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
}
- // iterate and apply th eoperations
+ // iterate and apply the operations
for (const auto& val : json_patch)
{
// wrapper to get a value for an operation
@@ -9818,25 +14075,25 @@ basic_json_parser_63:
const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
// check if desired value is present
- if (it == val.m_value.object->end())
+ if (JSON_UNLIKELY(it == val.m_value.object->end()))
{
- throw std::invalid_argument(error_msg + " must have member '" + member + "'");
+ JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
}
// check if result is of type string
- if (string_type and not it->second.is_string())
+ if (JSON_UNLIKELY(string_type and not it->second.is_string()))
{
- throw std::invalid_argument(error_msg + " must have string member '" + member + "'");
+ JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
}
// no error: return value
return it->second;
};
- // type check
- if (not val.is_object())
+ // type check: every element of the array must be an object
+ if (JSON_UNLIKELY(not val.is_object()))
{
- throw std::invalid_argument("JSON patch must be an array of objects");
+ JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
}
// collect mandatory members
@@ -9884,32 +14141,37 @@ basic_json_parser_63:
case patch_operations::copy:
{
- const std::string from_path = get_value("copy", "from", true);;
+ const std::string from_path = get_value("copy", "from", true);
const json_pointer from_ptr(from_path);
// the "from" location must exist - use at()
- result[ptr] = result.at(from_ptr);
+ basic_json v = result.at(from_ptr);
+
+ // The copy is functionally identical to an "add"
+ // operation at the target location using the value
+ // specified in the "from" member.
+ operation_add(ptr, v);
break;
}
case patch_operations::test:
{
bool success = false;
- try
+ JSON_TRY
{
// check if "value" matches the one at "path"
// the "path" location must exist - use at()
success = (result.at(ptr) == get_value("test", "value", false));
}
- catch (std::out_of_range&)
+ JSON_CATCH (out_of_range&)
{
// ignore out of range errors: success remains false
}
// throw an exception if test fails
- if (not success)
+ if (JSON_UNLIKELY(not success))
{
- throw std::domain_error("unsuccessful: " + val.dump());
+ JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
}
break;
@@ -9919,7 +14181,7 @@ basic_json_parser_63:
{
// op must be "add", "remove", "replace", "move", "copy", or
// "test"
- throw std::invalid_argument("operation value '" + op + "' is invalid");
+ JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
}
}
}
@@ -9942,8 +14204,8 @@ basic_json_parser_63:
@note Currently, only `remove`, `add`, and `replace` operations are
generated.
- @param[in] source JSON value to copare from
- @param[in] target JSON value to copare against
+ @param[in] source JSON value to compare from
+ @param[in] target JSON value to compare against
@param[in] path helper value to create JSON pointers
@return a JSON patch to convert the @a source to @a target
@@ -9959,9 +14221,8 @@ basic_json_parser_63:
@since version 2.0.0
*/
- static basic_json diff(const basic_json& source,
- const basic_json& target,
- std::string path = "")
+ static basic_json diff(const basic_json& source, const basic_json& target,
+ const std::string& path = "")
{
// the patch
basic_json result(value_t::array);
@@ -9977,9 +14238,7 @@ basic_json_parser_63:
// different types: replace value
result.push_back(
{
- {"op", "replace"},
- {"path", path},
- {"value", target}
+ {"op", "replace"}, {"path", path}, {"value", target}
});
}
else
@@ -9989,7 +14248,7 @@ basic_json_parser_63:
case value_t::array:
{
// first pass: traverse common elements
- size_t i = 0;
+ std::size_t i = 0;
while (i < source.size() and i < target.size())
{
// recursive call to compare array values at index i
@@ -10002,9 +14261,12 @@ basic_json_parser_63:
// in a second pass, traverse the remaining elements
// remove my remaining elements
+ const auto end_index = static_cast<difference_type>(result.size());
while (i < source.size())
{
- result.push_back(object(
+ // add operations in reverse order to avoid invalid
+ // indices
+ result.insert(result.begin() + end_index, object(
{
{"op", "remove"},
{"path", path + "/" + std::to_string(i)}
@@ -10030,7 +14292,7 @@ basic_json_parser_63:
case value_t::object:
{
// first pass: traverse this object's elements
- for (auto it = source.begin(); it != source.end(); ++it)
+ for (auto it = source.cbegin(); it != source.cend(); ++it)
{
// escape the key name to be used in a JSON patch
const auto key = json_pointer::escape(it.key());
@@ -10046,14 +14308,13 @@ basic_json_parser_63:
// found a key that is not in o -> remove it
result.push_back(object(
{
- {"op", "remove"},
- {"path", path + "/" + key}
+ {"op", "remove"}, {"path", path + "/" + key}
}));
}
}
// second pass: traverse other object's elements
- for (auto it = target.begin(); it != target.end(); ++it)
+ for (auto it = target.cbegin(); it != target.cend(); ++it)
{
if (source.find(it.key()) == source.end())
{
@@ -10061,8 +14322,7 @@ basic_json_parser_63:
const auto key = json_pointer::escape(it.key());
result.push_back(
{
- {"op", "add"},
- {"path", path + "/" + key},
+ {"op", "add"}, {"path", path + "/" + key},
{"value", it.value()}
});
}
@@ -10076,9 +14336,7 @@ basic_json_parser_63:
// both primitive type: replace value
result.push_back(
{
- {"op", "replace"},
- {"path", path},
- {"value", target}
+ {"op", "replace"}, {"path", path}, {"value", target}
});
break;
}
@@ -10091,7 +14349,6 @@ basic_json_parser_63:
/// @}
};
-
/////////////
// presets //
/////////////
@@ -10105,8 +14362,402 @@ uses the standard template types.
@since version 1.0.0
*/
using json = basic_json<>;
+
+//////////////////
+// json_pointer //
+//////////////////
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+NLOHMANN_BASIC_JSON_TPL&
+json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const
+{
+ using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;
+ auto result = &j;
+
+ // in case no reference tokens exist, return a reference to the JSON value
+ // j which will be overwritten by a primitive value
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (result->m_type)
+ {
+ case detail::value_t::null:
+ {
+ if (reference_token == "0")
+ {
+ // start a new array if reference token is 0
+ result = &result->operator[](0);
+ }
+ else
+ {
+ // start a new object otherwise
+ result = &result->operator[](reference_token);
+ }
+ break;
+ }
+
+ case detail::value_t::object:
+ {
+ // create an entry in the object
+ result = &result->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ // create an entry in the array
+ JSON_TRY
+ {
+ result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
+ }
+ JSON_CATCH(std::invalid_argument&)
+ {
+ JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+ }
+ break;
+ }
+
+ /*
+ The following code is only reached if there exists a reference
+ token _and_ the current value is primitive. In this case, we have
+ an error situation, because primitive values may only occur as
+ single value; that is, with an empty list of reference tokens.
+ */
+ default:
+ JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
+ }
+ }
+
+ return *result;
+}
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+NLOHMANN_BASIC_JSON_TPL&
+json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
+{
+ using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;
+ for (const auto& reference_token : reference_tokens)
+ {
+ // convert null values to arrays or objects before continuing
+ if (ptr->m_type == detail::value_t::null)
+ {
+ // check if reference token is a number
+ const bool nums =
+ std::all_of(reference_token.begin(), reference_token.end(),
+ [](const char x)
+ {
+ return (x >= '0' and x <= '9');
+ });
+
+ // change value to array for numbers or "-" or to object otherwise
+ *ptr = (nums or reference_token == "-")
+ ? detail::value_t::array
+ : detail::value_t::object;
+ }
+
+ switch (ptr->m_type)
+ {
+ case detail::value_t::object:
+ {
+ // use unchecked object access
+ ptr = &ptr->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ // error condition (cf. RFC 6901, Sect. 4)
+ if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+ {
+ JSON_THROW(detail::parse_error::create(106, 0,
+ "array index '" + reference_token +
+ "' must not begin with '0'"));
+ }
+
+ if (reference_token == "-")
+ {
+ // explicitly treat "-" as index beyond the end
+ ptr = &ptr->operator[](ptr->m_value.array->size());
+ }
+ else
+ {
+ // convert array index to number; unchecked access
+ JSON_TRY
+ {
+ ptr = &ptr->operator[](
+ static_cast<size_type>(array_index(reference_token)));
+ }
+ JSON_CATCH(std::invalid_argument&)
+ {
+ JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+ }
+ }
+ break;
+ }
+
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+ }
+ }
+
+ return *ptr;
+}
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+NLOHMANN_BASIC_JSON_TPL&
+json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const
+{
+ using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->m_type)
+ {
+ case detail::value_t::object:
+ {
+ // note: at performs range check
+ ptr = &ptr->at(reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_UNLIKELY(reference_token == "-"))
+ {
+ // "-" always fails the range check
+ JSON_THROW(detail::out_of_range::create(402,
+ "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+ ") is out of range"));
+ }
+
+ // error condition (cf. RFC 6901, Sect. 4)
+ if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+ {
+ JSON_THROW(detail::parse_error::create(106, 0,
+ "array index '" + reference_token +
+ "' must not begin with '0'"));
+ }
+
+ // note: at performs range check
+ JSON_TRY
+ {
+ ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+ }
+ JSON_CATCH(std::invalid_argument&)
+ {
+ JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+ }
+ break;
+ }
+
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+ }
+ }
+
+ return *ptr;
+}
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+const NLOHMANN_BASIC_JSON_TPL&
+json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
+{
+ using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->m_type)
+ {
+ case detail::value_t::object:
+ {
+ // use unchecked object access
+ ptr = &ptr->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_UNLIKELY(reference_token == "-"))
+ {
+ // "-" cannot be used for const access
+ JSON_THROW(detail::out_of_range::create(402,
+ "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+ ") is out of range"));
+ }
+
+ // error condition (cf. RFC 6901, Sect. 4)
+ if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+ {
+ JSON_THROW(detail::parse_error::create(106, 0,
+ "array index '" + reference_token +
+ "' must not begin with '0'"));
+ }
+
+ // use unchecked array access
+ JSON_TRY
+ {
+ ptr = &ptr->operator[](
+ static_cast<size_type>(array_index(reference_token)));
+ }
+ JSON_CATCH(std::invalid_argument&)
+ {
+ JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+ }
+ break;
+ }
+
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+ }
+ }
+
+ return *ptr;
+}
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+const NLOHMANN_BASIC_JSON_TPL&
+json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
+{
+ using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->m_type)
+ {
+ case detail::value_t::object:
+ {
+ // note: at performs range check
+ ptr = &ptr->at(reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_UNLIKELY(reference_token == "-"))
+ {
+ // "-" always fails the range check
+ JSON_THROW(detail::out_of_range::create(402,
+ "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+ ") is out of range"));
+ }
+
+ // error condition (cf. RFC 6901, Sect. 4)
+ if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+ {
+ JSON_THROW(detail::parse_error::create(106, 0,
+ "array index '" + reference_token +
+ "' must not begin with '0'"));
+ }
+
+ // note: at performs range check
+ JSON_TRY
+ {
+ ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+ }
+ JSON_CATCH(std::invalid_argument&)
+ {
+ JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+ }
+ break;
+ }
+
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+ }
+ }
+
+ return *ptr;
+}
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+void json_pointer::flatten(const std::string& reference_string,
+ const NLOHMANN_BASIC_JSON_TPL& value,
+ NLOHMANN_BASIC_JSON_TPL& result)
+{
+ switch (value.m_type)
+ {
+ case detail::value_t::array:
+ {
+ if (value.m_value.array->empty())
+ {
+ // flatten empty array as null
+ result[reference_string] = nullptr;
+ }
+ else
+ {
+ // iterate array and use index as reference string
+ for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
+ {
+ flatten(reference_string + "/" + std::to_string(i),
+ value.m_value.array->operator[](i), result);
+ }
+ }
+ break;
+ }
+
+ case detail::value_t::object:
+ {
+ if (value.m_value.object->empty())
+ {
+ // flatten empty object as null
+ result[reference_string] = nullptr;
+ }
+ else
+ {
+ // iterate object and use keys as reference string
+ for (const auto& element : *value.m_value.object)
+ {
+ flatten(reference_string + "/" + escape(element.first), element.second, result);
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ // add primitive value with its reference string
+ result[reference_string] = value;
+ break;
+ }
+ }
}
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+NLOHMANN_BASIC_JSON_TPL
+json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value)
+{
+ if (JSON_UNLIKELY(not value.is_object()))
+ {
+ JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
+ }
+
+ NLOHMANN_BASIC_JSON_TPL result;
+
+ // iterate the JSON object values
+ for (const auto& element : *value.m_value.object)
+ {
+ if (JSON_UNLIKELY(not element.second.is_primitive()))
+ {
+ JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
+ }
+
+ // assign value to reference pointed to by JSON pointer; Note that if
+ // the JSON pointer is "" (i.e., points to the whole value), function
+ // get_and_create returns a reference to result itself. An assignment
+ // will then create a primitive value.
+ json_pointer(element.first).get_and_create(result) = element.second;
+ }
+
+ return result;
+}
+
+inline bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept
+{
+ return (lhs.reference_tokens == rhs.reference_tokens);
+}
+
+inline bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept
+{
+ return not (lhs == rhs);
+}
+} // namespace nlohmann
+
///////////////////////
// nonmember support //
@@ -10120,7 +14771,7 @@ namespace std
@since version 1.0.0
*/
-template <>
+template<>
inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value and
@@ -10131,7 +14782,7 @@ inline void swap(nlohmann::json& j1,
}
/// hash value for JSON objects
-template <>
+template<>
struct hash<nlohmann::json>
{
/*!
@@ -10146,38 +14797,78 @@ struct hash<nlohmann::json>
return h(j.dump());
}
};
-}
+
+/// specialization for std::less<value_t>
+/// @note: do not remove the space after '<',
+/// see https://github.com/nlohmann/json/pull/679
+template<>
+struct less< ::nlohmann::detail::value_t>
+{
+ /*!
+ @brief compare two value_t enum values
+ @since version 3.0.0
+ */
+ bool operator()(nlohmann::detail::value_t lhs,
+ nlohmann::detail::value_t rhs) const noexcept
+ {
+ return nlohmann::detail::operator<(lhs, rhs);
+ }
+};
+
+} // namespace std
/*!
@brief user-defined string literal for JSON values
This operator implements a user-defined string literal for JSON objects. It
-can be used by adding \p "_json" to a string literal and returns a JSON object
+can be used by adding `"_json"` to a string literal and returns a JSON object
if no parse error occurred.
@param[in] s a string representation of a JSON object
+@param[in] n the length of string @a s
@return a JSON object
@since version 1.0.0
*/
-inline nlohmann::json operator "" _json(const char* s, std::size_t)
+inline nlohmann::json operator "" _json(const char* s, std::size_t n)
{
- return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
+ return nlohmann::json::parse(s, s + n);
}
/*!
@brief user-defined string literal for JSON pointer
+This operator implements a user-defined string literal for JSON Pointers. It
+can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
+object if no parse error occurred.
+
+@param[in] s a string representation of a JSON Pointer
+@param[in] n the length of string @a s
+@return a JSON pointer object
+
@since version 2.0.0
*/
-inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t)
+inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
{
- return nlohmann::json::json_pointer(s);
+ return nlohmann::json::json_pointer(std::string(s, n));
}
// restore GCC/clang diagnostic settings
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#pragma GCC diagnostic pop
#endif
+#if defined(__clang__)
+ #pragma GCC diagnostic pop
+#endif
+
+// clean up
+#undef JSON_CATCH
+#undef JSON_THROW
+#undef JSON_TRY
+#undef JSON_LIKELY
+#undef JSON_UNLIKELY
+#undef JSON_DEPRECATED
+#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
+#undef NLOHMANN_BASIC_JSON_TPL
#endif
diff --git a/ext/librethinkdbxx/.travis.yml b/ext/librethinkdbxx/.travis.yml
new file mode 100644
index 00000000..b306a410
--- /dev/null
+++ b/ext/librethinkdbxx/.travis.yml
@@ -0,0 +1,11 @@
+sudo: required
+dist: trusty
+
+python:
+ - "3.4.3"
+
+addons:
+ rethinkdb: "2.3"
+
+script:
+ - make test
diff --git a/ext/librethinkdbxx/COPYRIGHT b/ext/librethinkdbxx/COPYRIGHT
new file mode 100644
index 00000000..c25145d5
--- /dev/null
+++ b/ext/librethinkdbxx/COPYRIGHT
@@ -0,0 +1,16 @@
+RethinkDB Language Drivers
+
+Copyright 2010-2012 RethinkDB
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this product except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/ext/librethinkdbxx/Makefile b/ext/librethinkdbxx/Makefile
new file mode 100644
index 00000000..ba319c16
--- /dev/null
+++ b/ext/librethinkdbxx/Makefile
@@ -0,0 +1,126 @@
+# Customisable build settings
+
+CXX ?= clang++
+CXXFLAGS ?=
+INCLUDE_PYTHON_DOCS ?= no
+DEBUG ?= no
+PYTHON ?= python3
+
+# Required build settings
+
+ifneq (no,$(DEBUG))
+ CXXFLAGS += -ggdb
+else
+ CXXFLAGS += -O3 # -flto
+endif
+
+CXXFLAGS += -std=c++11 -I'build/gen' -Wall -pthread -fPIC
+
+prefix ?= /usr
+DESTDIR ?=
+
+.DELETE_ON_ERROR:
+SHELL := /bin/bash
+
+modules := connection datum json term cursor types utils
+headers := utils error exceptions types datum connection cursor term
+
+o_files := $(patsubst %, build/obj/%.o, $(modules))
+d_files := $(patsubst %, build/dep/%.d, $(modules))
+
+skip_tests := regression/1133 regression/767 regression/1005 # python-only
+skip_tests += arity # arity errors are compile-time
+skip_tests += geo # geo types not implemented yet
+skip_tests += limits # possibly broken tests: https://github.com/rethinkdb/rethinkdb/issues/5940
+
+upstream_tests := \
+ $(filter-out %.rb.%, \
+ $(filter-out $(patsubst %,test/upstream/%%, $(skip_tests)), \
+ $(filter test/upstream/$(test_filter)%, \
+ $(shell find test/upstream -name '*.yaml' | egrep -v '.(rb|js).yaml$$'))))
+upstream_tests_cc := $(patsubst %.yaml, build/tests/%.cc, $(upstream_tests))
+upstream_tests_o := $(patsubst %.cc, %.o, $(upstream_tests_cc))
+
+.PRECIOUS: $(upstream_tests_cc) $(upstream_tests_o)
+
+default: build/librethinkdb++.a build/include/rethinkdb.h build/librethinkdb++.so
+
+all: default build/test
+
+build/librethinkdb++.a: $(o_files)
+ ar rcs $@ $^
+
+build/librethinkdb++.so: $(o_files)
+ $(CXX) -o $@ $(CXXFLAGS) -shared $^
+
+build/obj/%.o: src/%.cc build/gen/protocol_defs.h
+ @mkdir -p $(dir $@)
+ @mkdir -p $(dir build/dep/$*.d)
+ $(CXX) -o $@ $(CXXFLAGS) -c $< -MP -MQ $@ -MD -MF build/dep/$*.d
+
+build/gen/protocol_defs.h: reql/ql2.proto reql/gen.py | build/gen/.
+ $(PYTHON) reql/gen.py $< > $@
+
+clean:
+ rm -rf build
+
+ifneq (no,$(INCLUDE_PYTHON_DOCS))
+build/include/rethinkdb.h: build/rethinkdb.nodocs.h reql/add_docs.py reql/python_docs.txt | build/include/.
+ $(PYTHON) reql/add_docs.py reql/python_docs.txt < $< > $@
+else
+build/include/rethinkdb.h: build/rethinkdb.nodocs.h | build/include/.
+ cp $< $@
+endif
+
+build/rethinkdb.nodocs.h: build/gen/protocol_defs.h $(patsubst %, src/%.h, $(headers))
+ ( echo "// Auto-generated file, built from $^"; \
+ echo '#pragma once'; \
+ cat $^ | \
+ grep -v '^#pragma once' | \
+ grep -v '^#include "'; \
+ ) > $@
+
+build/tests/%.cc: %.yaml test/yaml_to_cxx.py
+ @mkdir -p $(dir $@)
+ $(PYTHON) test/yaml_to_cxx.py $< > $@
+
+build/tests/upstream_tests.cc: $(upstream_tests) test/gen_index_cxx.py FORCE | build/tests/.
+ @echo '$(PYTHON) test/gen_index_cxx.py $(wordlist 1,5,$(upstream_tests)) ... > $@'
+ @$(PYTHON) test/gen_index_cxx.py $(upstream_tests) > $@
+
+build/tests/%.o: build/tests/%.cc build/include/rethinkdb.h test/testlib.h | build/tests/.
+ $(CXX) -o $@ $(CXXFLAGS) -isystem build/include -I test -c $< -Wno-unused-variable
+
+build/tests/%.o: test/%.cc test/testlib.h build/include/rethinkdb.h | build/tests/.
+ $(CXX) -o $@ $(CXXFLAGS) -isystem build/include -I test -c $<
+
+build/test: build/tests/testlib.o build/tests/test.o build/tests/upstream_tests.o $(upstream_tests_o) build/librethinkdb++.a
+ @echo $(CXX) -o $@ $(CXXFLAGS) $(wordlist 1,5,$^) ...
+ @$(CXX) -o $@ $(CXXFLAGS) build/librethinkdb++.a $^
+
+.PHONY: test
+test: build/test
+ build/test
+
+build/bench: build/tests/bench.o build/librethinkdb++.a
+ @$(CXX) -o $@ $(CXXFLAGS) -isystem build/include build/librethinkdb++.a $^
+
+.PHONY: bench
+bench: build/bench
+ build/bench
+
+.PHONY: install
+install: build/librethinkdb++.a build/include/rethinkdb.h build/librethinkdb++.so
+ install -m755 -d $(DESTDIR)$(prefix)/lib
+ install -m755 -d $(DESTDIR)$(prefix)/include
+ install -m644 build/librethinkdb++.a $(DESTDIR)$(prefix)/lib/librethinkdb++.a
+ install -m644 build/librethinkdb++.so $(DESTDIR)$(prefix)/lib/librethinkdb++.so
+ install -m644 build/include/rethinkdb.h $(DESTDIR)$(prefix)/include/rethinkdb.h
+
+%/.:
+ mkdir -p $*
+
+.PHONY: FORCE
+FORCE:
+
+-include $(d_files)
diff --git a/ext/librethinkdbxx/README.md b/ext/librethinkdbxx/README.md
new file mode 100644
index 00000000..92fa9136
--- /dev/null
+++ b/ext/librethinkdbxx/README.md
@@ -0,0 +1,72 @@
+# RethinkDB driver for C++
+
+This driver is compatible with RethinkDB 2.0. It is based on the
+official RethinkDB Python driver.
+
+* [RethinkDB server](http://rethinkdb.com/)
+* [RethinkDB API docs](http://rethinkdb.com/api/python/)
+
+## Example
+
+```
+#include <memory>
+#include <cstdio>
+#include <rethinkdb.h>
+
+namespace R = RethinkDB;
+
+int main() {
+ std::unique_ptr<R::Connection> conn = R::connect("localhost", 28015);
+ R::Cursor cursor = R::table("users").filter(R::row["age"] > 14).run(*conn);
+ for (R::Datum& user : cursor) {
+ printf("%s\n", user.as_json().c_str());
+ }
+}
+```
+
+## Build
+
+Requires a modern C++ compiler. to build and install, run:
+
+```
+make
+make install
+```
+
+Will build `include/rethinkdb.h`, `librethinkdb++.a` and
+`librethinkdb++.so` into the `build/` directory.
+
+To include documentation from the Python driver in the header file,
+pass the following argument to make.
+
+```
+make INCLUDE_PYTHON_DOCS=yes
+```
+
+To build in debug mode:
+
+```
+make DEBUG=yes
+```
+
+To install to a specific location:
+
+```
+make install prefix=/usr/local DESTDIR=
+```
+
+## Status
+
+Still in early stages of development.
+
+## Tests
+
+This driver is tested against the upstream ReQL tests from the
+RethinkDB repo, which are programmatically translated from Python to
+C++. As of 34dc13c, all tests pass:
+
+```
+$ make test
+...
+SUCCESS: 2053 tests passed
+```
diff --git a/ext/librethinkdbxx/reql/add_docs.py b/ext/librethinkdbxx/reql/add_docs.py
new file mode 100644
index 00000000..67f08df8
--- /dev/null
+++ b/ext/librethinkdbxx/reql/add_docs.py
@@ -0,0 +1,80 @@
+from sys import stdin, stderr, stdout, argv
+from re import match, sub
+
+docs = {}
+
+for line in open(argv[1]):
+ res = match('^\t\(([^,]*), (.*)\),$', line)
+ if res:
+ fullname = res.group(1)
+ docs[fullname.split('.')[-1]] = eval(res.group(2)).decode('utf-8')
+
+translate_name = {
+ 'name': None,
+ 'delete_': 'delete',
+ 'union_': 'union',
+ 'operator[]': '__getitem__',
+ 'operator+': '__add__',
+ 'operator-': '__sub__',
+ 'operator*': '__mul__',
+ 'operator/': '__div__',
+ 'operator%': '__mod__',
+ 'operator&&': 'and_',
+ 'operator||': 'or_',
+ 'operator==': '__eq__',
+ 'operator!=': '__ne__',
+ 'operator>': '__gt__',
+ 'operator>=': '__ge__',
+ 'operator<': '__lt__',
+ 'operator<=': '__le__',
+ 'operator!': 'not_',
+ 'default_': 'default',
+ 'array': None,
+ 'desc': None,
+ 'asc': None,
+ 'maxval': None,
+ 'minval': None,
+ 'january': None,
+ 'february': None,
+ 'march': None,
+ 'april': None,
+ 'may': None,
+ 'june': None,
+ 'july': None,
+ 'august': None,
+ 'september': None,
+ 'october': None,
+ 'november': None,
+ 'december': None,
+ 'monday': None,
+ 'tuesday': None,
+ 'wednesday': None,
+ 'thursday': None,
+ 'friday': None,
+ 'saturday': None,
+ 'sunday': None,
+}
+
+def print_docs(name, line):
+ py_name = translate_name.get(name, name)
+ if py_name in docs:
+ indent = match("^( *)", line).group(1)
+ stdout.write('\n')
+ # TODO: convert the examples to C++
+ for line in docs[py_name].split('\n'):
+ stdout.write(indent + "// " + line + '\n')
+ elif py_name:
+ stderr.write('Warning: no docs for ' + py_name + ': ' + line)
+
+stdout.write('// Contains documentation copied as-is from the Python driver')
+
+for line in stdin:
+ res = match("^ *CO?[0-9_]+\(([^,)]+)|extern Query (\w+)|^ *// *(\$)doc\((\w+)\) *$", line)
+ if res:
+ name = res.group(1) or res.group(2) or res.group(4)
+ print_docs(name, line)
+ if not res.group(3):
+ stdout.write(line)
+ else:
+ stdout.write(line)
+
diff --git a/ext/librethinkdbxx/reql/gen.py b/ext/librethinkdbxx/reql/gen.py
new file mode 100644
index 00000000..2b1fe9fc
--- /dev/null
+++ b/ext/librethinkdbxx/reql/gen.py
@@ -0,0 +1,33 @@
+from sys import argv
+from re import sub, finditer, VERBOSE
+
+def gen(defs):
+ indent = 0
+ enum = False
+ def p(s): print(" " * (indent * 4) + s)
+ for item in finditer("""
+ (?P<type> message|enum) \\s+ (?P<name> \\w+) \\s* \\{ |
+ (?P<var> \\w+) \\s* = \\s* (?P<val> \\w+) \\s* ; |
+ \\}
+ """, defs, flags=VERBOSE):
+ if item.group(0) == "}":
+ indent = indent - 1
+ p("};" if enum else "}")
+ enum = False;
+ elif item.group('type') == 'enum':
+ p("enum class %s {" % item.group('name'))
+ indent = indent + 1
+ enum = True
+ elif item.group('type') == 'message':
+ p("namespace %s {" % item.group('name'))
+ indent = indent + 1
+ enum = False
+ else:
+ if enum:
+ p("%s = %s," % (item.group('var'), item.group('val')))
+
+print("// Auto-generated by reql/gen.py")
+print("#pragma once")
+print("namespace RethinkDB { namespace Protocol {")
+gen(sub("//.*", "", open(argv[1]).read()))
+print("} }")
diff --git a/ext/librethinkdbxx/reql/python_docs.txt b/ext/librethinkdbxx/reql/python_docs.txt
new file mode 100644
index 00000000..41a5c84e
--- /dev/null
+++ b/ext/librethinkdbxx/reql/python_docs.txt
@@ -0,0 +1,189 @@
+# This file was generated by _scripts/gen_python.py from the rethinkdb documentation in http://github.com/rethinkdb/docs
+# hash: "3d13a937cfdacb7ffa3dab2ce3ebdf25bd3c192e"
+
+import rethinkdb
+
+docsSource = [
+
+ (rethinkdb.net.Connection.close, b'conn.close(noreply_wait=True)\n\nClose an open connection.\n\nClosing a connection normally waits until all outstanding requests have finished and then frees any open resources associated with the connection. By passing `False` to the `noreply_wait` optional argument, the connection will be closed immediately, possibly aborting any outstanding noreply writes.\n\nA noreply query is executed by passing the `noreply` option to the [run](http://rethinkdb.com/api/python/run/) command, indicating that `run()` should not wait for the query to complete before returning. You may also explicitly wait for a noreply query to complete by using the [noreply_wait](http://rethinkdb.com/api/python/noreply_wait) command.\n\n*Example* Close an open connection, waiting for noreply writes to finish.\n\n conn.close()\n\n*Example* Close an open connection immediately.\n\n conn.close(noreply_wait=False)\n'),
+ (rethinkdb.connect, b'r.connect(host="localhost", port=28015, db="test", auth_key="", timeout=20) -> connection\nr.connect(host) -> connection\n\nCreate a new connection to the database server. The keyword arguments are:\n\n- `host`: host of the RethinkDB instance. The default value is `localhost`.\n- `port`: the driver port, by default `28015`.\n- `db`: the database used if not explicitly specified in a query, by default `test`.\n- `auth_key`: the authentication key, by default the empty string.\n- `timeout`: timeout period in seconds for the connection to be opened (default `20`).\n\nIf the connection cannot be established, a `RqlDriverError` exception will be thrown.\n\nThe authentication key can be set from the RethinkDB command line tool. Once set, client connections must provide the key as an option to `run` in order to make the connection. For more information, read "Using the RethinkDB authentication system" in the documentation on [securing your cluster](http://rethinkdb.com/docs/security/).\n\n__Note:__ Currently, the Python driver is not thread-safe. Each thread or multiprocessing PID should be given its own connection object. (This is likely to change in a future release of RethinkDB; you can track issue [#2427](https://github.com/rethinkdb/rethinkdb/issues/2427) for progress.)\n\n*Example* Opens a connection using the default host and port but specifying the default database.\n\n conn = r.connect(db=\'marvel\')\n\n*Example* Opens a new connection to the database.\n\n conn = r.connect(host = \'localhost\',\n port = 28015,\n db = \'heroes\',\n auth_key = \'hunter2\')\n\n'),
+ (rethinkdb.net.Connection.noreply_wait, b'conn.noreply_wait()\n\n`noreply_wait` ensures that previous queries with the `noreply` flag have been processed\nby the server. Note that this guarantee only applies to queries run on the given connection.\n\n*Example* We have previously run queries with the `noreply` argument set to `True`. Now\nwait until the server has processed them.\n\n conn.noreply_wait()\n\n'),
+ (rethinkdb, b'r -> r\n\nThe top-level ReQL namespace.\n\n*Example* Setup your top-level namespace.\n\n import rethinkdb as r\n\n'),
+ (rethinkdb.net.Connection.reconnect, b'conn.reconnect(noreply_wait=True)\n\nClose and reopen a connection.\n\nClosing a connection normally waits until all outstanding requests have finished and then frees any open resources associated with the connection. By passing `False` to the `noreply_wait` optional argument, the connection will be closed immediately, possibly aborting any outstanding noreply writes.\n\nA noreply query is executed by passing the `noreply` option to the [run](http://rethinkdb.com/api/python/run/) command, indicating that `run()` should not wait for the query to complete before returning. You may also explicitly wait for a noreply query to complete by using the [noreply_wait](http://rethinkdb.com/api/python/noreply_wait) command.\n\n*Example* Cancel outstanding requests/queries that are no longer needed.\n\n conn.reconnect(noreply_wait=False)\n'),
+ (rethinkdb.net.Connection.repl, b"conn.repl()\n\nSet the default connection to make REPL use easier. Allows calling\n`.run()` on queries without specifying a connection.\n\n__Note:__ Avoid using `repl` in application code. RethinkDB connection objects are not thread-safe, and calls to `connect` from multiple threads may change the global connection object used by `repl`. Applications should specify connections explicitly.\n\n*Example* Set the default connection for the REPL, then call\n`run()` without specifying the connection.\n\n r.connect(db='marvel').repl()\n r.table('heroes').run()\n"),
+ (rethinkdb.ast.RqlQuery.run, b'query.run(conn, use_outdated=False, time_format=\'native\', profile=False, durability="hard") -> cursor\nquery.run(conn, use_outdated=False, time_format=\'native\', profile=False, durability="hard") -> object\n\nRun a query on a connection, returning either a single JSON result or\na cursor, depending on the query.\n\nThe optional arguments are:\n\n- `use_outdated`: whether or not outdated reads are OK (default: `False`).\n- `time_format`: what format to return times in (default: `\'native\'`).\n Set this to `\'raw\'` if you want times returned as JSON objects for exporting.\n- `profile`: whether or not to return a profile of the query\'s\n execution (default: `False`).\n- `durability`: possible values are `\'hard\'` and `\'soft\'`. In soft durability mode RethinkDB\nwill acknowledge the write immediately after receiving it, but before the write has\nbeen committed to disk.\n- `group_format`: what format to return `grouped_data` and `grouped_streams` in (default: `\'native\'`).\n Set this to `\'raw\'` if you want the raw pseudotype.\n- `noreply`: set to `True` to not receive the result object or cursor and return immediately.\n- `db`: the database to run this query against as a string. The default is the database specified in the `db` parameter to [connect](http://rethinkdb.com/api/python/connect/) (which defaults to `test`). The database may also be specified with the [db](http://rethinkdb.com/api/python/db/) command.\n- `array_limit`: the maximum numbers of array elements that can be returned by a query (default: 100,000). This affects all ReQL commands that return arrays. Note that it has no effect on the size of arrays being _written_ to the database; those always have an upper limit of 100,000 elements.\n- `binary_format`: what format to return binary data in (default: `\'native\'`). Set this to `\'raw\'` if you want the raw pseudotype.\n- `min_batch_rows`: minimum number of rows to wait for before batching a result set (default: 8). This is an integer.\n- `max_batch_rows`: maximum number of rows to wait for before batching a result set (default: unlimited). This is an integer.\n- `max_batch_bytes`: maximum number of bytes to wait for before batching a result set (default: 1024). This is an integer.\n- `max_batch_seconds`: maximum number of seconds to wait before batching a result set (default: 0.5). This is a float (not an integer) and may be specified to the microsecond.\n- `first_batch_scaledown_factor`: factor to scale the other parameters down by on the first batch (default: 4). For example, with this set to 8 and `max_batch_rows` set to 80, on the first batch `max_batch_rows` will be adjusted to 10 (80 / 8). This allows the first batch to return faster.\n\n*Example* Run a query on the connection `conn` and print out every\nrow in the result.\n\n for doc in r.table(\'marvel\').run(conn):\n print doc\n\n*Example* If you are OK with potentially out of date data from all\nthe tables involved in this query and want potentially faster reads,\npass a flag allowing out of date data in an options object. Settings\nfor individual tables will supercede this global setting for all\ntables in the query.\n\n r.table(\'marvel\').run(conn, use_outdated=True)\n\n*Example* If you just want to send a write and forget about it, you\ncan set `noreply` to true in the options. In this case `run` will\nreturn immediately.\n\n r.table(\'marvel\').run(conn, noreply=True)\n\n*Example* If you want to specify whether to wait for a write to be\nwritten to disk (overriding the table\'s default settings), you can set\n`durability` to `\'hard\'` or `\'soft\'` in the options.\n\n r.table(\'marvel\')\n .insert({ \'superhero\': \'Iron Man\', \'superpower\': \'Arc Reactor\' })\n .run(conn, noreply=True, durability=\'soft\')\n\n*Example* If you do not want a time object to be converted to a\nnative date object, you can pass a `time_format` flag to prevent it\n(valid flags are "raw" and "native"). This query returns an object\nwith two fields (`epoch_time` and `$reql_type$`) instead of a native date\nobject.\n\n r.now().run(conn, time_format="raw")\n\n*Example* Specify the database to use for the query.\n\n for doc in r.table(\'marvel\').run(conn, db=\'heroes\'):\n print doc\n\nThis is equivalent to using the `db` command to specify the database:\n\n r.db(\'heroes\').table(\'marvel\').run(conn) ...\n\n*Example* Change the batching parameters for this query.\n\n r.table(\'marvel\').run(conn, max_batch_rows=16, max_batch_bytes=2048)\n'),
+ (rethinkdb.set_loop_type, b'r.set_loop_type(string)\n\nSet an asynchronous event loop model. Currently, the only event loop model RethinkDB supports is `"tornado"`, for use with the [Tornado web framework](http://www.tornadoweb.org). After setting the event loop to `"tornado"`, the [connect](http://rethinkdb.com/api/python/connect) and [run](http://rethinkdb.com/api/python/run) commands will return Tornado `Future` objects.\n\n*Example* Read a table\'s data using Tornado.\n\n r.set_loop_type("tornado")\n conn = r.connect(host=\'localhost\', port=28015)\n \n @gen.coroutine\n def use_cursor(conn):\n # Print every row in the table.\n cursor = yield r.table(\'test\').order_by(index="id").run(yield conn)\n while (yield cursor.fetch_next()):\n item = yield cursor.next()\n print(item)\n\nFor a longer discussion with Tornado examples, see the documentation article on [Asynchronous connections][ac].\n\n[ac]: /docs/async-connections/\n'),
+ (rethinkdb.net.Connection.use, b"conn.use(db_name)\n\nChange the default database on this connection.\n\n*Example* Change the default database so that we don't need to\nspecify the database when referencing a table.\n\n conn.use('marvel')\n r.table('heroes').run(conn) # refers to r.db('marvel').table('heroes')\n"),
+ (rethinkdb.ast.Table.config, b'table.config() -> selection&lt;object&gt;\ndatabase.config() -> selection&lt;object&gt;\n\nQuery (read and/or update) the configurations for individual tables or databases.\n\nThe `config` command is a shorthand way to access the `table_config` or `db_config` [System tables](http://rethinkdb.com/docs/system-tables/). It will return the single row from the system that corresponds to the database or table configuration, as if [get](http://rethinkdb.com/api/python/get) had been called on the system table with the UUID of the database or table in question.\n\n*Example* Get the configuration for the `users` table.\n\n r.table(\'users\').config().run(conn)\n \n {\n "id": "31c92680-f70c-4a4b-a49e-b238eb12c023",\n "name": "users",\n "db": "superstuff",\n "primary_key": "id",\n "shards": [\n {"primary_replica": "a", "replicas": ["a", "b"]},\n {"primary_replica": "d", "replicas": ["c", "d"]}\n ],\n "write_acks": "majority",\n "durability": "hard"\n }\n\n*Example* Change the write acknowledgement requirement of the `users` table.\n\n r.table(\'users\').config().update({\'write_acks\': \'single\'}).run(conn)\n'),
+ (rethinkdb.ast.Table.rebalance, b'table.rebalance() -> object\ndatabase.rebalance() -> object\n\nRebalances the shards of a table. When called on a database, all the tables in that database will be rebalanced.\n\nThe `rebalance` command operates by measuring the distribution of primary keys within a table and picking split points that will give each shard approximately the same number of documents. It won\'t change the number of shards within a table, or change any other configuration aspect for the table or the database.\n\nA table will lose availability temporarily after `rebalance` is called; use the [wait](http://rethinkdb.com/api/python/wait) command to wait for the table to become available again, or [status](http://rethinkdb.com/api/python/status) to check if the table is available for writing.\n\nRethinkDB automatically rebalances tables when the number of shards are increased, and as long as your documents have evenly distributed primary keys&mdash;such as the default UUIDs&mdash;it is rarely necessary to call `rebalance` manually. Cases where `rebalance` may need to be called include:\n\n* Tables with unevenly distributed primary keys, such as incrementing integers\n* Changing a table\'s primary key type\n* Increasing the number of shards on an empty table, then using non-UUID primary keys in that table\n\nThe [web UI](http://rethinkdb.com/docs/administration-tools/) (and the [info](http://rethinkdb.com/api/python/info) command) can be used to tell you when a table\'s shards need to be rebalanced.\n\nThe return value of `rebalance` is an object with two fields:\n\n* `rebalanced`: the number of tables rebalanced.\n* `status_changes`: a list of new and old table status values. Each element of the list will be an object with two fields:\n * `old_val`: The table\'s [status](http://rethinkdb.com/api/python/status) value before `rebalance` was executed. \n * `new_val`: The table\'s `status` value after `rebalance` was executed. (This value will almost always indicate the table is unavailable.)\n\nSee the [status](http://rethinkdb.com/api/python/status) command for an explanation of the objects returned in the `old_val` and `new_val` fields.\n\n*Example* Rebalance a table.\n\n r.table(\'superheroes\').rebalance().run(conn)\n \n {\n "rebalanced": 1,\n "status_changes": [\n {\n "old_val": {\n "db": "database",\n "id": "5cb35225-81b2-4cec-9eef-bfad15481265",\n "name": "superheroes",\n "shards": [\n {\n "primary_replica": "jeeves",\n "replicas": [\n {\n "server": "jeeves",\n "state": "ready"\n }\n ]\n },\n {\n "primary_replica": "jeeves",\n "replicas": [\n {\n "server": "jeeves",\n "state": "ready"\n }\n ]\n }\n ],\n "status": {\n "all_replicas_ready": True,\n "ready_for_outdated_reads": True,\n "ready_for_reads": True,\n "ready_for_writes": True\n }\n },\n "new_val": {\n "db": "database",\n "id": "5cb35225-81b2-4cec-9eef-bfad15481265",\n "name": "superheroes",\n "shards": [\n {\n "primary_replica": "jeeves",\n "replicas": [\n {\n "server": "jeeves",\n "state": "transitioning"\n }\n ]\n },\n {\n "primary_replica": "jeeves",\n "replicas": [\n {\n "server": "jeeves",\n "state": "transitioning"\n }\n ]\n }\n ],\n "status": {\n "all_replicas_ready": False,\n "ready_for_outdated_reads": False,\n "ready_for_reads": False,\n "ready_for_writes": False\n }\n }\n \n }\n ]\n }\n'),
+ (rethinkdb.ast.Table.reconfigure, b'table.reconfigure(shards=<s>, replicas=<r>[, primary_replica_tag=<t>, dry_run=False]) -> object\ndatabase.reconfigure(shards=<s>, replicas=<r>[, primary_replica_tag=<t>, dry_run=False]) -> object\n\nReconfigure a table\'s sharding and replication.\n\n* `shards`: the number of shards, an integer from 1-32. Required.\n* `replicas`: either an integer or a mapping object. Required.\n * If `replicas` is an integer, it specifies the number of replicas per shard. Specifying more replicas than there are servers will return an error.\n * If `replicas` is an object, it specifies key-value pairs of server tags and the number of replicas to assign to those servers: `{"tag1": 2, "tag2": 4, "tag3": 2, ...}`. For more information about server tags, read [Administration tools](http://rethinkdb.com/docs/administration-tools/).\n* `primary_replica_tag`: the primary server specified by its server tag. Required if `replicas` is an object; the tag must be in the object. This must *not* be specified if `replicas` is an integer.\n* `dry_run`: if `True` the generated configuration will not be applied to the table, only returned.\n\nThe return value of `reconfigure` is an object with three fields:\n\n* `reconfigured`: the number of tables reconfigured. This will be `0` if `dry_run` is `True`.\n* `config_changes`: a list of new and old table configuration values. Each element of the list will be an object with two fields:\n * `old_val`: The table\'s [config](http://rethinkdb.com/api/python/config) value before `reconfigure` was executed. \n * `new_val`: The table\'s `config` value after `reconfigure` was executed.\n* `status_changes`: a list of new and old table status values. Each element of the list will be an object with two fields:\n * `old_val`: The table\'s [status](http://rethinkdb.com/api/python/status) value before `reconfigure` was executed. \n * `new_val`: The table\'s `status` value after `reconfigure` was executed.\n\nFor `config_changes` and `status_changes`, see the [config](http://rethinkdb.com/api/python/config) and [status](http://rethinkdb.com/api/python/status) commands for an explanation of the objects returned in the `old_val` and `new_val` fields.\n\nA table will lose availability temporarily after `reconfigure` is called; use the [table_status](http://rethinkdb.com/api/python/table_status) command to determine when the table is available again.\n\n**Note:** Whenever you call `reconfigure`, the write durability will be set to `hard` and the write acknowledgments will be set to `majority`; these can be changed by using the `config` command on the table.\n\nIf `reconfigure` is called on a database, all the tables in the database will have their configurations affected. The return value will be an array of the objects described above, one per table.\n\nRead [Sharding and replication](http://rethinkdb.com/docs/sharding-and-replication/) for a complete discussion of the subject, including advanced topics.\n\n*Example* Reconfigure a table.\n\n r.table(\'superheroes\').reconfigure(shards=2, replicas=1).run(conn)\n \n {\n "reconfigured": 1,\n "config_changes": [\n {\n "new_val": {\n "id": "31c92680-f70c-4a4b-a49e-b238eb12c023",\n "name": "superheroes",\n "db": "superstuff",\n "primary_key": "id",\n "shards": [\n {"primary_replica": "jeeves", "replicas": ["jeeves"]},\n {"primary_replica": "alfred", "replicas": ["alfred"]}\n ],\n "write_acks": "majority",\n "durability": "hard"\n },\n "old_val": {\n "id": "31c92680-f70c-4a4b-a49e-b238eb12c023",\n "name": "superheroes",\n "db": "superstuff",\n "primary_key": "id",\n "shards": [\n {"primary_replica": "alfred", "replicas": ["alfred"]}\n ],\n "write_acks": "majority",\n "durability": "hard"\n }\n }\n ],\n "status_changes": [\n {\n "new_val": (status object),\n "old_val": (status object)\n }\n ]\n }\n\n*Example* Reconfigure a table, specifying replicas by server tags.\n\n r.table(\'superheroes\').reconfigure(shards=2, replicas={\'wooster\': 1, \'wayne\': 1}, primary_replica_tag=\'wooster\').run(conn)\n \n {\n "reconfigured": 1,\n "config_changes": [\n {\n "new_val": {\n "id": "31c92680-f70c-4a4b-a49e-b238eb12c023",\n "name": "superheroes",\n "db": "superstuff",\n "primary_key": "id",\n "shards": [\n {"primary_replica": "jeeves", "replicas": ["jeeves", "alfred"]},\n {"primary_replica": "jeeves", "replicas": ["jeeves", "alfred"]}\n ],\n "write_acks": "majority",\n "durability": "hard"\n },\n "old_val": {\n "id": "31c92680-f70c-4a4b-a49e-b238eb12c023",\n "name": "superheroes",\n "db": "superstuff",\n "primary_key": "id",\n "shards": [\n {"primary_replica": "alfred", "replicas": ["alfred"]}\n ],\n "write_acks": "majority",\n "durability": "hard"\n }\n }\n ],\n "status_changes": [\n {\n "new_val": (status object),\n "old_val": (status object)\n }\n ]\n }\n'),
+ (rethinkdb.ast.Table.status, b'table.status() -> selection&lt;object&gt;\n\nReturn the status of a table.\n\nThe return value is an object providing information about the table\'s shards, replicas and replica readiness states. For a more complete discussion of the object fields, read about the `table_status` table in [System tables](http://rethinkdb.com/docs/system-tables/).\n\n* `db`: database name.\n* `name`: table name.\n* `id`: table UUID.\n* `shards`: an array of objects, one for each shard, with the following keys per object:\n * `primary_replica`: name of the shard\'s primary server.\n * `replicas`: an array of objects showing the status of each replica, with the following keys:\n * `server`: name of the replica server.\n * `state`: one of `ready`, `disconnected`, `backfilling_data`, `offloading_data`, `erasing_data`, `looking_for_primary_replica` or `transitioning`.\n* `status`: an object with the following boolean keys:\n * `all_replicas_ready`: `True` if all backfills have finished.\n * `ready_for_outdated_reads`: `True` if the table is ready for read queries with the `use_outdated` flag set to `True`.\n * `ready_for_reads`: `True` if the table is ready for read queries with current data (with the `use_outdated` flag set to `False` or unspecified).\n * `ready_for_writes`: `True` if the table is ready for write queries.\n\n*Example* Get a table\'s status.\n\n r.table(\'superheroes\').status().run(conn)\n \n {\n "db": "database",\n "id": "5cb35225-81b2-4cec-9eef-bfad15481265",\n "name": "superheroes",\n "shards": [\n {\n "primary_replica": "jeeves",\n "replicas": [\n {\n "server": "jeeves",\n "state": "ready"\n }\n ]\n },\n {\n "primary_replica": "jeeves",\n "replicas": [\n {\n "server": "jeeves",\n "state": "ready"\n }\n ]\n }\n ],\n "status": {\n "all_replicas_ready": True,\n "ready_for_outdated_reads": True,\n "ready_for_reads": True,\n "ready_for_writes": True\n }\n }\n'),
+ (rethinkdb.ast.Table.wait, b'table.wait([wait_for=\'ready_for_writes\', timeout=<sec>]) -> object\ndatabase.wait([wait_for=\'ready_for_writes\', timeout=<sec>]) -> object\nr.wait([wait_for=\'ready_for_writes\', timeout=<sec>]) -> object\n\nWait for a table or all the tables in a database to be ready. A table may be temporarily unavailable after creation, rebalancing or reconfiguring. The `wait` command blocks until the given table (or database) is fully up to date.\n\nThe `wait` command takes two optional arguments:\n\n* `wait_for`: a string indicating a table [status](http://rethinkdb.com/api/python/status) to wait on before returning, one of `ready_for_outdated_reads`, `ready_for_reads`, `ready_for_writes`, or `all_replicas_ready`. The default is `ready_for_writes`. \n* `timeout`: a number indicating maximum time to wait for in seconds before returning. The default is no timeout.\n\nThe return value is an object consisting of two key/value pairs:\n\n* `ready`: an integer indicating the number of tables waited for. It will always be `1` when `wait` is called on a table, and the total number of tables when called on a database.\n* `status_changes`: a list with one entry for each of the tables. Each member of the list will be an object with two fields:\n * `old_val`: The table\'s [status](http://rethinkdb.com/api/python/status) value before `wait` was executed. \n * `new_val`: The table\'s `status` value after `wait` finished.\n\nSee [status](http://rethinkdb.com/api/python/status) and [System tables](http://rethinkdb.com/docs/system-tables/) for a description of the fields within `status_changes`.\n\nIf `wait` is called with no table or database specified (the `r.wait()` form), it will wait on all the tables in the default database (set with the [connect](http://rethinkdb.com/api/python/connect/) command\'s `db` parameter, which defaults to `test`).\n\n*Example* Wait on a table to be ready.\n\n r.table(\'superheroes\').wait().run(conn)\n \n {\n "ready": 1,\n "status_changes": [\n \t{\n \t "old_val": {\n \t\t"db": "database",\n \t\t"id": "5cb35225-81b2-4cec-9eef-bfad15481265",\n \t\t"name": "superheroes",\n \t\t"shards": [\n \t\t {\n \t\t\t"primary_replica": None,\n \t\t\t"replicas": [\n \t\t\t {\n \t\t\t\t"server": "jeeves",\n \t\t\t\t"state": "ready"\n \t\t\t }\n \t\t\t]\n \t\t },\n \t\t {\n \t\t\t"primary_replica": None,\n \t\t\t"replicas": [\n \t\t\t {\n \t\t\t\t"server": "jeeves",\n \t\t\t\t"state": "ready"\n \t\t\t }\n \t\t\t]\n \t\t }\n \t\t],\n \t\t"status": {\n \t\t "all_replicas_ready": True,\n \t\t "ready_for_outdated_reads": True,\n \t\t "ready_for_reads": True,\n \t\t "ready_for_writes": True\n \t\t}\n \t },\n \t "new_val": {\n \t\t"db": "database",\n \t\t"id": "5cb35225-81b2-4cec-9eef-bfad15481265",\n \t\t"name": "superheroes",\n \t\t"shards": [\n \t\t {\n \t\t\t"primary_replica": None,\n \t\t\t"replicas": [\n \t\t\t {\n \t\t\t\t"server": "jeeves",\n \t\t\t\t"state": "ready"\n \t\t\t }\n \t\t\t]\n \t\t },\n \t\t {\n \t\t\t"primary_replica": None,\n \t\t\t"replicas": [\n \t\t\t {\n \t\t\t\t"server": "jeeves",\n \t\t\t\t"state": "ready"\n \t\t\t }\n \t\t\t]\n \t\t }\n \t\t],\n \t\t"status": {\n \t\t "all_replicas_ready": True,\n \t\t "ready_for_outdated_reads": True,\n \t\t "ready_for_reads": True,\n \t\t "ready_for_writes": True\n \t\t}\n \t }\n \t}\n ]\n }\n'),
+ (rethinkdb.ast.RqlQuery.avg, b"sequence.avg([field_or_function]) -> number\n\nAverages all the elements of a sequence. If called with a field name,\naverages all the values of that field in the sequence, skipping\nelements of the sequence that lack that field. If called with a\nfunction, calls that function on every element of the sequence and\naverages the results, skipping elements of the sequence where that\nfunction returns `None` or a non-existence error.\n\nProduces a non-existence error when called on an empty sequence. You\ncan handle this case with `default`.\n\n*Example* What's the average of 3, 5, and 7?\n\n r.expr([3, 5, 7]).avg().run(conn)\n\n*Example* What's the average number of points scored in a game?\n\n r.table('games').avg('points').run(conn)\n\n*Example* What's the average number of points scored in a game,\ncounting bonus points?\n\n r.table('games').avg(lambda game:\n game['points'] + game['bonus_points']\n ).run(conn)\n\n*Example* What's the average number of points scored in a game?\n(But return `None` instead of raising an error if there are no games where\npoints have been scored.)\n\n r.table('games').avg('points').default(None).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.contains, b"sequence.contains(value|predicate[, value|predicate, ...]) -> bool\n\nWhen called with values, returns `True` if a sequence contains all the\nspecified values. When called with predicate functions, returns `True`\nif for each predicate there exists at least one element of the stream\nwhere that predicate returns `True`.\n\nValues and predicates may be mixed freely in the argument list.\n\n*Example* Has Iron Man ever fought Superman?\n\n r.table('marvel').get('ironman')['opponents'].contains('superman').run(conn)\n\n*Example* Has Iron Man ever defeated Superman in battle?\n\n r.table('marvel').get('ironman')['battles'].contains(lambda battle:\n (battle['winner'] == 'ironman') & (battle['loser'] == 'superman')\n ).run(conn)\n\n*Example* Use `contains` with a predicate function to simulate an `or`. Return the Marvel superheroes who live in Detroit, Chicago or Hoboken.\n\n r.table('marvel').filter(\n lambda hero: r.expr(['Detroit', 'Chicago', 'Hoboken']).contains(hero['city'])\n ).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.count, b"sequence.count([value_or_predicate]) -> number\nbinary.count() -> number\n\nCounts the number of elements in a sequence. If called with a value,\ncounts the number of times that value occurs in the sequence. If\ncalled with a predicate function, counts the number of elements in the\nsequence where that function returns `True`.\n\nIf `count` is called on a [binary](http://rethinkdb.com/api/python/binary) object, it will return the size of the object in bytes.\n\n*Example* Count the number of users.\n\n r.table('users').count().run(conn)\n\n*Example* Count the number of 18 year old users.\n\n r.table('users')['age'].count(18).run(conn)\n\n*Example* Count the number of users over 18.\n\n r.table('users')['age'].count(lambda age: age > 18).run(conn)\n\n r.table('users').count(lambda user: user['age'] > 18).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.distinct, b"sequence.distinct() -> array\ntable.distinct([index=<indexname>]) -> stream\n\nRemoves duplicate elements from a sequence.\n\nThe `distinct` command can be called on any sequence or table with an index.\n\n{% infobox %}\nWhile `distinct` can be called on a table without an index, the only effect will be to convert the table into a stream; the content of the stream will not be affected.\n{% endinfobox %}\n\n*Example* Which unique villains have been vanquished by Marvel heroes?\n\n r.table('marvel').concat_map(\n lambda hero: hero['villain_list']).distinct().run(conn)\n\n*Example* Topics in a table of messages have a secondary index on them, and more than one message can have the same topic. What are the unique topics in the table?\n\n r.table('messages').distinct(index='topics').run(conn)\n\nThe above structure is functionally identical to:\n\n r.table('messages')['topics'].distinct().run(conn)\n\nHowever, the first form (passing the index as an argument to `distinct`) is faster, and won't run into array limit issues since it's returning a stream.\n"),
+ (rethinkdb.ast.RqlQuery.group, b'sequence.group(field_or_function..., [index=\'index_name\', multi=False]) -> grouped_stream\n\nTakes a stream and partitions it into multiple groups based on the\nfields or functions provided.\n\nWith the `multi` flag single documents can be assigned to multiple groups, similar to the behavior of [multi-indexes](http://rethinkdb.com/docs/secondary-indexes/python). When `multi` is `True` and the grouping value is an array, documents will be placed in each group that corresponds to the elements of the array. If the array is empty the row will be ignored.\n\n*Example* Grouping games by player.\n\nSuppose that the table `games` has the following data:\n\n [\n {"id": 2, "player": "Bob", "points": 15, "type": "ranked"},\n {"id": 5, "player": "Alice", "points": 7, "type": "free"},\n {"id": 11, "player": "Bob", "points": 10, "type": "free"},\n {"id": 12, "player": "Alice", "points": 2, "type": "free"}\n ]\n\nGrouping games by player can be done with:\n\n > r.table(\'games\').group(\'player\').run(conn)\n \n {\n "Alice": [\n {"id": 5, "player": "Alice", "points": 7, "type": "free"},\n {"id": 12, "player": "Alice", "points": 2, "type": "free"}\n ],\n "Bob": [\n {"id": 2, "player": "Bob", "points": 15, "type": "ranked"},\n {"id": 11, "player": "Bob", "points": 10, "type": "free"}\n ]\n }\n\nCommands chained after `group` will be called on each of these grouped\nsub-streams, producing grouped data.\n\n*Example* What is each player\'s best game?\n\n > r.table(\'games\').group(\'player\').max(\'points\').run(conn)\n \n {\n "Alice": {"id": 5, "player": "Alice", "points": 7, "type": "free"},\n "Bob": {"id": 2, "player": "Bob", "points": 15, "type": "ranked"}\n }\n\nCommands chained onto grouped data will operate on each grouped datum,\nproducing more grouped data.\n\n*Example* What is the maximum number of points scored by each player?\n\n > r.table(\'games\').group(\'player\').max(\'points\')[\'points\'].run(conn)\n \n {\n "Alice": 7,\n "Bob": 15\n }\n\nYou can also group by more than one field.\n\n*Example* What is the maximum number of points scored by each\nplayer for each game type?\n\n > r.table(\'games\').group(\'player\', \'type\').max(\'points\')[\'points\'].run(conn)\n \n {\n ("Alice", "free"): 7,\n ("Bob", "free"): 10,\n ("Bob", "ranked"): 15\n }\n\nYou can also group by a function.\n\n*Example* What is the maximum number of points scored by each\nplayer for each game type?\n\n > r.table(\'games\')\n .group(lambda game:\n game.pluck(\'player\', \'type\')\n ).max(\'points\')[\'points\'].run(conn)\n \n {\n frozenset([(\'player\', \'Alice\'), (\'type\', \'free\')]): 7,\n frozenset([(\'player\', \'Bob\'), (\'type\', \'free\')]): 10,\n frozenset([(\'player\', \'Bob\'), (\'type\', \'ranked\')]): 15,\n }\n\nUsing a function, you can also group by date on a ReQL [date field](http://rethinkdb.com/docs/dates-and-times/javascript/).\n\n*Example* How many matches have been played this year by month?\n\n > r.table(\'matches\').group(\n lambda match: [match[\'date\'].year(), match[\'date\'].month()]\n ).count().run(conn)\n \n {\n (2014, 2): 2,\n (2014, 3): 2,\n (2014, 4): 1,\n (2014, 5): 3\n }\n\nYou can also group on an index (primary key or secondary).\n\n*Example* What is the maximum number of points scored by game type?\n\n > r.table(\'games\').group(index=\'type\').max(\'points\')[\'points\'].run(conn)\n \n {\n "free": 10,\n "ranked": 15\n }\n\nSuppose that the table `games2` has the following data:\n\n [\n { \'id\': 1, \'matches\': {\'a\': [1, 2, 3], \'b\': [4, 5, 6]} },\n { \'id\': 2, \'matches\': {\'b\': [100], \'c\': [7, 8, 9]} },\n { \'id\': 3, \'matches\': {\'a\': [10, 20], \'c\': [70, 80]} }\n ]\n\nUsing the `multi` option we can group data by match A, B or C.\n\n > r.table(\'games2\').group(r.row[\'matches\'].keys(), multi=True).run(conn)\n \n [\n {\n \'group\': \'a\',\n \'reduction\': [ <id 1>, <id 3> ]\n },\n {\n \'group\': \'b\',\n \'reduction\': [ <id 1>, <id 2> ]\n },\n {\n \'group\': \'c\',\n \'reduction\': [ <id 2>, <id 3> ]\n }\n ]\n\n(The full result set is abbreviated in the figure; `<id 1>, <id 2>` and `<id 3>` would be the entire documents matching those keys.)\n\n*Example* Use [map](http://rethinkdb.com/api/python/map) and [sum](http://rethinkdb.com/api/python/sum) to get the total points scored for each match.\n\n r.table(\'games2\').group(r.row[\'matches\'].keys(), multi=True).ungroup().map(\n lambda doc: { \'match\': doc[\'group\'], \'total\': doc[\'reduction\'].sum(\n lambda set: set[\'matches\'][doc[\'group\']].sum()\n )}).run(conn)\n \n [\n { \'match\': \'a\', \'total\': 36 },\n { \'match\': \'b\', \'total\': 115 },\n { \'match\': \'c\', \'total\': 174 }\n ]\n\nThe inner `sum` adds the scores by match within each document; the outer `sum` adds those results together for a total across all the documents.\n\nIf you want to operate on all the groups rather than operating on each\ngroup (e.g. if you want to order the groups by their reduction), you\ncan use [ungroup](http://rethinkdb.com/api/python/ungroup/) to turn a grouped stream or\ngrouped data into an array of objects representing the groups.\n\n*Example* Ungrouping grouped data.\n\n > r.table(\'games\').group(\'player\').max(\'points\')[\'points\'].ungroup().run(conn)\n \n [\n {\n "group": "Alice",\n "reduction": 7\n },\n {\n "group": "Bob",\n "reduction": 15\n }\n ]\n\nUngrouping is useful e.g. for ordering grouped data, or for inserting\ngrouped data into a table.\n\n*Example* What is the maximum number of points scored by each\nplayer, with the highest scorers first?\n\n > r.table(\'games\').group(\'player\').max(\'points\')[\'points\'].ungroup().order_by(\n r.desc(\'reduction\')).run(conn)\n \n [\n {\n "group": "Bob",\n "reduction": 15\n },\n {\n "group": "Alice",\n "reduction": 7\n }\n ]\n\nWhen grouped data are returned to the client, they are transformed\ninto a client-specific native type. (Something similar is done with\n[times](http://rethinkdb.com/docs/dates-and-times/).) In Python, grouped data are\ntransformed into a `dictionary`. If the group value is an `array`, the\nkey is converted to a `tuple`. If the group value is a `dictionary`,\nit will be converted to a `frozenset`.\n\nIf you instead want to receive the raw\npseudotype from the server (e.g. if you\'re planning to serialize the\nresult as JSON), you can specify `group_format: \'raw\'` as an optional\nargument to `run`:\n\n*Example* Get back the raw `GROUPED_DATA` pseudotype.\n\n > r.table(\'games\').group(\'player\').avg(\'points\').run(conn, group_format=\'raw\')\n \n {\n "$reql_type$": "GROUPED_DATA",\n "data": [\n ["Alice", 4.5],\n ["Bob", 12.5]\n ]\n }\n\nNot passing the `group_format` flag would return:\n\n {\n "Alice": 4.5,\n "Bob": 12.5\n }\n\nYou might also want to use the [ungroup](http://rethinkdb.com/api/python/ungroup/)\ncommand (see above), which will turn the grouped data into an array of\nobjects on the server.\n\nIf you run a query that returns a grouped stream, it will be\nautomatically converted to grouped data before being sent back to you\n(there is currently no efficient way to stream groups from RethinkDB).\nThis grouped data is subject to the array size limit (see [run](http://rethinkdb.com/api/python/run)).\n\nIn general, operations on grouped streams will be efficiently\ndistributed, and operations on grouped data won\'t be. You can figure\nout what you\'re working with by putting `type_of` on the end of your\nquery. Below are efficient and inefficient examples.\n\n*Example* Efficient operation.\n\n # r.table(\'games\').group(\'player\').type_of().run(conn)\n # Returns "GROUPED_STREAM"\n r.table(\'games\').group(\'player\').min(\'points\').run(conn) # EFFICIENT\n\n*Example* Inefficient operation.\n\n # r.table(\'games\').group(\'player\').order_by(\'score\').type_of().run(conn)\n # Returns "GROUPED_DATA"\n r.table(\'games\').group(\'player\').order_by(\'score\').nth(0).run(conn) # INEFFICIENT\n\nWhat does it mean to be inefficient here? When operating on grouped\ndata rather than a grouped stream, *all* of the data has to be\navailable on the node processing the query. This means that the\noperation will only use one server\'s resources, and will require\nmemory proportional to the size of the grouped data it\'s operating\non. (In the case of the `order_by` in the inefficient example, that\nmeans memory proportional **to the size of the table**.) The array\nlimit is also enforced for grouped data, so the `order_by` example\nwould fail for tables with more than 100,000 rows unless you used the `array_limit` option with `run`.\n\n*Example* What is the maximum number of points scored by each\nplayer in free games?\n\n > r.table(\'games\').filter(lambda game:\n game[\'type\'] = \'free\'\n ).group(\'player\').max(\'points\')[\'points\'].run(conn)\n \n {\n "Alice": 7,\n "Bob": 10\n }\n\n*Example* What is each player\'s highest even and odd score?\n\n > r.table(\'games\')\n .group(\'name\', lambda game:\n game[\'points\'] % 2\n ).max(\'points\')[\'points\'].run(conn)\n \n {\n ("Alice", 1): 7,\n ("Bob", 0): 10,\n ("Bob", 1): 15\n }\n'),
+ (rethinkdb.ast.RqlQuery.max, b"sequence.max(field_or_function) -> element\nsequence.max(index='index') -> element\n\nFinds the maximum element of a sequence. The `max` command can be called with:\n\n* a **field name**, to return the element of the sequence with the largest value in that field;\n* an **index** (the primary key or a secondary index), to return the element of the sequence with the largest value in that index;\n* a **function**, to apply the function to every element within the sequence and return the element which returns the largest value from the function, ignoring any elements where the function produces a non-existence error.\n\nFor more information on RethinkDB's sorting order, read the section in [ReQL data types](http://rethinkdb.com/docs/data-types/#sorting-order).\n\nCalling `max` on an empty sequence will throw a non-existence error; this can be handled using the [default](http://rethinkdb.com/api/python/default/) command.\n\n*Example* Return the maximum value in the list `[3, 5, 7]`.\n\n r.expr([3, 5, 7]).max().run(conn)\n\n*Example* Return the user who has scored the most points.\n\n r.table('users').max('points').run(conn)\n\n*Example* The same as above, but using a secondary index on the `points` field.\n\n r.table('users').max(index='points').run(conn)\n\n*Example* Return the user who has scored the most points, adding in bonus points from a separate field using a function.\n\n r.table('users').max(lambda user:\n user['points'] + user['bonus_points']\n ).run(conn)\n\n*Example* Return the highest number of points any user has ever scored. This returns the value of that `points` field, not a document.\n\n r.table('users').max('points')['points'].run(conn)\n\n*Example* Return the user who has scored the most points, but add a default `None` return value to prevent an error if no user has ever scored points.\n\n r.table('users').max('points').default(None).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.min, b"sequence.min(field_or_function) -> element\nsequence.min(index='index') -> element\n\nFinds the minimum element of a sequence. The `min` command can be called with:\n\n* a **field name**, to return the element of the sequence with the smallest value in that field;\n* an **index** (the primary key or a secondary index), to return the element of the sequence with the smallest value in that index;\n* a **function**, to apply the function to every element within the sequence and return the element which returns the smallest value from the function, ignoring any elements where the function produces a non-existence error.\n\nFor more information on RethinkDB's sorting order, read the section in [ReQL data types](http://rethinkdb.com/docs/data-types/#sorting-order).\n\nCalling `min` on an empty sequence will throw a non-existence error; this can be handled using the [default](http://rethinkdb.com/api/python/default/) command.\n\n*Example* Return the minimum value in the list `[3, 5, 7]`.\n\n r.expr([3, 5, 7]).min().run(conn)\n\n*Example* Return the user who has scored the fewest points.\n\n r.table('users').min('points').run(conn)\n\n*Example* The same as above, but using a secondary index on the `points` field.\n\n r.table('users').min(index='points').run(conn)\n\n*Example* Return the user who has scored the fewest points, adding in bonus points from a separate field using a function.\n\n r.table('users').min(lambda user:\n user['points'] + user['bonus_points']\n ).run(conn)\n\n*Example* Return the smallest number of points any user has ever scored. This returns the value of that `points` field, not a document.\n\n r.table('users').min('points')['points'].run(conn)\n\n*Example* Return the user who has scored the fewest points, but add a default `None` return value to prevent an error if no user has ever scored points.\n\n r.table('users').min('points').default(None).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.reduce, b'sequence.reduce(reduction_function) -> value\n\nProduce a single value from a sequence through repeated application of a reduction\nfunction. \nThe reduction function can be called on:\n\n- two elements of the sequence\n- one element of the sequence and one result of a previous reduction\n- two results of previous reductions\n\nThe reduction function can be called on the results of two previous reductions because the\n`reduce` command is distributed and parallelized across shards and CPU cores. A common\nmistaken when using the `reduce` command is to suppose that the reduction is executed\nfrom left to right. Read the [map-reduce in RethinkDB](http://rethinkdb.com/docs/map-reduce/) article to\nsee an example.\n\nIf the sequence is empty, the server will produce a `RqlRuntimeError` that can be\ncaught with `default`. \nIf the sequence has only one element, the first element will be returned.\n\n*Example* Return the number of documents in the table `posts`.\n\n r.table("posts").map(lambda doc: 1)\n .reduce(lambda left, right: left+right)\n .default(0).run(conn)\n\nA shorter way to execute this query is to use [count](http://rethinkdb.com/api/python/count).\n\n*Example* Suppose that each `post` has a field `comments` that is an array of\ncomments. \nReturn the number of comments for all posts.\n\n r.table("posts").map(lambda doc:\n doc["comments"].count()\n ).reduce(lambda left, right:\n left+right\n ).default(0).run(conn)\n\n*Example* Suppose that each `post` has a field `comments` that is an array of\ncomments. \nReturn the maximum number comments per post.\n\n r.table("posts").map(lambda doc:\n doc["comments"].count()\n ).reduce(lambda left, right:\n r.branch(\n left > right,\n left,\n right\n )\n ).default(0).run(conn)\n\nA shorter way to execute this query is to use [max](http://rethinkdb.com/api/python/max).\n'),
+ (rethinkdb.ast.RqlQuery.sum, b"sequence.sum([field_or_function]) -> number\n\nSums all the elements of a sequence. If called with a field name,\nsums all the values of that field in the sequence, skipping elements\nof the sequence that lack that field. If called with a function,\ncalls that function on every element of the sequence and sums the\nresults, skipping elements of the sequence where that function returns\n`None` or a non-existence error.\n\nReturns `0` when called on an empty sequence.\n\n*Example* What's 3 + 5 + 7?\n\n r.expr([3, 5, 7]).sum().run(conn)\n\n*Example* How many points have been scored across all games?\n\n r.table('games').sum('points').run(conn)\n\n*Example* How many points have been scored across all games,\ncounting bonus points?\n\n r.table('games').sum(lambda game:\n game['points'] + game['bonus_points']\n ).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.ungroup, b'grouped_stream.ungroup() -> array\ngrouped_data.ungroup() -> array\n\nTakes a grouped stream or grouped data and turns it into an array of\nobjects representing the groups. Any commands chained after `ungroup`\nwill operate on this array, rather than operating on each group\nindividually. This is useful if you want to e.g. order the groups by\nthe value of their reduction.\n\nThe format of the array returned by `ungroup` is the same as the\ndefault native format of grouped data in the JavaScript driver and\ndata explorer.\n\n*Example* What is the maximum number of points scored by each\nplayer, with the highest scorers first?\n\nSuppose that the table `games` has the following data:\n\n [\n {"id": 2, "player": "Bob", "points": 15, "type": "ranked"},\n {"id": 5, "player": "Alice", "points": 7, "type": "free"},\n {"id": 11, "player": "Bob", "points": 10, "type": "free"},\n {"id": 12, "player": "Alice", "points": 2, "type": "free"}\n ]\n\nWe can use this query:\n\n r.table(\'games\')\n .group(\'player\').max(\'points\')[\'points\']\n .ungroup().order_by(r.desc(\'reduction\')).run(conn)\n\nResult: \n\n [\n {\n "group": "Bob",\n "reduction": 15\n },\n {\n "group": "Alice",\n "reduction": 7\n }\n ]\n\n*Example* Select one random player and all their games.\n\n r.table(\'games\').group(\'player\').ungroup().sample(1).run(conn)\n\nResult:\n\n [\n {\n "group": "Bob",\n "reduction": [\n {"id": 2, "player": "Bob", "points": 15, "type": "ranked"},\n {"id": 11, "player": "Bob", "points": 10, "type": "free"}\n ]\n }\n ]\n\nNote that if you didn\'t call `ungroup`, you would instead select one\nrandom game from each player:\n\n r.table(\'games\').group(\'player\').sample(1).run(conn)\n\nResult:\n\n {\n "Alice": [\n {"id": 5, "player": "Alice", "points": 7, "type": "free"}\n ],\n "Bob": [\n {"id": 11, "player": "Bob", "points": 10, "type": "free"}\n ]\n }\n\n*Example* Types!\n\n r.table(\'games\').group(\'player\').type_of().run(conn) # Returns "GROUPED_STREAM"\n r.table(\'games\').group(\'player\').ungroup().type_of().run(conn) # Returns "ARRAY"\n r.table(\'games\').group(\'player\').avg(\'points\').run(conn) # Returns "GROUPED_DATA"\n r.table(\'games\').group(\'player\').avg(\'points\').ungroup().run(conn) #Returns "ARRAY"\n'),
+ (rethinkdb.args, b"r.args(array) -> special\n\n`r.args` is a special term that's used to splice an array of arguments\ninto another term. This is useful when you want to call a variadic\nterm such as `get_all` with a set of arguments produced at runtime.\n\nThis is analogous to unpacking argument lists in Python.\n\n*Example* Get Alice and Bob from the table `people`.\n\n r.table('people').get_all('Alice', 'Bob').run(conn)\n # or\n r.table('people').get_all(r.args(['Alice', 'Bob'])).run(conn)\n\n*Example* Get all of Alice's children from the table `people`.\n\n # r.table('people').get('Alice') returns {'id': 'Alice', 'children': ['Bob', 'Carol']}\n r.table('people').get_all(r.args(r.table('people').get('Alice')['children'])).run(conn)\n"),
+ (rethinkdb.binary, b'r.binary(data) -> binary\n\nEncapsulate binary data within a query.\n\nThe type of data `binary` accepts depends on the client language. In Python, it expects a parameter of `bytes` type. Using a `bytes` object within a query implies the use of `binary` and the ReQL driver will automatically perform the coercion (in Python 3 only).\n\nBinary objects returned to the client in JavaScript will also be of the `bytes` type. This can be changed with the `binary_format` option provided to [run](http://rethinkdb.com/api/python/run) to return "raw" objects.\n\nOnly a limited subset of ReQL commands may be chained after `binary`:\n\n* [coerce_to](http://rethinkdb.com/api/python/coerce_to/) can coerce `binary` objects to `string` types\n* [count](http://rethinkdb.com/api/python/count/) will return the number of bytes in the object\n* [slice](http://rethinkdb.com/api/python/slice/) will treat bytes like array indexes (i.e., `slice(10,20)` will return bytes 10&ndash;19)\n* [type_of](http://rethinkdb.com/api/python/type_of) returns `PTYPE<BINARY>`\n* [info](http://rethinkdb.com/api/python/info) will return information on a binary object.\n\n*Example* Save an avatar image to a existing user record.\n\n f = open(\'./default_avatar.png\', \'rb\')\n avatar_image = f.read()\n f.close()\n r.table(\'users\').get(100).update({\'avatar\': r.binary(avatar_image)}).run(conn)\n\n*Example* Get the size of an existing avatar image.\n\n r.table(\'users\').get(100)[\'avatar\'].count().run(conn)\n \n 14156\n\nRead more details about RethinkDB\'s binary object support: [Storing binary objects](http://rethinkdb.com/docs/storing-binary/).\n'),
+ (rethinkdb.branch, b'r.branch(test, true_branch, false_branch) -> any\n\nIf the `test` expression returns `False` or `None`, the `false_branch` will be evaluated.\nOtherwise, the `true_branch` will be evaluated.\n \nThe `branch` command is effectively an `if` renamed due to language constraints.\n\n*Example* Return heroes and superheroes.\n\n r.table(\'marvel\').map(\n r.branch(\n r.row[\'victories\'] > 100,\n r.row[\'name\'] + \' is a superhero\',\n r.row[\'name\'] + \' is a hero\'\n )\n ).run(conn)\n\nIf the documents in the table `marvel` are:\n\n [{\n "name": "Iron Man",\n "victories": 214\n },\n {\n "name": "Jubilee",\n "victories": 9\n }]\n\nThe results will be:\n\n [\n "Iron Man is a superhero",\n "Jubilee is a hero"\n ]\n'),
+ (rethinkdb.ast.RqlQuery.coerce_to, b"sequence.coerce_to('array') -> array\nvalue.coerce_to('string') -> string\nstring.coerce_to('number') -> number\narray.coerce_to('object') -> object\nobject.coerce_to('array') -> array\nbinary.coerce_to('string') -> string\nstring.coerce_to('binary') -> binary\n\nConvert a value of one type into another.\n\n* a sequence, selection or object can be coerced to an array\n* an array of key-value pairs can be coerced to an object\n* a string can be coerced to a number\n* any datum (single value) can be coerced to a string\n* a binary object can be coerced to a string and vice-versa\n\n*Example* Coerce a stream to an array to store its output in a field. (A stream cannot be stored in a field directly.)\n\n r.table('posts').map(lambda post: post.merge(\n { 'comments': r.table('comments').get_all(post['id'], index='post_id').coerce_to('array') }\n )).run(conn)\n\n*Example* Coerce an array of pairs into an object.\n\n r.expr([['name', 'Ironman'], ['victories', 2000]]).coerce_to('object').run(conn)\n\n__Note:__ To coerce a list of key-value pairs like `['name', 'Ironman', 'victories', 2000]` to an object, use the [object](http://rethinkdb.com/api/python/object) command.\n\n*Example* Coerce a number to a string.\n\n r.expr(1).coerce_to('string').run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.default, b'value.default(default_value) -> any\nsequence.default(default_value) -> any\n\nHandle non-existence errors. Tries to evaluate and return its first argument. If an\nerror related to the absence of a value is thrown in the process, or if its first\nargument returns `None`, returns its second argument. (Alternatively, the second argument\nmay be a function which will be called with either the text of the non-existence error\nor `None`.)\n\n*Example* Suppose we want to retrieve the titles and authors of the table `posts`.\nIn the case where the author field is missing or `None`, we want to retrieve the string\n`Anonymous`.\n\n r.table("posts").map(lambda post:\n {\n "title": post["title"],\n "author": post["author"].default("Anonymous")\n }\n ).run(conn)\n\nWe can rewrite the previous query with `r.branch` too.\n\n r.table("posts").map(lambda post:\n r.branch(\n post.has_fields("author"),\n {\n "title": post["title"],\n "author": post["author"]\n },\n {\n "title": post["title"],\n "author": "Anonymous" \n }\n )\n ).run(conn)\n\n*Example* The `default` command can be useful to filter documents too. Suppose\nwe want to retrieve all our users who are not grown-ups or whose age is unknown\n(i.e the field `age` is missing or equals `None`). We can do it with this query:\n\n r.table("users").filter(lambda user:\n (user["age"] < 18).default(True)\n ).run(conn)\n\nOne more way to write the previous query is to set the age to be `-1` when the\nfield is missing.\n\n r.table("users").filter(lambda user:\n user["age"].default(-1) < 18\n ).run(conn)\n\nOne last way to do the same query is to use `has_fields`.\n\n r.table("users").filter(lambda user:\n user.has_fields("age").not_() | (user["age"] < 18)\n ).run(conn)\n\nThe body of every `filter` is wrapped in an implicit `.default(False)`. You can overwrite\nthe value `False` by passing an option in filter, so the previous query can also be\nwritten like this.\n\n r.table("users").filter(\n lambda user: (user["age"] < 18).default(True),\n default=True\n ).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.do, b"any.do(function) -> any\nr.do([args]*, function) -> any\nany.do(expr) -> any\nr.do([args]*, expr) -> any\n\nCall an anonymous function using return values from other ReQL commands or queries as arguments.\n\nThe last argument to `do` (or, in some forms, the only argument) is an expression or an anonymous function which receives values from either the previous arguments or from prefixed commands chained before `do`. The `do` command is essentially a single-element [map](http://rethinkdb.com/api/python/map/), letting you map a function over just one document. This allows you to bind a query result to a local variable within the scope of `do`, letting you compute the result just once and reuse it in a complex expression or in a series of ReQL commands.\n\nArguments passed to the `do` function must be basic data types, and cannot be streams or selections. (Read about [ReQL data types](http://rethinkdb.com/docs/data-types/).) While the arguments will all be evaluated before the function is executed, they may be evaluated in any order, so their values should not be dependent on one another. The type of `do`'s result is the type of the value returned from the function or last expression.\n\n*Example* Compute a golfer's net score for a game.\n\n r.table('players').get('86be93eb-a112-48f5-a829-15b2cb49de1d').do(\n lambda player: player['gross_score'] - player['course_handicap']\n ).run(conn)\n\n*Example* Return the name of the best scoring player in a two-player golf match.\n\n r.do(r.table('players').get(id1), r.table('players').get(id2),\n (lambda player1, player2:\n r.branch(player1['gross_score'].lt(player2['gross_score']),\n player1, player2))\n ).run(conn)\n\nNote that `branch`, the ReQL conditional command, must be used instead of `if`. See the `branch` [documentation](http://rethinkdb.com/api/python/branch) for more.\n\n*Example* Take different actions based on the result of a ReQL [insert](http://rethinkdb.com/api/python/insert) command.\n\n new_data = {\n 'id': 100,\n 'name': 'Agatha',\n 'gross_score': 57,\n 'course_handicap': 4\n }\n r.table('players').insert(new_data).do(lambda doc:\n r.branch((doc['inserted'] != 0),\n r.table('log').insert({'time': r.now(), 'response': doc, 'result': 'ok'}),\n r.table('log').insert({'time': r.now(), 'response': doc, 'result': 'error'}))\n ).run(conn)\n"),
+ (rethinkdb.error, b"r.error(message) -> error\n\nThrow a runtime error. If called with no arguments inside the second argument to `default`, re-throw the current error.\n\n*Example* Iron Man can't possibly have lost a battle:\n\n r.table('marvel').get('IronMan').do(\n lambda ironman: r.branch(ironman['victories'] < ironman['battles'],\n r.error('impossible code path'),\n ironman)\n ).run(conn)\n\n"),
+ (rethinkdb.expr, b"r.expr(value) -> value\n\nConstruct a ReQL JSON object from a native object.\n\nIf the native object is of the `bytes` type, then `expr` will return a binary object. See [binary](http://rethinkdb.com/api/python/binary) for more information.\n\n*Example* Objects wrapped with expr can then be manipulated by ReQL API functions.\n\n r.expr({'a':'b'}).merge({'b':[1,2,3]}).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.for_each, b"sequence.for_each(write_query) -> object\n\nLoop over a sequence, evaluating the given write query for each element.\n\n*Example* Now that our heroes have defeated their villains, we can safely remove them from the villain table.\n\n r.table('marvel').for_each(\n lambda hero: r.table('villains').get(hero['villainDefeated']).delete()\n ).run(conn)\n\n"),
+ (rethinkdb.http, b'r.http(url[, options]) -> value\nr.http(url[, options]) -> stream\n\nRetrieve data from the specified URL over HTTP. The return type depends on the `result_format` option, which checks the `Content-Type` of the response by default.\n\n*Example* Perform an HTTP `GET` and store the result in a table.\n\n r.table(\'posts\').insert(r.http(\'http://httpbin.org/get\')).run(conn)\n\nSee [the tutorial](http://rethinkdb.com/docs/external-api-access/) on `r.http` for more examples on how to use this command.\n\n* `timeout`: Number of seconds to wait before timing out and aborting the operation. Default: 30.\n\n* `reattempts`: An integer giving the number of attempts to make in cast of connection errors or potentially-temporary HTTP errors. Default: 5.\n\n* `redirects`: An integer giving the number of redirects and location headers to follow. Default: 1.\n\n* `verify`: Verify the server\'s SSL certificate, specified as a boolean. Default: True.\n\n* `result_format`: The format the result should be returned in. The values can be `\'text\'` (always return as a string), `\'json\'` (parse the result as JSON, raising an error if the parsing fails), `\'jsonp\'` (parse the result as [padded JSON](http://www.json-p.org/)), `\'binary\'` (return a binary object), or `\'auto\'` . The default is `\'auto\'`.\n\n When `result_format` is `\'auto\'`, the response body will be parsed according to the `Content-Type` of the response:\n * `application/json`: parse as `\'json\'`\n * `application/json-p`, `text/json-p`, `text/javascript`: parse as `\'jsonp\'`\n * `audio/*`, `video/*`, `image/*`, `application/octet-stream`: return a binary object\n * Anything else: parse as `\'text\'`\n\n* `method`: HTTP method to use for the request. One of `GET`, `POST`, `PUT`, `PATCH`, `DELETE` or `HEAD`. Default: `GET`.\n\n* `auth`: Authentication information in the form of an object with key/value pairs indicating the authentication type (in the `type` key) and any required information. Types currently supported are `basic` and `digest` for HTTP Basic and HTTP Digest authentication respectively. If `type` is omitted, `basic` is assumed. Example:\n\n\t```py\n\tr.http(\'http://httpbin.org/basic-auth/fred/mxyzptlk\',\n auth={ \'type\': \'basic\', \'user\': \'fred\', \'pass\': \'mxyzptlk\' }).run(conn)\n\t```\n\n* `params`: URL parameters to append to the URL as encoded key/value pairs, specified as an object. For example, `{ \'query\': \'banana\', \'limit\': 2 }` will be appended as `?query=banana&limit=2`. Default: none.\n\n* `header`: Extra header lines to include. The value may be an array of strings or an object. Default: none.\n\n Unless specified otherwise, `r.http` will by default use the headers `Accept-Encoding: deflate=1;gzip=0.5` and `User-Agent: RethinkDB/VERSION`.\n\n* `data`: Data to send to the server on a `POST`, `PUT`, `PATCH`, or `DELETE` request.\n\n For `PUT`, `PATCH` and `DELETE` requests, the value will be serialized to JSON and placed in the request body, and the `Content-Type` will be set to `application/json`.\n\n\tFor `POST` requests, data may be either an object or a string. Objects will be written to the body as form-encoded key/value pairs (values must be numbers, strings, or `None`). Strings will be put directly into the body. If `data` is not a string or an object, an error will be thrown.\n\n If `data` is not specified, no data will be sent.\n\n`r.http` supports depagination, which will request multiple pages in a row and aggregate the results into a stream. The use of this feature is controlled by the optional arguments `page` and `page_limit`. Either none or both of these arguments must be provided.\n\n* `page`: This option may specify either a built-in pagination strategy (as a string), or a function to provide the next URL and/or `params` to request.\n\n At the moment, the only supported built-in is `\'link-next\'`, which is equivalent to `lambda info: info[\'header\'][\'link\'][\'rel="next"\'].default(None)`.\n\n *Example* Perform a GitHub search and collect up to 3 pages of results.\n\n ```py\n r.http("https://api.github.com/search/code?q=addClass+user:mozilla",\n page=\'link-next\', page_limit=3).run(conn)\n ```\n\n As a function, `page` takes one parameter, an object of the format:\n\n ```py\n {\n \'params\': object, # the URL parameters used in the last request\n \'header\': object, # the HTTP headers of the last response as key/value pairs\n \'body\': value # the body of the last response in the format specified by `result_format`\n }\n ```\n\n The `header` field will be a parsed version of the header with fields lowercased, like so:\n\n ```py\n {\n \'content-length\': \'1024\',\n \'content-type\': \'application/json\',\n \'date\': \'Thu, 1 Jan 1970 00:00:00 GMT\',\n \'link\': {\n \'rel="last"\': \'http://example.com/?page=34\',\n \'rel="next"\': \'http://example.com/?page=2\'\n }\n }\n ```\n\n The `page` function may return a string corresponding to the next URL to request, `None` indicating that there is no more to get, or an object of the format:\n\n ```py\n {\n \'url\': string, # the next URL to request, or None for no more pages\n \'params\': object # new URL parameters to use, will be merged with the previous request\'s params\n }\n ```\n\n* `page_limit`: An integer specifying the maximum number of requests to issue using the `page` functionality. This is to prevent overuse of API quotas, and must be specified with `page`.\n * `-1`: no limit\n * `0`: no requests will be made, an empty stream will be returned\n * `n`: `n` requests will be made\n\n# Examples\n\n*Example* Perform multiple requests with different parameters.\n\n r.expr([1, 2, 3]).map(lambda i: r.http(\'http://httpbin.org/get\',\n params={ \'user\': i })).run(conn)\n\n*Example* Perform a `PUT` request for each item in a table.\n\n r.table(\'data\').map(lambda row: r.http(\'http://httpbin.org/put\',\n method=\'PUT\', data=row)).run(conn)\n\n*Example* Perform a `POST` request with accompanying data.\n\nUsing form-encoded data:\n\n r.http(\'http://httpbin.org/post\',\n method=\'POST\',\n data={ \'player\': \'Bob\', \'game\': \'tic tac toe\' }).run(conn)\n\nUsing JSON data:\n\n r.http(\'http://httpbin.org/post\',\n method=\'POST\',\n data=r.expr(value).coerce_to(\'string\'),\n header={ \'Content-Type\': \'application/json\' }).run(conn)\n\n*Example* Perform depagination with a custom `page` function.\n\n r.http(\'example.com/pages\',\n page=lambda info: info[\'body\'][\'meta\'][\'next\'].default(None),\n page_limit=5).run(conn)\n\n# Learn more\n\nSee [the tutorial](http://rethinkdb.com/docs/external-api-access/) on `r.http` for more examples on how to use this command.\n'),
+ (rethinkdb.ast.RqlQuery.info, b"any.info() -> object\n\nGet information about a ReQL value.\n\n*Example* Get information about a table such as primary key, or cache size.\n\n r.table('marvel').info().run(conn)\n\n"),
+ (rethinkdb.js, b'r.js(js_string[, timeout=<number>]) -> value\n\nCreate a javascript expression.\n\n*Example* Concatenate two strings using JavaScript.\n\n`timeout` is the number of seconds before `r.js` times out. The default value is 5 seconds.\n\n{% infobox %}\nWhenever possible, you should use native ReQL commands rather than `r.js` for better performance.\n{% endinfobox %}\n\n r.js("\'str1\' + \'str2\'").run(conn)\n\n*Example* Select all documents where the \'magazines\' field is greater than 5 by running JavaScript on the server.\n\n r.table(\'marvel\').filter(\n r.js(\'(function (row) { return row.magazines.length > 5; })\')\n ).run(conn)\n\n*Example* You may also specify a timeout in seconds (defaults to 5).\n\n r.js(\'while(true) {}\', timeout=1.3).run(conn)\n\n'),
+ (rethinkdb.json, b'r.json(json_string) -> value\n\nParse a JSON string on the server.\n\n*Example* Send an array to the server\'\n\n r.json("[1,2,3]").run(conn)\n\n'),
+ (rethinkdb.range, b'r.range() -> stream\nr.range([start_value, ]end_value) -> stream\n\nGenerate a stream of sequential integers in a specified range. `range` takes 0, 1 or 2 arguments:\n\n* With no arguments, `range` returns an "infinite" stream from 0 up to and including the maximum integer value;\n* With one argument, `range` returns a stream from 0 up to but not including the end value;\n* With two arguments, `range` returns a stream from the start value up to but not including the end value.\n\nNote that the left bound (including the implied left bound of 0 in the 0- and 1-argument form) is always closed and the right bound is always open: the start value will always be included in the returned range and the end value will *not* be included in the returned range.\n\nAny specified arguments must be integers, or a `RqlRuntimeError` will be thrown. If the start value is equal or to higher than the end value, no error will be thrown but a zero-element stream will be returned.\n\n*Example* Return a four-element range of `[0, 1, 2, 3]`.\n\n > r.range(4).run(conn)\n \n [0, 1, 2, 3]\n\nYou can also use the [limit](http://rethinkdb.com/api/python/limit) command with the no-argument variant to achieve the same result in this case:\n\n > r.range().limit(4).run(conn)\n \n [0, 1, 2, 3]\n\n*Example* Return a range from -5 through 5.\n\n > r.range(-5, 6).run(conn)\n \n [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]\n'),
+ (rethinkdb.ast.RqlQuery.to_json_string, b'value.to_json_string() -> string\nvalue.to_json() -> string\n\nConvert a ReQL value or object to a JSON string. You may use either `to_json_string` or `to_json`.\n\n*Example* Get a ReQL document as a JSON string.\n\n > r.table(\'hero\').get(1).to_json()\n \n \'{"id": 1, "name": "Batman", "city": "Gotham", "powers": ["martial arts", "cinematic entrances"]}\'\n'),
+ (rethinkdb.ast.RqlQuery.to_json, b'value.to_json_string() -> string\nvalue.to_json() -> string\n\nConvert a ReQL value or object to a JSON string. You may use either `to_json_string` or `to_json`.\n\n*Example* Get a ReQL document as a JSON string.\n\n > r.table(\'hero\').get(1).to_json()\n \n \'{"id": 1, "name": "Batman", "city": "Gotham", "powers": ["martial arts", "cinematic entrances"]}\'\n'),
+ (rethinkdb.ast.RqlQuery.type_of, b'any.type_of() -> string\n\nGets the type of a value.\n\n*Example* Get the type of a string.\n\n r.expr("foo").type_of().run(conn)\n\n'),
+ (rethinkdb.uuid, b'r.uuid() -> string\n\nReturn a UUID (universally unique identifier), a string that can be used as a unique ID.\n\n*Example* Generate a UUID.\n\n > r.uuid().run(conn)\n \n 27961a0e-f4e8-4eb3-bf95-c5203e1d87b9\n'),
+ (rethinkdb.net.Cursor.close, b'cursor.close()\n\nClose a cursor. Closing a cursor cancels the corresponding query and frees the memory\nassociated with the open request.\n\n*Example* Close a cursor.\n\n cursor.close()\n'),
+ (rethinkdb.net.Cursor.next, b"cursor.next([wait=True])\n\nGet the next element in the cursor.\n\nThe optional `wait` argument specifies whether to wait for the next available element and how long to wait:\n\n* `True`: Wait indefinitely (the default).\n* `False`: Do not wait at all. If data is immediately available, it will be returned; if it is not available, a `RqlDriverError` will be raised.\n* number: Wait up the specified number of seconds for data to be available before raising `RqlDriverError`.\n\nThe behavior of `next` will be identical with `False`, `None` or the number `0`.\n\nCalling `next` the first time on a cursor provides the first element of the cursor. If the data set is exhausted (e.g., you have retrieved all the documents in a table), a `StopIteration` error will be raised when `next` is called.\n\n*Example* Retrieve the next element.\n\n cursor = r.table('superheroes').run(conn)\n doc = cursor.next()\n\n*Example* Retrieve the next element on a [changefeed](http://rethinkdb.com/docs/changefeeds/python), waiting up to five seconds.\n\n cursor = r.table('superheroes').changes().run(conn)\n doc = cursor.next(wait=5)\n\n__Note:__ RethinkDB sequences can be iterated through via the Python [Iterable][it] interface. The canonical way to retrieve all the results is to use a [for...in](../each/) loop or [list()](../to_array/).\n\n[it]: https://docs.python.org/3.4/library/stdtypes.html#iterator-types\n"),
+ (rethinkdb.ast.RqlQuery.date, b'time.date() -> time\n\nReturn a new time object only based on the day, month and year (ie. the same day at 00:00).\n\n*Example* Retrieve all the users whose birthday is today\n\n r.table("users").filter(lambda user:\n user["birthdate"].date() == r.now().date()\n ).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.day, b'time.day() -> number\n\nReturn the day of a time object as a number between 1 and 31.\n\n*Example* Return the users born on the 24th of any month.\n\n r.table("users").filter(\n r.row["birthdate"].day() == 24\n )\n\n'),
+ (rethinkdb.ast.RqlQuery.day_of_week, b'time.day_of_week() -> number\n\nReturn the day of week of a time object as a number between 1 and 7 (following ISO 8601 standard). For your convenience, the terms r.monday, r.tuesday etc. are defined and map to the appropriate integer.\n\n*Example* Return today\'s day of week.\n\n r.now().day_of_week().run(conn)\n\n*Example* Retrieve all the users who were born on a Tuesday.\n\n r.table("users").filter( lambda user:\n user["birthdate"].day_of_week().eq(r.tuesday)\n )\n\n'),
+ (rethinkdb.ast.RqlQuery.day_of_year, b'time.day_of_year() -> number\n\nReturn the day of the year of a time object as a number between 1 and 366 (following ISO 8601 standard).\n\n*Example* Retrieve all the users who were born the first day of a year.\n\n r.table("users").filter(\n r.row["birthdate"].day_of_year() == 1\n ).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.during, b'time.during(start_time, end_time[, left_bound="closed", right_bound="open"])\n -> bool\n\nReturn whether a time is between two other times. By default, this is inclusive of the start time and exclusive of the end time. Set `left_bound` and `right_bound` to explicitly include (`closed`) or exclude (`open`) that endpoint of the range.\n\n*Example* Retrieve all the posts that were posted between December 1st, 2013 (inclusive) and December 10th, 2013 (exclusive).\n\n r.table("posts").filter(\n r.row[\'date\'].during(r.time(2013, 12, 1, "Z"), r.time(2013, 12, 10, "Z"))\n ).run(conn)\n\n*Example* Retrieve all the posts that were posted between December 1st, 2013 (exclusive) and December 10th, 2013 (inclusive).\n\n r.table("posts").filter(\n r.row[\'date\'].during(r.time(2013, 12, 1, "Z"), r.time(2013, 12, 10, "Z"), left_bound="open", right_bound="closed")\n ).run(conn)\n\n'),
+ (rethinkdb.epoch_time, b'r.epoch_time(epoch_time) -> time\n\nCreate a time object based on seconds since epoch. The first argument is a double and\nwill be rounded to three decimal places (millisecond-precision).\n\n*Example* Update the birthdate of the user "John" to November 3rd, 1986.\n\n r.table("user").get("John").update({"birthdate": r.epoch_time(531360000)}).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.hours, b'time.hours() -> number\n\nReturn the hour in a time object as a number between 0 and 23.\n\n*Example* Return all the posts submitted after midnight and before 4am.\n\n r.table("posts").filter(lambda post:\n post["date"].hours() < 4\n ).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.in_timezone, b"time.in_timezone(timezone) -> time\n\nReturn a new time object with a different timezone. While the time stays the same, the results returned by methods such as hours() will change since they take the timezone into account. The timezone argument has to be of the ISO 8601 format.\n\n*Example* Hour of the day in San Francisco (UTC/GMT -8, without daylight saving time).\n\n r.now().in_timezone('-08:00').hours().run(conn)\n"),
+ (rethinkdb.iso8601, b'r.iso8601(iso8601Date[, default_timezone=\'\']) -> time\n\nCreate a time object based on an ISO 8601 date-time string (e.g. \'2013-01-01T01:01:01+00:00\'). We support all valid ISO 8601 formats except for week dates. If you pass an ISO 8601 date-time without a time zone, you must specify the time zone with the `default_timezone` argument. Read more about the ISO 8601 format at [Wikipedia](http://en.wikipedia.org/wiki/ISO_8601).\n\n*Example* Update the time of John\'s birth.\n\n r.table("user").get("John").update({"birth": r.iso8601(\'1986-11-03T08:30:00-07:00\')}).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.minutes, b'time.minutes() -> number\n\nReturn the minute in a time object as a number between 0 and 59.\n\n*Example* Return all the posts submitted during the first 10 minutes of every hour.\n\n r.table("posts").filter(lambda post:\n post["date"].minutes() < 10\n ).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.month, b'time.month() -> number\n\nReturn the month of a time object as a number between 1 and 12. For your convenience, the terms r.january, r.february etc. are defined and map to the appropriate integer.\n\n*Example* Retrieve all the users who were born in November.\n\n r.table("users").filter(\n r.row["birthdate"].month() == 11\n )\n\n*Example* Retrieve all the users who were born in November.\n\n r.table("users").filter(\n r.row["birthdate"].month() == r.november\n )\n\n'),
+ (rethinkdb.now, b'r.now() -> time\n\nReturn a time object representing the current time in UTC. The command now() is computed once when the server receives the query, so multiple instances of r.now() will always return the same time inside a query.\n\n*Example* Add a new user with the time at which he subscribed.\n\n r.table("users").insert({\n "name": "John",\n "subscription_date": r.now()\n }).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.seconds, b'time.seconds() -> number\n\nReturn the seconds in a time object as a number between 0 and 59.999 (double precision).\n\n*Example* Return the post submitted during the first 30 seconds of every minute.\n\n r.table("posts").filter(lambda post:\n post["date"].seconds() < 30\n ).run(conn)\n\n'),
+ (rethinkdb.time, b'r.time(year, month, day[, hour, minute, second], timezone)\n -> time\n\nCreate a time object for a specific time.\n\nA few restrictions exist on the arguments:\n\n- `year` is an integer between 1400 and 9,999.\n- `month` is an integer between 1 and 12.\n- `day` is an integer between 1 and 31.\n- `hour` is an integer.\n- `minutes` is an integer.\n- `seconds` is a double. Its value will be rounded to three decimal places\n(millisecond-precision).\n- `timezone` can be `\'Z\'` (for UTC) or a string with the format `\xc2\xb1[hh]:[mm]`.\n\n*Example* Update the birthdate of the user "John" to November 3rd, 1986 UTC.\n\n r.table("user").get("John").update({"birthdate": r.time(1986, 11, 3, \'Z\')}).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.time_of_day, b'time.time_of_day() -> number\n\nReturn the number of seconds elapsed since the beginning of the day stored in the time object.\n\n*Example* Retrieve posts that were submitted before noon.\n\n r.table("posts").filter(\n r.row["date"].time_of_day() <= 12*60*60\n ).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.timezone, b'time.timezone() -> string\n\nReturn the timezone of the time object.\n\n*Example* Return all the users in the "-07:00" timezone.\n\n r.table("users").filter(lambda user:\n user["subscriptionDate"].timezone() == "-07:00"\n )\n\n'),
+ (rethinkdb.ast.RqlQuery.to_epoch_time, b'time.to_epoch_time() -> number\n\nConvert a time object to its epoch time.\n\n*Example* Return the current time in seconds since the Unix Epoch with millisecond-precision.\n\n r.now().to_epoch_time()\n\n'),
+ (rethinkdb.ast.RqlQuery.to_iso8601, b'time.to_iso8601() -> string\n\nConvert a time object to a string in ISO 8601 format.\n\n*Example* Return the current ISO 8601 time.\n\n > r.now().to_iso8601().run(conn)\n \n "2015-04-20T18:37:52.690+00:00"\n\n'),
+ (rethinkdb.ast.RqlQuery.year, b'time.year() -> number\n\nReturn the year of a time object.\n\n*Example* Retrieve all the users born in 1986.\n\n r.table("users").filter(lambda user:\n user["birthdate"].year() == 1986\n ).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.append, b"array.append(value) -> array\n\nAppend a value to an array.\n\n*Example* Retrieve Iron Man's equipment list with the addition of some new boots.\n\n r.table('marvel').get('IronMan')['equipment'].append('newBoots').run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.__getitem__, b"sequence[attr] -> sequence\nsingleSelection[attr] -> value\nobject[attr] -> value\narray[index] -> value\n\nGet a single field from an object. If called on a sequence, gets that field from every object in the sequence, skipping objects that lack it.\n\n*Example* What was Iron Man's first appearance in a comic?\n\n r.table('marvel').get('IronMan')['firstAppearance'].run(conn)\n\nThe `[]` command also accepts integer arguments as array offsets, like the [nth](http://rethinkdb.com/api/python/nth) command.\n\n*Example* Get the fourth element in a sequence. (The first element is position `0`, so the fourth element is position `3`.)\n\n r.expr([10, 20, 30, 40, 50])[3]\n \n 40\n"),
+ (rethinkdb.ast.RqlQuery.change_at, b'array.change_at(index, value) -> array\n\nChange a value in an array at a given index. Returns the modified array.\n\n*Example* Bruce Banner hulks out.\n\n r.expr(["Iron Man", "Bruce", "Spider-Man"]).change_at(1, "Hulk").run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.delete_at, b"array.delete_at(index [,endIndex]) -> array\n\nRemove one or more elements from an array at a given index. Returns the modified array. (Note: `delete_at` operates on arrays, not documents; to delete documents, see the [delete](http://rethinkdb.com/api/python/delete) command.)\n\nIf only `index` is specified, `delete_at` removes the element at that index. If both `index` and `end_index` are specified, `delete_at` removes the range of elements between `index` and `end_index`, inclusive of `index` but not inclusive of `end_index`.\n\nIf `end_index` is specified, it must not be less than `index`. Both `index` and `end_index` must be within the array's bounds (i.e., if the array has 10 elements, an `index` or `end_index` of 10 or higher is invalid).\n\nBy using a negative `index` you can delete from the end of the array. `-1` is the last element in the array, `-2` is the second-to-last element, and so on. You may specify a negative `end_index`, although just as with a positive value, this will not be inclusive. The range `(2,-1)` specifies the third element through the next-to-last element.\n\n*Example* Delete the second element of an array.\n\n > r.expr(['a','b','c','d','e','f']).delete_at(1).run(conn)\n \n ['a', 'c', 'd', 'e', 'f']\n\n*Example* Delete the second and third elements of an array.\n\n > r.expr(['a','b','c','d','e','f']).delete_at(1,3).run(conn)\n \n ['a', 'd', 'e', 'f']\n\n*Example* Delete the next-to-last element of an array.\n\n > r.expr(['a','b','c','d','e','f']).delete_at(-2).run(conn)\n \n ['a', 'b', 'c', 'd', 'f']\n\n*Example* Delete a comment on a post.\n\nGiven a post document such as:\n\n{\n id: '4cf47834-b6f9-438f-9dec-74087e84eb63',\n title: 'Post title',\n author: 'Bob',\n comments: [\n { author: 'Agatha', text: 'Comment 1' },\n { author: 'Fred', text: 'Comment 2' }\n ]\n}\n\nThe second comment can be deleted by using `update` and `delete_at` together.\n\n r.table('posts').get('4cf47834-b6f9-438f-9dec-74087e84eb63').update(\n lambda post: { 'comments': post['comments'].delete_at(1) }\n ).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.difference, b"array.difference(array) -> array\n\nRemove the elements of one array from another array.\n\n*Example* Retrieve Iron Man's equipment list without boots.\n\n r.table('marvel').get('IronMan')['equipment'].difference(['Boots']).run(conn)\n\n*Example* Remove Iron Man's boots from his equipment.\n\n r.table('marvel').get('IronMan')[:equipment].update(lambda doc:\n {'equipment': doc['equipment'].difference(['Boots'])}\n ).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.get_field, b"sequence.get_field(attr) -> sequence\nsingleSelection.get_field(attr) -> value\nobject.get_field(attr) -> value\n\nGet a single field from an object. If called on a sequence, gets that field from every\nobject in the sequence, skipping objects that lack it.\n\n*Example* What was Iron Man's first appearance in a comic?\n\n r.table('marvel').get('IronMan').get_field('firstAppearance').run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.has_fields, b'sequence.has_fields([selector1, selector2...]) -> stream\narray.has_fields([selector1, selector2...]) -> array\nobject.has_fields([selector1, selector2...]) -> boolean\n\nTest if an object has one or more fields. An object has a field if it has that key and the key has a non-null value. For instance, the object `{\'a\': 1,\'b\': 2,\'c\': null}` has the fields `a` and `b`.\n\nWhen applied to a single object, `has_fields` returns `true` if the object has the fields and `false` if it does not. When applied to a sequence, it will return a new sequence (an array or stream) containing the elements that have the specified fields.\n\n*Example* Return the players who have won games.\n\n r.table(\'players\').has_fields(\'games_won\').run(conn)\n\n*Example* Return the players who have *not* won games. To do this, use `has_fields` with [not](http://rethinkdb.com/api/python/not), wrapped with [filter](http://rethinkdb.com/api/python/filter).\n\n r.table(\'players\').filter(~r.row.has_fields(\'games_won\')).run(conn)\n\n*Example* Test if a specific player has won any games.\n\n r.table(\'players\').get(\n \'b5ec9714-837e-400c-aa74-dbd35c9a7c4c\').has_fields(\'games_won\').run(conn)\n\n**Nested Fields**\n\n`has_fields` lets you test for nested fields in objects. If the value of a field is itself a set of key/value pairs, you can test for the presence of specific keys.\n\n*Example* In the `players` table, the `games_won` field contains one or more fields for kinds of games won:\n\n {\n \'games_won\': {\n \'playoffs\': 2,\n \'championships\': 1\n }\n }\n\nReturn players who have the "championships" field.\n\n r.table(\'players\').has_fields({\'games_won\': {\'championships\': true}}).run(conn)\n\nNote that `true` in the example above is testing for the existence of `championships` as a field, not testing to see if the value of the `championships` field is set to `true`. There\'s a more convenient shorthand form available. (See [pluck](http://rethinkdb.com/api/python/pluck) for more details on this.)\n\n r.table(\'players\').has_fields({\'games_won\': \'championships\'}).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.insert_at, b'array.insert_at(index, value) -> array\n\nInsert a value in to an array at a given index. Returns the modified array.\n\n*Example* Hulk decides to join the avengers.\n\n r.expr(["Iron Man", "Spider-Man"]).insert_at(1, "Hulk").run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.keys, b"singleSelection.keys() -> array\nobject.keys() -> array\n\nReturn an array containing all of the object's keys.\n\n*Example* Get all the keys of a row.\n\n r.table('marvel').get('ironman').keys().run(conn)\n\n"),
+ (rethinkdb.literal, b'r.literal(object) -> special\n\nReplace an object in a field instead of merging it with an existing object in a `merge` or `update` operation. = Using `literal` with no arguments in a `merge` or `update` operation will remove the corresponding field.\n\n*Example* Replace one nested document with another rather than merging the fields.\n\nAssume your users table has this structure:\n\n [\n {\n "id": 1,\n "name": "Alice",\n "data": {\n "age": 18,\n "city": "Dallas"\n }\n } \n ...\n ]\n\nUsing `update` to modify the `data` field will normally merge the nested documents:\n\n r.table(\'users\').get(1).update({ \'data\': { \'age\': 19, \'job\': \'Engineer\' } }).run(conn)\n \n {\n "id": 1,\n "name": "Alice",\n "data": {\n "age": 19,\n "city": "Dallas",\n "job": "Engineer"\n }\n } \n\nThat will preserve `city` and other existing fields. But to replace the entire `data` document with a new object, use `literal`:\n\n r.table(\'users\').get(1).update({ \'data\': r.literal({ \'age\': 19, \'job\': \'Engineer\' }) }).run(conn)\n \n {\n "id": 1,\n "name": "Alice",\n "data": {\n "age": 19,\n "job": "Engineer"\n }\n } \n\n*Example* Use `literal` to remove a field from a document.\n\n r.table(\'users\').get(1).merge({ "data": r.literal() }).run(conn)\n \n {\n "id": 1,\n "name": "Alice"\n }\n'),
+ (rethinkdb.ast.RqlQuery.merge, b'singleSelection.merge(object|function[, object|function, ...]) -> object\nobject.merge(object|function[, object|function, ...]) -> object\nsequence.merge(object|function[, object|function, ...]) -> stream\narray.merge(object|function[, object|function, ...]) -> array\n\nMerge two or more objects together to construct a new object with properties from all. When there is a conflict between field names, preference is given to fields in the rightmost object in the argument list `merge` also accepts a subquery function that returns an object, which will be used similarly to a [map](http://rethinkdb.com/api/python/map/) function.\n\n*Example* Equip Thor for battle.\n\n r.table(\'marvel\').get(\'thor\').merge(\n r.table(\'equipment\').get(\'hammer\'),\n r.table(\'equipment\').get(\'pimento_sandwich\')\n ).run(conn)\n\n*Example* Equip every hero for battle, using a subquery function to retrieve their weapons.\n\n r.table(\'marvel\').merge(lambda hero:\n { \'weapons\': r.table(\'weapons\').get(hero[\'weapon_id\']) }\n ).run(conn)\n\n*Example* Use `merge` to join each blog post with its comments.\n\nNote that the sequence being merged&mdash;in this example, the comments&mdash;must be coerced from a selection to an array. Without `coerce_to` the operation will throw an error ("Expected type DATUM but found SELECTION").\n\n r.table(\'posts\').merge(lambda post:\n { \'comments\': r.table(\'comments\').get_all(post[\'id\'],\n index=\'post_id\').coerce_to(\'array\') }\n ).run(conn)\n\n*Example* Merge can be used recursively to modify object within objects.\n\n r.expr({\'weapons\' : {\'spectacular graviton beam\' : {\'dmg\' : 10, \'cooldown\' : 20}}}).merge(\n {\'weapons\' : {\'spectacular graviton beam\' : {\'dmg\' : 10}}}\n ).run(conn)\n\n*Example* To replace a nested object with another object you can use the literal keyword.\n\n r.expr({\'weapons\' : {\'spectacular graviton beam\' : {\'dmg\' : 10, \'cooldown\' : 20}}}).merge(\n {\'weapons\' : r.literal({\'repulsor rays\' : {\'dmg\' : 3, \'cooldown\' : 0}})}\n ).run(conn)\n\n*Example* Literal can be used to remove keys from an object as well.\n\n r.expr({\'weapons\' : {\'spectacular graviton beam\' : {\'dmg\' : 10, \'cooldown\' : 20}}}).merge(\n {\'weapons\' : {\'spectacular graviton beam\' : r.literal()}}\n ).run(conn)\n\n'),
+ (rethinkdb.object, b'r.object([key, value,]...) -> object\n\nCreates an object from a list of key-value pairs, where the keys must\nbe strings. `r.object(A, B, C, D)` is equivalent to\n`r.expr([[A, B], [C, D]]).coerce_to(\'OBJECT\')`.\n\n*Example* Create a simple object.\n\n > r.object(\'id\', 5, \'data\', [\'foo\', \'bar\']).run(conn)\n {\'data\': ["foo", "bar"], \'id\': 5}\n'),
+ (rethinkdb.ast.RqlQuery.pluck, b"sequence.pluck([selector1, selector2...]) -> stream\narray.pluck([selector1, selector2...]) -> array\nobject.pluck([selector1, selector2...]) -> object\nsingleSelection.pluck([selector1, selector2...]) -> object\n\nPlucks out one or more attributes from either an object or a sequence of objects\n(projection).\n\n*Example* We just need information about IronMan's reactor and not the rest of the\ndocument.\n\n r.table('marvel').get('IronMan').pluck('reactorState', 'reactorPower').run(conn)\n\n*Example* For the hero beauty contest we only care about certain qualities.\n\n r.table('marvel').pluck('beauty', 'muscleTone', 'charm').run(conn)\n\n*Example* Pluck can also be used on nested objects.\n\n r.table('marvel').pluck({'abilities' : {'damage' : True, 'mana_cost' : True}, 'weapons' : True}).run(conn)\n\n*Example* The nested syntax can quickly become overly verbose so there's a shorthand\nfor it.\n\n r.table('marvel').pluck({'abilities' : ['damage', 'mana_cost']}, 'weapons').run(conn)\n\nFor more information read the [nested field documentation](http://rethinkdb.com/docs/nested-fields/).\n"),
+ (rethinkdb.ast.RqlQuery.prepend, b"array.prepend(value) -> array\n\nPrepend a value to an array.\n\n*Example* Retrieve Iron Man's equipment list with the addition of some new boots.\n\n r.table('marvel').get('IronMan')['equipment'].prepend('newBoots').run(conn)\n"),
+ (rethinkdb.row, b"r.row -> value\n\nReturns the currently visited document. Note that `row` does not work within subqueries to access nested documents; you should use anonymous functions to access those documents instead. (See the last example.)\n\n*Example* Get all users whose age is greater than 5.\n\n r.table('users').filter(r.row['age'] > 5).run(conn)\n\n*Example* Access the attribute 'child' of an embedded document.\n\n r.table('users').filter(r.row['embedded_doc']['child'] > 5).run(conn)\n\n*Example* Add 1 to every element of an array.\n\n r.expr([1, 2, 3]).map(r.row + 1).run(conn)\n\n*Example* For nested queries, use functions instead of `row`.\n\n r.table('users').filter(\n lambda doc: doc['name'] == r.table('prizes').get('winner')\n ).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.set_difference, b"array.set_difference(array) -> array\n\nRemove the elements of one array from another and return them as a set (an array with\ndistinct values).\n\n*Example* Check which pieces of equipment Iron Man has, excluding a fixed list.\n\n r.table('marvel').get('IronMan')['equipment'].set_difference(['newBoots', 'arc_reactor']).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.set_insert, b"array.set_insert(value) -> array\n\nAdd a value to an array and return it as a set (an array with distinct values).\n\n*Example* Retrieve Iron Man's equipment list with the addition of some new boots.\n\n r.table('marvel').get('IronMan')['equipment'].set_insert('newBoots').run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.set_intersection, b"array.set_intersection(array) -> array\n\nIntersect two arrays returning values that occur in both of them as a set (an array with\ndistinct values).\n\n*Example* Check which pieces of equipment Iron Man has from a fixed list.\n\n r.table('marvel').get('IronMan')['equipment'].set_intersection(['newBoots', 'arc_reactor']).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.set_union, b"array.set_union(array) -> array\n\nAdd a several values to an array and return it as a set (an array with distinct values).\n\n*Example* Retrieve Iron Man's equipment list with the addition of some new boots and an arc reactor.\n\n r.table('marvel').get('IronMan')['equipment'].set_union(['newBoots', 'arc_reactor']).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.splice_at, b'array.splice_at(index, array) -> array\n\nInsert several values in to an array at a given index. Returns the modified array.\n\n*Example* Hulk and Thor decide to join the avengers.\n\n r.expr(["Iron Man", "Spider-Man"]).splice_at(1, ["Hulk", "Thor"]).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.without, b"sequence.without([selector1, selector2...]) -> stream\narray.without([selector1, selector2...]) -> array\nsingleSelection.without([selector1, selector2...]) -> object\nobject.without([selector1, selector2...]) -> object\n\nThe opposite of pluck; takes an object or a sequence of objects, and returns them with\nthe specified paths removed.\n\n*Example* Since we don't need it for this computation we'll save bandwidth and leave\nout the list of IronMan's romantic conquests.\n\n r.table('marvel').get('IronMan').without('personalVictoriesList').run(conn)\n\n*Example* Without their prized weapons, our enemies will quickly be vanquished.\n\n r.table('enemies').without('weapons').run(conn)\n\n*Example* Nested objects can be used to remove the damage subfield from the weapons and abilities fields.\n\n r.table('marvel').without({'weapons' : {'damage' : True}, 'abilities' : {'damage' : True}}).run(conn)\n\n*Example* The nested syntax can quickly become overly verbose so there's a shorthand for it.\n\n r.table('marvel').without({'weapons' : 'damage', 'abilities' : 'damage'}).run(conn)\n\n"),
+ (rethinkdb.circle, b"r.circle([longitude, latitude], radius[, num_vertices=32, geo_system='WGS84', unit='m', fill=True]) -> geometry\nr.circle(point, radius[, {num_vertices=32, geo_system='WGS84', unit='m', fill=True]) -> geometry\n\nConstruct a circular line or polygon. A circle in RethinkDB is a polygon or line *approximating* a circle of a given radius around a given center, consisting of a specified number of vertices (default 32).\n\nThe center may be specified either by two floating point numbers, the latitude (&minus;90 to 90) and longitude (&minus;180 to 180) of the point on a perfect sphere (see [Geospatial support](http://rethinkdb.com/docs/geo-support/) for more information on ReQL's coordinate system), or by a point object. The radius is a floating point number whose units are meters by default, although that may be changed with the `unit` argument.\n\nOptional arguments available with `circle` are:\n\n* `num_vertices`: the number of vertices in the polygon or line. Defaults to 32.\n* `geo_system`: the reference ellipsoid to use for geographic coordinates. Possible values are `WGS84` (the default), a common standard for Earth's geometry, or `unit_sphere`, a perfect sphere of 1 meter radius.\n* `unit`: Unit for the radius distance. Possible values are `m` (meter, the default), `km` (kilometer), `mi` (international mile), `nm` (nautical mile), `ft` (international foot).\n* `fill`: if `True` (the default) the circle is filled, creating a polygon; if `False` the circle is unfilled (creating a line).\n\n*Example* Define a circle.\n\n r.table('geo').insert({\n 'id': 300,\n 'name': 'Hayes Valley',\n 'neighborhood': r.circle([-122.423246,37.779388], 1000)\n }).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.distance, b"geometry.distance(geometry[, geo_system='WGS84', unit='m']) -> number\n\nCompute the distance between a point and another geometry object. At least one of the geometry objects specified must be a point.\n\nOptional arguments available with `distance` are:\n\n* `geo_system`: the reference ellipsoid to use for geographic coordinates. Possible values are `WGS84` (the default), a common standard for Earth's geometry, or `unit_sphere`, a perfect sphere of 1 meter radius.\n* `unit`: Unit to return the distance in. Possible values are `m` (meter, the default), `km` (kilometer), `mi` (international mile), `nm` (nautical mile), `ft` (international foot).\n\nIf one of the objects is a polygon or a line, the point will be projected onto the line or polygon assuming a perfect sphere model before the distance is computed (using the model specified with `geo_system`). As a consequence, if the polygon or line is extremely large compared to Earth's radius and the distance is being computed with the default WGS84 model, the results of `distance` should be considered approximate due to the deviation between the ellipsoid and spherical models.\n\n*Example* Compute the distance between two points on the Earth in kilometers.\n\n > point1 = r.point(-122.423246,37.779388)\n > point2 = r.point(-117.220406,32.719464)\n > r.distance(point1, point2, unit='km').run(conn)\n \n 734.1252496021841\n"),
+ (rethinkdb.ast.RqlQuery.fill, b"line.fill() -> polygon\n\nConvert a Line object into a Polygon object. If the last point does not specify the same coordinates as the first point, `polygon` will close the polygon by connecting them.\n\nLongitude (&minus;180 to 180) and latitude (&minus;90 to 90) of vertices are plotted on a perfect sphere. See [Geospatial support](http://rethinkdb.com/docs/geo-support/) for more information on ReQL's coordinate system.\n\nIf the last point does not specify the same coordinates as the first point, `polygon` will close the polygon by connecting them. You cannot directly construct a polygon with holes in it using `polygon`, but you can use [polygon_sub](http://rethinkdb.com/api/python/polygon_sub) to use a second polygon within the interior of the first to define a hole.\n\n*Example* Create a line object and then convert it to a polygon.\n\n r.table('geo').insert({\n 'id': 201,\n 'rectangle': r.line(\n [-122.423246,37.779388],\n [-122.423246,37.329898],\n [-121.886420,37.329898],\n [-121.886420,37.779388]\n )\n }).run(conn)\n \n r.table('geo').get(201).update({\n 'rectangle': r.row('rectangle').fill()\n }).run(conn)\n"),
+ (rethinkdb.geojson, b"r.geojson(geojson) -> geometry\n\nConvert a [GeoJSON][] object to a ReQL geometry object.\n\n[GeoJSON]: http://geojson.org\n\nRethinkDB only allows conversion of GeoJSON objects which have ReQL equivalents: Point, LineString, and Polygon. MultiPoint, MultiLineString, and MultiPolygon are not supported. (You could, however, store multiple points, lines and polygons in an array and use a geospatial multi index with them.)\n\nOnly longitude/latitude coordinates are supported. GeoJSON objects that use Cartesian coordinates, specify an altitude, or specify their own coordinate reference system will be rejected.\n\n*Example* Convert a GeoJSON object to a ReQL geometry object.\n\n geo_json = {\n 'type': 'Point',\n 'coordinates': [ -122.423246, 37.779388 ]\n }\n r.table('geo').insert({\n 'id': 'sfo',\n 'name': 'San Francisco',\n 'location': r.geojson(geo_json)\n }).run(conn)\n"),
+ (rethinkdb.ast.Table.get_intersecting, b"table.get_intersecting(geometry, index='indexname') -> selection<stream>\n\nGet all documents where the given geometry object intersects the geometry object of the requested geospatial index.\n\nThe `index` argument is mandatory. This command returns the same results as `table.filter(r.row('index').intersects(geometry))`. The total number of results is limited to the array size limit which defaults to 100,000, but can be changed with the `array_limit` option to [run](http://rethinkdb.com/api/python/run).\n\n*Example* Which of the locations in a list of parks intersect `circle1`?\n\n circle1 = r.circle([-117.220406,32.719464], 10, unit='mi')\n r.table('parks').get_intersecting(circle1, index='area').run(conn)\n"),
+ (rethinkdb.ast.Table.get_nearest, b"table.get_nearest(point, index='indexname'[, max_results=100, max_dist=100000, unit='m', geo_system='WGS84']) -> array\n\nGet all documents where the specified geospatial index is within a certain distance of the specified point (default 100 kilometers).\n\nThe `index` argument is mandatory. Optional arguments are:\n\n* `max_results`: the maximum number of results to return (default 100).\n* `unit`: Unit for the distance. Possible values are `m` (meter, the default), `km` (kilometer), `mi` (international mile), `nm` (nautical mile), `ft` (international foot).\n* `max_dist`: the maximum distance from an object to the specified point (default 100 km).\n* `geo_system`: the reference ellipsoid to use for geographic coordinates. Possible values are `WGS84` (the default), a common standard for Earth's geometry, or `unit_sphere`, a perfect sphere of 1 meter radius.\n\nThe return value will be an array of two-item objects with the keys `dist` and `doc`, set to the distance between the specified point and the document (in the units specified with `unit`, defaulting to meters) and the document itself, respectively.\n\n*Example* Return a list of enemy hideouts within 5000 meters of the secret base.\n\n secret_base = r.point(-122.422876,37.777128)\n r.table('hideouts').get_nearest(secret_base, index='location',\n max_dist=5000).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.includes, b"sequence.includes(geometry) -> sequence\ngeometry.includes(geometry) -> bool\n\nTests whether a geometry object is completely contained within another. When applied to a sequence of geometry objects, `includes` acts as a [filter](http://rethinkdb.com/api/python/filter), returning a sequence of objects from the sequence that include the argument.\n\n*Example* Is `point2` included within a 2000-meter circle around `point1`?\n\n > point1 = r.point(-117.220406,32.719464)\n > point2 = r.point(-117.206201,32.725186)\n > r.circle(point1, 2000).includes(point2).run(conn)\n \n True\n\n*Example* Which of the locations in a list of parks include `circle1`?\n\n circle1 = r.circle([-117.220406,32.719464], 10, unit='mi')\n r.table('parks')['area'].includes(circle1).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.intersects, b"sequence.intersects(geometry) -> sequence\ngeometry.intersects(geometry) -> bool\n\nTests whether two geometry objects intersect with one another. When applied to a sequence of geometry objects, `intersects` acts as a [filter](http://rethinkdb.com/api/python/filter), returning a sequence of objects from the sequence that intersect with the argument.\n\n*Example* Is `point2` within a 2000-meter circle around `point1`?\n\n > point1 = r.point(-117.220406,32.719464)\n > point2 = r.point(-117.206201,32.725186)\n > r.circle(point1, 2000).intersects(point2).run(conn)\n \n True\n\n*Example* Which of the locations in a list of parks intersect `circle1`?\n\n circle1 = r.circle([-117.220406,32.719464], 10, unit='mi')\n r.table('parks')('area').intersects(circle1).run(conn)\n"),
+ (rethinkdb.line, b"r.line([lon1, lat1], [lon2, lat2], ...) -> line\nr.line(point1, point2, ...) -> line\n\nConstruct a geometry object of type Line. The line can be specified in one of two ways:\n\n* Two or more two-item arrays, specifying latitude and longitude numbers of the line's vertices;\n* Two or more [Point](http://rethinkdb.com/api/python/point) objects specifying the line's vertices.\n\nLongitude (&minus;180 to 180) and latitude (&minus;90 to 90) of vertices are plotted on a perfect sphere. See [Geospatial support](http://rethinkdb.com/docs/geo-support/) for more information on ReQL's coordinate system.\n\n*Example* Define a line.\n\n r.table('geo').insert({\n 'id': 101,\n 'route': r.line([-122.423246,37.779388], [-121.886420,37.329898])\n }).run(conn)\n"),
+ (rethinkdb.point, b"r.point(longitude, latitude) -> point\n\nConstruct a geometry object of type Point. The point is specified by two floating point numbers, the longitude (&minus;180 to 180) and latitude (&minus;90 to 90) of the point on a perfect sphere. See [Geospatial support](http://rethinkdb.com/docs/geo-support/) for more information on ReQL's coordinate system.\n\n*Example* Define a point.\n\n r.table('geo').insert({\n 'id': 1,\n 'name': 'San Francisco',\n 'location': r.point(-122.423246,37.779388)\n }).run(conn)\n"),
+ (rethinkdb.polygon, b"r.polygon([lon1, lat1], [lon2, lat2], ...) -> polygon\nr.polygon(point1, point2, ...) -> polygon\n\nConstruct a geometry object of type Polygon. The Polygon can be specified in one of two ways:\n\n* Three or more two-item arrays, specifying latitude and longitude numbers of the polygon's vertices;\n* Three or more [Point](http://rethinkdb.com/api/python/point) objects specifying the polygon's vertices.\n\nLongitude (&minus;180 to 180) and latitude (&minus;90 to 90) of vertices are plotted on a perfect sphere. See [Geospatial support](http://rethinkdb.com/docs/geo-support/) for more information on ReQL's coordinate system.\n\nIf the last point does not specify the same coordinates as the first point, `polygon` will close the polygon by connecting them. You cannot directly construct a polygon with holes in it using `polygon`, but you can use [polygon_sub](http://rethinkdb.com/api/python/polygon_sub) to use a second polygon within the interior of the first to define a hole.\n\n*Example* Define a polygon.\n\n r.table('geo').insert({\n 'id': 101,\n 'rectangle': r.polygon(\n [-122.423246,37.779388],\n [-122.423246,37.329898],\n [-121.886420,37.329898],\n [-121.886420,37.779388]\n )\n }).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.polygon_sub, b'polygon1.polygon_sub(polygon2) -> polygon\n\nUse `polygon2` to "punch out" a hole in `polygon1`. `polygon2` must be completely contained within `polygon1` and must have no holes itself (it must not be the output of `polygon_sub` itself).\n\n*Example* Define a polygon with a hole punched in it.\n\n outer_polygon = r.polygon(\n [-122.4,37.7],\n [-122.4,37.3],\n [-121.8,37.3],\n [-121.8,37.7]\n )\n inner_polygon = r.polygon(\n [-122.3,37.4],\n [-122.3,37.6],\n [-122.0,37.6],\n [-122.0,37.4]\n )\n outer_polygon.polygon_sub(inner_polygon).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.to_geojson, b"geometry.to_geojson() -> object\n\nConvert a ReQL geometry object to a [GeoJSON][] object.\n\n[GeoJSON]: http://geojson.org\n\n*Example* Convert a ReQL geometry object to a GeoJSON object.\n\n > r.table(geo).get('sfo')['location'].to_geojson().run(conn)\n \n {\n 'type': 'Point',\n 'coordinates': [ -122.423246, 37.779388 ]\n }\n"),
+ (rethinkdb.ast.RqlQuery.eq_join, b'sequence.eq_join(left_field, right_table[, index=\'id\']) -> sequence\n\nJoin tables using a field on the left-hand sequence matching primary keys or secondary indexes on the right-hand table. `eq_join` is more efficient than other Re_qL join types, and operates much faster. Documents in the result set consist of pairs of left-hand and right-hand documents, matched when the field on the left-hand side exists and is non-null and an entry with that field\'s value exists in the specified index on the right-hand side.\n\nThe result set of `eq_join` is a stream or array of objects. Each object in the returned set will be an object of the form `{ left: <left-document>, right: <right-document> }`, where the values of `left` and `right` will be the joined documents. Use the <code><a href="/api/python/zip/">zip</a></code> command to merge the `left` and `right` fields together.\n\n**Example:** Match players with the games they\'ve played against one another.\n\nThe players table contains these documents:\n\n [\n { \'id\': 1, \'player\': \'George\', \'gameId\': 1 },\n { \'id\': 2, \'player\': \'Agatha\', \'gameId\': 3 },\n { \'id\': 3, \'player\': \'Fred\', \'gameId\': 2 },\n { \'id\': 4, \'player\': \'Marie\', \'gameId\': 2 },\n { \'id\': 5, \'player\': \'Earnest\', \'gameId\': 1 },\n { \'id\': 6, \'player\': \'Beth\', \'gameId\': 3 }\n ]\n\nThe games table contains these documents:\n\n [\n { \'id\': 1, \'field\': \'Little Delving\' },\n { \'id\': 2, \'field\': \'Rushock Bog\' },\n { \'id\': 3, \'field\': \'Bucklebury\' }\n ]\n\nJoin these tables using `game_id` on the player table and `id` on the games table:\n\n r.table(\'players\').eq_join(\'game_id\', r.table(\'games\')).run(conn)\n\nThis will return a result set such as the following:\n\n [\n {\n "left" : { "gameId" : 3, "id" : 2, "player" : "Agatha" },\n "right" : { "id" : 3, "field" : "Bucklebury" }\n },\n {\n "left" : { "gameId" : 2, "id" : 3, "player" : "Fred" },\n "right" : { "id" : 2, "field" : "Rushock Bog" }\n },\n ...\n ]\n\nWhat you likely want is the result of using `zip` with that. For clarity, we\'ll use `without` to drop the `id` field from the games table (it conflicts with the `id` field for the players and it\'s redundant anyway), and we\'ll order it by the games.\n\n r.table(\'players\').eq_join(\'game_id\', r.table(\'games\')).without({\'right\': "id"}).zip().order_by(\'game_id\').run(conn)\n \n [\n { "field": "Little Delving", "gameId": 1, "id": 5, "player": "Earnest" },\n { "field": "Little Delving", "gameId": 1, "id": 1, "player": "George" },\n { "field": "Rushock Bog", "gameId": 2, "id": 3, "player": "Fred" },\n { "field": "Rushock Bog", "gameId": 2, "id": 4, "player": "Marie" },\n { "field": "Bucklebury", "gameId": 3, "id": 6, "player": "Beth" },\n { "field": "Bucklebury", "gameId": 3, "id": 2, "player": "Agatha" }\n ]\n\nFor more information, see [Table joins in Rethink_dB](http://rethinkdb.com/docs/table-joins/).\n\n**Example:** Use a secondary index on the right table rather than the primary key. If players have a secondary index on their cities, we can get a list of arenas with players in the same area.\n\n r.table(\'arenas\').eq_join(\'city_id\', r.table(\'arenas\'), index=\'city_id\').run(conn)\n\n**Example:** Use a nested key as the join field. Suppose the documents in the players table were structured like this:\n\n { \'id\': 1, \'player\': \'George\', \'game\': {\'id\': 1} },\n { \'id\': 2, \'player\': \'Agatha\', \'game\': {\'id\': 3} },\n ...\n\nSimply specify the field using the `row` command instead of a string.\n\n r.table(\'players\').eq_join(r.row[\'game\'][\'id\'], r.table(\'games\')).without({\'right\': \'id\'}).zip().run(conn)\n \n [\n { "field": "Little Delving", "game": { "id": 1 }, "id": 5, "player": "Earnest" },\n { "field": "Little Delving", "game": { "id": 1 }, "id": 1, "player": "George" },\n ...\n ]\n\n**Example:** Use a function instead of a field to join on a more complicated expression. Suppose the players have lists of favorite games ranked in order in a field such as `"favorites": [3, 2, 1]`. Get a list of players and their top favorite:\n\n r.table(\'players3\').eq_join(\n lambda player: player[\'favorites\'].nth(0),\n r.table(\'games\')\n ).without([{\'left\': [\'favorites\', \'game_id\', \'id\']}, {\'right\': \'id\'}]).zip()\n\nResult:\n\n [\n \t{ "field": "Rushock Bog", "name": "Fred" },\n \t{ "field": "Little Delving", "name": "George" },\n \t...\n ]\n'),
+ (rethinkdb.ast.RqlQuery.inner_join, b"sequence.inner_join(other_sequence, predicate) -> stream\narray.inner_join(other_sequence, predicate) -> array\n\nReturns an inner join of two sequences. The returned sequence represents an intersection of the left-hand sequence and the right-hand sequence: each row of the left-hand sequence will be compared with each row of the right-hand sequence to find all pairs of rows which satisfy the predicate. Each matched pair of rows of both sequences are combined into a result row. In most cases, you will want to follow the join with [zip](http://rethinkdb.com/api/python/zip) to combine the left and right results.\n\nNote that `inner_join` is slower and much less efficient than using [eq_join](http://rethinkdb.com/api/python/eq_join/) or [concat_map](http://rethinkdb.com/api/python/concat_map/) with [get_all](http://rethinkdb.com/api/python/get_all/). You should avoid using `inner_join` in commands when possible.\n\n*Example* Return a list of all matchups between Marvel and DC heroes in which the DC hero could beat the Marvel hero in a fight.\n\n r.table('marvel').inner_join(r.table('dc'),\n lambda marvel_row, dc_row: marvel_row['strength'] < dc_row['strength']\n ).zip().run(conn)\n\n(Compare this to an [outer_join](http://rethinkdb.com/api/python/outer_join) with the same inputs and predicate, which would return a list of *all* Marvel heroes along with any DC heroes with a higher strength.)"),
+ (rethinkdb.ast.RqlQuery.outer_join, b"sequence.outer_join(other_sequence, predicate) -> stream\narray.outer_join(other_sequence, predicate) -> array\n\nReturns a left outer join of two sequences. The returned sequence represents a union of the left-hand sequence and the right-hand sequence: all documents in the left-hand sequence will be returned, each matched with a document in the right-hand sequence if one satisfies the predicate condition. In most cases, you will want to follow the join with [zip](http://rethinkdb.com/api/python/zip) to combine the left and right results.\n\nNote that `outer_join` is slower and much less efficient than using [concat_map](http://rethinkdb.com/api/python/concat_map/) with [get_all](http://rethinkdb.com/api/python/get_all). You should avoid using `outer_join` in commands when possible.\n\n*Example* Return a list of all Marvel heroes, paired with any DC heroes who could beat them in a fight.\n\n r.table('marvel').outer_join(r.table('dc'),\n lambda marvel_row, dc_row: marvel_row['strength'] < dc_row['strength']\n ).zip().run(conn)\n\n(Compare this to an [inner_join](http://rethinkdb.com/api/python/inner_join) with the same inputs and predicate, which would return a list only of the matchups in which the DC hero has the higher strength.)\n"),
+ (rethinkdb.ast.RqlQuery.zip, b"stream.zip() -> stream\narray.zip() -> array\n\nUsed to 'zip' up the result of a join by merging the 'right' fields into 'left' fields of each member of the sequence.\n\n*Example* 'zips up' the sequence by merging the left and right fields produced by a join.\n\n r.table('marvel').eq_join('main_dc_collaborator', r.table('dc')).zip().run(conn)\n"),
+ (rethinkdb.db_create, b'r.db_create(db_name) -> object\n\nCreate a database. A RethinkDB database is a collection of tables, similar to\nrelational databases.\n\nIf successful, the command returns an object with two fields:\n\n* `dbs_created`: always `1`.\n* `config_changes`: a list containing one object with two fields, `old_val` and `new_val`:\n * `old_val`: always `None`.\n * `new_val`: the database\'s new [config](http://rethinkdb.com/api/python/config) value.\n\nIf a database with the same name already exists, the command throws `RqlRuntimeError`.\n\nNote: Only alphanumeric characters and underscores are valid for the database name.\n\n*Example* Create a database named \'superheroes\'.\n\n r.db_create(\'superheroes\').run(conn)\n \n {\n "config_changes": [\n {\n "new_val": {\n "id": "e4689cfc-e903-4532-a0e6-2d6797a43f07",\n "name": "superheroes"\n },\n "old_val": None\n }\n ],\n "dbs_created": 1\n }\n\n'),
+ (rethinkdb.db_drop, b'r.db_drop(db_name) -> object\n\nDrop a database. The database, all its tables, and corresponding data will be deleted.\n\nIf successful, the command returns an object with two fields:\n\n* `dbs_dropped`: always `1`.\n* `tables_dropped`: the number of tables in the dropped database.\n* `config_changes`: a list containing one two-field object, `old_val` and `new_val`:\n * `old_val`: the database\'s original [config](http://rethinkdb.com/api/python/config) value.\n * `new_val`: always `None`.\n\nIf the given database does not exist, the command throws `RqlRuntimeError`.\n\n*Example* Drop a database named \'superheroes\'.\n\n r.db_drop(\'superheroes\').run(conn)\n \n {\n "config_changes": [\n {\n "old_val": {\n "id": "e4689cfc-e903-4532-a0e6-2d6797a43f07",\n "name": "superheroes"\n },\n "new_val": None\n }\n ],\n "tables_dropped": 3,\n "dbs_dropped": 1\n }\n\n'),
+ (rethinkdb.db_list, b'r.db_list() -> array\n\nList all database names in the system. The result is a list of strings.\n\n*Example* List all databases.\n\n r.db_list().run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.changes, b'stream.changes(squash=True, include_states=False) -> stream\nsingleSelection.changes(squash=True, include_states=False) -> stream\n\nReturn an infinite stream of objects representing changes to a query.\n\nThe `squash` optional argument controls how `changes` batches change notifications:\n\n* `True`: When multiple changes to the same document occur before a batch of notifications is sent, the changes are "squashed" into one change. The client receives a notification that will bring it fully up to date with the server. This is the default.\n* `False`: All changes will be sent to the client verbatim.\n* `n`: A numeric value (floating point). Similar to `True`, but the server will wait `n` seconds to respond in order to squash as many changes together as possible, reducing network traffic.\n\nIf the `include_states` optional argument is `True`, the changefeed stream will include special status documents consisting of the field `state` and a string indicating a change in the feed\'s state. These documents can occur at any point in the feed between the notification documents described below. There are currently two states:\n\n* `{"state": "initializing"}` indicates the following documents represent initial values on the feed rather than changes. This will be the first document of a feed that returns initial values.\n* `{"state": "ready"}` indicates the following documents represent changes. This will be the first document of a feed that does *not* return initial values; otherwise, it will indicate the initial values have all been sent.\n\nPoint changefeeds will always return initial values and have an `initializing` state; feeds that return changes on unfiltered tables will never return initial values. Feeds that return changes on more complex queries may or may not return return initial values, depending on the kind of aggregation. Read the article on [Changefeeds in RethinkDB][cfr] for a more detailed discussion. If `include_states` is `True` on a changefeed that does not return initial values, the first document on the feed will be `{"state": "ready"}`.\n\n[cfr]: /docs/changefeeds/python/\n\nIf `include_states` is `False` (the default), the status documents will not be sent on the feed.\n\nIf the table becomes unavailable, the changefeed will be disconnected, and a runtime exception will be thrown by the driver.\n\nChangefeed notifications take the form of a two-field object:\n\n {\n "old_val": <document before change>,\n "new_val": <document after change>\n }\n\nThe first notification object in the changefeed stream will contain the query\'s initial value in `new_val` and have no `old_val` field. When a document is deleted, `new_val` will be `None`; when a document is inserted, `old_val` will be `None`.\n\nCertain document transformation commands can be chained before changefeeds. For more information, read the [discussion of changefeeds][cfr] in the "Query language" documentation.\n\nThe server will buffer up to 100,000 elements. If the buffer limit is hit, early changes will be discarded, and the client will receive an object of the form `{"error": "Changefeed cache over array size limit, skipped X elements."}` where `X` is the number of elements skipped.\n\nCommands that operate on streams (such as `filter` or `map`) can usually be chained after `changes`. However, since the stream produced by `changes` has no ending, commands that need to consume the entire stream before returning (such as `reduce` or `count`) cannot.\n\nIt\'s a good idea to open changefeeds on their own connection. If you don\'t, other queries run on the same connection will experience unpredictable latency spikes while the connection blocks on more changes.\n\n*Example* Subscribe to the changes on a table.\n\nStart monitoring the changefeed in one client:\n\n for change in r.table(\'games\').changes().run(conn):\n print change\n\nAs these queries are performed in a second client, the first client would receive and print the following objects:\n\n > r.table(\'games\').insert({\'id\': 1}).run(conn)\n {\'old_val\': None, \'new_val\': {\'id\': 1}}\n \n > r.table(\'games\').get(1).update({\'player1\': \'Bob\'}).run(conn)\n {\'old_val\': {\'id\': 1}, \'new_val\': {\'id\': 1, \'player1\': \'Bob\'}}\n \n > r.table(\'games\').get(1).replace({\'id\': 1, \'player1\': \'Bob\', \'player2\': \'Alice\'}).run(conn)\n {\'old_val\': {\'id\': 1, \'player1\': \'Bob\'},\n \'new_val\': {\'id\': 1, \'player1\': \'Bob\', \'player2\': \'Alice\'}}\n \n > r.table(\'games\').get(1).delete().run(conn)\n {\'old_val\': {\'id\': 1, \'player1\': \'Bob\', \'player2\': \'Alice\'}, \'new_val\': None}\n \n > r.table_drop(\'games\').run(conn)\n RqlRuntimeError: Changefeed aborted (table unavailable)\n\n*Example* Return all the changes that increase a player\'s score.\n\n r.table(\'test\').changes().filter(\n r.row[\'new_val\'][\'score\'] > r.row[\'old_val\'][\'score\']\n ).run(conn)\n\n*Example* Return all the changes to Bob\'s score.\n\n # Note that this will have to look at and discard all the changes to\n # rows besides Bob\'s. This is currently no way to filter with an index\n # on changefeeds.\n r.table(\'test\').changes().filter(r.row[\'new_val\'][\'name\'].eq(\'Bob\')).run(conn)\n\n*Example* Return all the inserts on a table.\n\n r.table(\'test\').changes().filter(r.row[\'old_val\'].eq(None)).run(conn)\n\n*Example* Return all the changes to game 1, with state notifications.\n\n r.table(\'games\').get(1).changes(include_states=True).run(conn)\n \n # result returned on changefeed\n {"state": "initializing"}\n {"new_val": {"id": 1, "score": 12, "arena": "Hobbiton Field"}}\n {"state": "ready"}\n {\n \t"old_val": {"id": 1, "score": 12, "arena": "Hobbiton Field"},\n \t"new_val": {"id": 1, "score": 14, "arena": "Hobbiton Field"}\n }\n {\n \t"old_val": {"id": 1, "score": 14, "arena": "Hobbiton Field"},\n \t"new_val": {"id": 1, "score": 17, "arena": "Hobbiton Field", "winner": "Frodo"}\n }\n\n*Example* Return all the changes to the top 10 games. This assumes the presence of a `score` secondary index on the `games` table.\n\n r.table(\'games\').order_by(index=r.desc(\'score\')).limit(10).run(conn)\n'),
+ (rethinkdb.ast.Table.index_create, b'table.index_create(index_name[, index_function][, multi=False, geo=False]) -> object\n\nCreate a new secondary index on a table. Secondary indexes improve the speed of many read queries at the slight cost of increased storage space and decreased write performance. For more information about secondary indexes, read the article "[Using secondary indexes in RethinkDB](http://rethinkdb.com/docs/secondary-indexes/)."\n\nRethinkDB supports different types of secondary indexes:\n\n- *Simple indexes* based on the value of a single field.\n- *Compound indexes* based on multiple fields.\n- *Multi indexes* based on arrays of values.\n- *Geospatial indexes* based on indexes of geometry objects, created when the `geo` optional argument is true.\n- Indexes based on *arbitrary expressions*.\n\nThe `index_function` can be an anonymous function or a binary representation obtained from the `function` field of [index_status](http://rethinkdb.com/api/python/index_status).\n\nIf successful, `create_index` will return an object of the form `{"created": 1}`. If an index by that name already exists on the table, a `RqlRuntimeError` will be thrown.\n\n*Example* Create a simple index based on the field `post_id`.\n\n r.table(\'comments\').index_create(\'post_id\').run(conn)\n*Example* Create a simple index based on the nested field `author > name`.\n\n r.table(\'comments\').index_create(\'author_name\', r.row["author"]["name"]).run(conn)\n\n*Example* Create a geospatial index based on the field `location`.\n\n r.table(\'places\').index_create(\'location\', geo=True).run(conn)\n\nA geospatial index field should contain only geometry objects. It will work with geometry ReQL terms ([get_intersecting](http://rethinkdb.com/api/python/get_intersecting/) and [get_nearest](http://rethinkdb.com/api/python/get_nearest/)) as well as index-specific terms ([index_status](http://rethinkdb.com/api/python/index_status), [index_wait](http://rethinkdb.com/api/python/index_wait), [index_drop](http://rethinkdb.com/api/python/index_drop) and [index_list](http://rethinkdb.com/api/python/index_list)). Using terms that rely on non-geometric ordering such as [get_all](http://rethinkdb.com/api/python/get_all/), [order_by](http://rethinkdb.com/api/python/order_by/) and [between](http://rethinkdb.com/api/python/order_by/) will result in an error.\n\n*Example* Create a compound index based on the fields `post_id` and `date`.\n\n r.table(\'comments\').index_create(\'post_and_date\', [r.row["post_id"], r.row["date"]]).run(conn)\n\n*Example* Create a multi index based on the field `authors`.\n\n r.table(\'posts\').index_create(\'authors\', multi=True).run(conn)\n\n*Example* Create a geospatial multi index based on the field `towers`.\n\n r.table(\'networks\').index_create(\'towers\', geo=True, multi=True).run(conn)\n\n*Example* Create an index based on an arbitrary expression.\n\n r.table(\'posts\').index_create(\'authors\', lambda doc:\n r.branch(\n doc.has_fields("updated_at"),\n doc["updated_at"],\n doc["created_at"]\n )\n ).run(conn)\n\n*Example* Create a new secondary index based on an existing one.\n\n index = r.table(\'posts\').index_status(\'authors\').nth(0)[\'function\'].run(conn)\n r.table(\'new_posts\').index_create(\'authors\', index).run(conn)\n\n*Example* Rebuild an outdated secondary index on a table.\n\n old_index = r.table(\'posts\').index_status(\'old_index\').nth(0)[\'function\'].run(conn)\n r.table(\'posts\').index_create(\'new_index\', old_index).run(conn)\n r.table(\'posts\').index_wait(\'new_index\').run(conn)\n r.table(\'posts\').index_rename(\'new_index\', \'old_index\', overwrite=True).run(conn)\n'),
+ (rethinkdb.ast.Table.index_drop, b"table.index_drop(index_name) -> object\n\nDelete a previously created secondary index of this table.\n\n*Example* Drop a secondary index named 'code_name'.\n\n r.table('dc').index_drop('code_name').run(conn)\n\n"),
+ (rethinkdb.ast.Table.index_list, b"table.index_list() -> array\n\nList all the secondary indexes of this table.\n\n*Example* List the available secondary indexes for this table.\n\n r.table('marvel').index_list().run(conn)\n"),
+ (rethinkdb.ast.Table.index_rename, b"table.index_rename(old_index_name, new_index_name[, overwrite=False]) -> object\n\nRename an existing secondary index on a table. If the optional argument `overwrite` is specified as `True`, a previously existing index with the new name will be deleted and the index will be renamed. If `overwrite` is `False` (the default) an error will be raised if the new index name already exists.\n\nThe return value on success will be an object of the format `{'renamed': 1}`, or `{'renamed': 0}` if the old and new names are the same.\n\nAn error will be raised if the old index name does not exist, if the new index name is already in use and `overwrite` is `False`, or if either the old or new index name are the same as the primary key field name.\n\n*Example* Rename an index on the comments table.\n\n r.table('comments').index_rename('post_id', 'message_id').run(conn)\n"),
+ (rethinkdb.ast.Table.index_status, b'table.index_status([, index...]) -> array\n\nGet the status of the specified indexes on this table, or the status\nof all indexes on this table if no indexes are specified.\n\nThe result is an array where for each index, there will be an object like this one:\n\n {\n "index": <index_name>,\n "ready": True,\n "function": <binary>,\n "multi": <bool>,\n "outdated": <bool>\n }\n\nor this one:\n\n {\n "index": <index_name>,\n "ready": False,\n "blocks_processed": <int>,\n "blocks_total": <int>,\n "function": <binary>,\n "multi": <bool>,\n "outdated": <bool>\n }\n\nThe `multi` field will be `true` or `false` depending on whether this index was created as a multi index (see [index_create](http://rethinkdb.com/api/python/index_create/) for details). The `outdated` field will be true if the index is outdated in the current version of RethinkDB and needs to be rebuilt.\n\nThe `function` field is a binary object containing an opaque representation of the secondary index (including the `multi` argument if specified). It can be passed as the second argument to [index_create](http://rethinkdb.com/api/python/index_create/) to create a new index with the same function; see `index_create` for more information.\n\n*Example* Get the status of all the indexes on `test`:\n\n r.table(\'test\').index_status().run(conn)\n\n*Example* Get the status of the `timestamp` index:\n\n r.table(\'test\').index_status(\'timestamp\').run(conn)\n\n*Example* Save the binary representation of the index:\n\n func = r.table(\'test\').index_status(\'timestamp\').nth(0)[\'function\'].run(conn)\n'),
+ (rethinkdb.ast.Table.index_wait, b'table.index_wait([, index...]) -> array\n\nWait for the specified indexes on this table to be ready, or for all\nindexes on this table to be ready if no indexes are specified.\n\nThe result is an array containing one object for each table index:\n\n {\n "index": <index_name>,\n "ready": True,\n "function": <binary>,\n "multi": <bool>,\n "geo": <bool>,\n "outdated": <bool>\n }\n\nSee the [index_status](http://rethinkdb.com/api/python/index_status) documentation for a description of the field values.\n\n*Example* Wait for all indexes on the table `test` to be ready:\n\n r.table(\'test\').index_wait().run(conn)\n\n*Example* Wait for the index `timestamp` to be ready:\n\n r.table(\'test\').index_wait(\'timestamp\').run(conn)\n'),
+ (rethinkdb.ast.DB.table_create, b'db.table_create(table_name[, options]) -> object\n\nCreate a table. A RethinkDB table is a collection of JSON documents.\n\nIf successful, the command returns an object with two fields:\n\n* `tables_created`: always `1`.\n* `config_changes`: a list containing one two-field object, `old_val` and `new_val`:\n * `old_val`: always `None`.\n * `new_val`: the table\'s new [config](http://rethinkdb.com/api/python/config) value.\n\nIf a table with the same name already exists, the command throws `RqlRuntimeError`.\n\nNote: Only alphanumeric characters and underscores are valid for the table name.\n\nWhen creating a table you can specify the following options:\n\n* `primary_key`: the name of the primary key. The default primary key is `id`.\n* `durability`: if set to `soft`, writes will be acknowledged by the server immediately and flushed to disk in the background. The default is `hard`: acknowledgment of writes happens after data has been written to disk.\n* `shards`: the number of shards, an integer from 1-32. Defaults to `1`.\n* `replicas`: either an integer or a mapping object. Defaults to `1`.\n * If `replicas` is an integer, it specifies the number of replicas per shard. Specifying more replicas than there are servers will return an error.\n * If `replicas` is an object, it specifies key-value pairs of server tags and the number of replicas to assign to those servers: `{\'tag1\': 2, \'tag2\': 4, \'tag3\': 2, ...}`.\n* `primary_replica_tag`: the primary server specified by its server tag. Required if `replicas` is an object; the tag must be in the object. This must *not* be specified if `replicas` is an integer.\n\nThe [data type](http://rethinkdb.com/docs/data-types/) of a primary key is usually a string (like a UUID) or a number, but it can also be a time, binary object, boolean or an array. It cannot be an object.\n\n*Example* Create a table named \'dc_universe\' with the default settings.\n\n r.db(\'test\').table_create(\'dc_universe\').run(conn)\n \n {\n "config_changes": [\n {\n "new_val": {\n "db": "test",\n "durability": "hard",\n "id": "20ea60d4-3b76-4817-8828-98a236df0297",\n "name": "dc_universe",\n "primary_key": "id",\n "shards": [\n {\n "primary_replica": "rethinkdb_srv1",\n "replicas": [\n "rethinkdb_srv1",\n "rethinkdb_srv2"\n ]\n }\n ],\n "write_acks": "majority"\n },\n "old_val": None\n }\n ],\n "tables_created": 1\n }\n\n*Example* Create a table named \'dc_universe\' using the field \'name\' as primary key.\n\n r.db(\'test\').table_create(\'dc_universe\', primary_key=\'name\').run(conn)\n\n*Example* Create a table set up for two shards and three replicas per shard. This requires three available servers.\n\n r.db(\'test\').table_create(\'dc_universe\', shards=2, replicas=3).run(conn)\n\nRead [Sharding and replication](http://rethinkdb.com/docs/sharding-and-replication/) for a complete discussion of the subject, including advanced topics.\n'),
+ (rethinkdb.ast.DB.table_drop, b'db.table_drop(table_name) -> object\n\nDrop a table. The table and all its data will be deleted.\n\nIf successful, the command returns an object with two fields:\n\n* `tables_dropped`: always `1`.\n* `config_changes`: a list containing one two-field object, `old_val` and `new_val`:\n * `old_val`: the dropped table\'s [config](http://rethinkdb.com/api/python/config) value.\n * `new_val`: always `None`.\n\nIf the given table does not exist in the database, the command throws `RqlRuntimeError`.\n\n*Example* Drop a table named \'dc_universe\'.\n\n r.db(\'test\').table_drop(\'dc_universe\').run(conn)\n \n {\n "config_changes": [\n {\n "old_val": {\n "db": "test",\n "durability": "hard",\n "id": "20ea60d4-3b76-4817-8828-98a236df0297",\n "name": "dc_universe",\n "primary_key": "id",\n "shards": [\n {\n "primary_replica": "rethinkdb_srv1",\n "replicas": [\n "rethinkdb_srv1",\n "rethinkdb_srv2"\n ]\n }\n ],\n "write_acks": "majority"\n },\n "new_val": None\n }\n ],\n "tables_dropped": 1\n }\n'),
+ (rethinkdb.ast.DB.table_list, b"db.table_list() -> array\n\nList all table names in a database. The result is a list of strings.\n\n*Example* List all tables of the 'test' database.\n\n r.db('test').table_list().run(conn)\n \n"),
+ (rethinkdb.ast.RqlQuery.__add__, b'number + number -> number\nstring + string -> string\narray + array -> array\ntime + number -> time\n\nSum two numbers, concatenate two strings, or concatenate 2 arrays.\n\n*Example* It\'s as easy as 2 + 2 = 4.\n\n > (r.expr(2) + 2).run(conn)\n \n 4\n\n*Example* Strings can be concatenated too.\n\n > (r.expr("foo") + "bar").run(conn)\n \n "foobar"\n\n*Example* Arrays can be concatenated too.\n\n > (r.expr(["foo", "bar"]) + ["buzz"]).run(conn)\n \n [\'foo\', \'bar\', \'buzz\']\n\n*Example* Create a date one year from now.\n\n r.now() + 365*24*60*60\n\n*Example* Use [args](http://rethinkdb.com/api/python/args) with `add` to sum multiple values.\n\n > r.add(r.args([10, 20, 30])).run(conn)\n \n 60\n\n*Example* Concatenate an array of strings with `args`.\n\n > r.add(r.args([\'foo\', \'bar\', \'buzz\'])).run(conn)\n \n "foobarbuzz"\n'),
+ (rethinkdb.add, b'number + number -> number\nstring + string -> string\narray + array -> array\ntime + number -> time\n\nSum two numbers, concatenate two strings, or concatenate 2 arrays.\n\n*Example* It\'s as easy as 2 + 2 = 4.\n\n > (r.expr(2) + 2).run(conn)\n \n 4\n\n*Example* Strings can be concatenated too.\n\n > (r.expr("foo") + "bar").run(conn)\n \n "foobar"\n\n*Example* Arrays can be concatenated too.\n\n > (r.expr(["foo", "bar"]) + ["buzz"]).run(conn)\n \n [\'foo\', \'bar\', \'buzz\']\n\n*Example* Create a date one year from now.\n\n r.now() + 365*24*60*60\n\n*Example* Use [args](http://rethinkdb.com/api/python/args) with `add` to sum multiple values.\n\n > r.add(r.args([10, 20, 30])).run(conn)\n \n 60\n\n*Example* Concatenate an array of strings with `args`.\n\n > r.add(r.args([\'foo\', \'bar\', \'buzz\'])).run(conn)\n \n "foobarbuzz"\n'),
+ (rethinkdb.ast.RqlQuery.__and__, b'bool & bool -> bool\nr.and_(bool, bool) -> bool\nbool.and_(bool) -> bool\n\nCompute the logical "and" of two or more values. The `and_` command can be used as an infix operator after its first argument (`r.expr(True).and_(False)`) or given all of its arguments as parameters (`r.and_(True, False)`). The standard Python and operator, `&`, may also be used with ReQL.\n\n*Example* Return whether both `a` and `b` evaluate to true.\n\n > a = True\n > b = False\n > (r.expr(a) & b).run(conn)\n \n False\n*Example* Return whether all of `x`, `y` and `z` evaluate to true.\n\n > x = True\n > y = True\n > z = True\n > r.and_(x, y, z).run(conn)\n \n True\n'),
+ (rethinkdb.and_, b'bool & bool -> bool\nr.and_(bool, bool) -> bool\nbool.and_(bool) -> bool\n\nCompute the logical "and" of two or more values. The `and_` command can be used as an infix operator after its first argument (`r.expr(True).and_(False)`) or given all of its arguments as parameters (`r.and_(True, False)`). The standard Python and operator, `&`, may also be used with ReQL.\n\n*Example* Return whether both `a` and `b` evaluate to true.\n\n > a = True\n > b = False\n > (r.expr(a) & b).run(conn)\n \n False\n*Example* Return whether all of `x`, `y` and `z` evaluate to true.\n\n > x = True\n > y = True\n > z = True\n > r.and_(x, y, z).run(conn)\n \n True\n'),
+ (rethinkdb.ast.RqlQuery.__div__, b"number / number -> number\n\nDivide two numbers.\n\n*Example* It's as easy as 2 / 2 = 1.\n\n (r.expr(2) / 2).run(conn)\n"),
+ (rethinkdb.div, b"number / number -> number\n\nDivide two numbers.\n\n*Example* It's as easy as 2 / 2 = 1.\n\n (r.expr(2) / 2).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.__eq__, b'value == value -> bool\nvalue.eq(value) -> bool\n\nTest if two values are equal.\n\n*Example* Does 2 equal 2?\n\n (r.expr(2) == 2).run(conn)\n r.expr(2).eq(2).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.eq, b'value == value -> bool\nvalue.eq(value) -> bool\n\nTest if two values are equal.\n\n*Example* Does 2 equal 2?\n\n (r.expr(2) == 2).run(conn)\n r.expr(2).eq(2).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.__ge__, b'value >= value -> bool\nvalue.ge(value) -> bool\n\nTest if the first value is greater than or equal to other.\n\n*Example* Is 2 greater than or equal to 2?\n\n (r.expr(2) >= 2).run(conn)\n r.expr(2).ge(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.ge, b'value >= value -> bool\nvalue.ge(value) -> bool\n\nTest if the first value is greater than or equal to other.\n\n*Example* Is 2 greater than or equal to 2?\n\n (r.expr(2) >= 2).run(conn)\n r.expr(2).ge(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.__gt__, b'value > value -> bool\nvalue.gt(value) -> bool\n\nTest if the first value is greater than other.\n\n*Example* Is 2 greater than 2?\n\n (r.expr(2) > 2).run(conn)\n r.expr(2).gt(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.gt, b'value > value -> bool\nvalue.gt(value) -> bool\n\nTest if the first value is greater than other.\n\n*Example* Is 2 greater than 2?\n\n (r.expr(2) > 2).run(conn)\n r.expr(2).gt(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.__le__, b'value <= value -> bool\nvalue.le(value) -> bool\n\nTest if the first value is less than or equal to other.\n\n*Example* Is 2 less than or equal to 2?\n\n (r.expr(2) <= 2).run(conn)\n r.expr(2).le(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.le, b'value <= value -> bool\nvalue.le(value) -> bool\n\nTest if the first value is less than or equal to other.\n\n*Example* Is 2 less than or equal to 2?\n\n (r.expr(2) <= 2).run(conn)\n r.expr(2).le(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.__lt__, b'value < value -> bool\nvalue.lt(value) -> bool\n\nTest if the first value is less than other.\n\n*Example* Is 2 less than 2?\n\n (r.expr(2) < 2).run(conn)\n r.expr(2).lt(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.lt, b'value < value -> bool\nvalue.lt(value) -> bool\n\nTest if the first value is less than other.\n\n*Example* Is 2 less than 2?\n\n (r.expr(2) < 2).run(conn)\n r.expr(2).lt(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.__mod__, b"number % number -> number\n\nFind the remainder when dividing two numbers.\n\n*Example* It's as easy as 2 % 2 = 0.\n\n (r.expr(2) % 2).run(conn)\n\n`\n"),
+ (rethinkdb.mod, b"number % number -> number\n\nFind the remainder when dividing two numbers.\n\n*Example* It's as easy as 2 % 2 = 0.\n\n (r.expr(2) % 2).run(conn)\n\n`\n"),
+ (rethinkdb.ast.RqlQuery.__mul__, b'number * number -> number\narray * number -> array\n\nMultiply two numbers, or make a periodic array.\n\n*Example* It\'s as easy as 2 * 2 = 4.\n\n (r.expr(2) * 2).run(conn)\n\n*Example* Arrays can be multiplied by numbers as well.\n\n (r.expr(["This", "is", "the", "song", "that", "never", "ends."]) * 100).run(conn)\n\n'),
+ (rethinkdb.mul, b'number * number -> number\narray * number -> array\n\nMultiply two numbers, or make a periodic array.\n\n*Example* It\'s as easy as 2 * 2 = 4.\n\n (r.expr(2) * 2).run(conn)\n\n*Example* Arrays can be multiplied by numbers as well.\n\n (r.expr(["This", "is", "the", "song", "that", "never", "ends."]) * 100).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.__ne__, b'value != value -> bool\nvalue.ne(value) -> bool\n\nTest if two values are not equal.\n\n*Example* Does 2 not equal 2?\n\n (r.expr(2) != 2).run(conn)\n r.expr(2).ne(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.ne, b'value != value -> bool\nvalue.ne(value) -> bool\n\nTest if two values are not equal.\n\n*Example* Does 2 not equal 2?\n\n (r.expr(2) != 2).run(conn)\n r.expr(2).ne(2).run(conn)\n\n'),
+ (rethinkdb.ast.RqlQuery.__invert__, b'bool.not_() -> bool\nnot_(bool) -> bool\n(~bool) -> bool\n\nCompute the logical inverse (not) of an expression.\n\n`not_` can be called either via method chaining, immediately after an expression that evaluates as a boolean value, or by passing the expression as a parameter to `not_`. All values that are not `False` or `None` will be converted to `True`.\n\nYou may also use `~` as a shorthand operator.\n\n*Example* Not true is false.\n\n r.not_(True).run(conn)\n r.expr(True).not_().run(conn)\n (~r.expr(True)).run(conn)\n\nThese evaluate to `false`.\n\nNote that when using `~` the expression is wrapped in parentheses. Without this, Python will evaluate `r.expr(True)` *first* rather than using the ReQL operator and return an incorrect value. (`~True` evaluates to &minus;2 in Python.)\n\n*Example* Return all the users that do not have a "flag" field.\n\n r.table(\'users\').filter(\n lambda users: (~users.has_fields(\'flag\'))\n ).run(conn)\n\n*Example* As above, but prefix-style.\n\n r.table(\'users\').filter(\n lambda users: r.not_(users.has_fields(\'flag\'))\n ).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.not_, b'bool.not_() -> bool\nnot_(bool) -> bool\n(~bool) -> bool\n\nCompute the logical inverse (not) of an expression.\n\n`not_` can be called either via method chaining, immediately after an expression that evaluates as a boolean value, or by passing the expression as a parameter to `not_`. All values that are not `False` or `None` will be converted to `True`.\n\nYou may also use `~` as a shorthand operator.\n\n*Example* Not true is false.\n\n r.not_(True).run(conn)\n r.expr(True).not_().run(conn)\n (~r.expr(True)).run(conn)\n\nThese evaluate to `false`.\n\nNote that when using `~` the expression is wrapped in parentheses. Without this, Python will evaluate `r.expr(True)` *first* rather than using the ReQL operator and return an incorrect value. (`~True` evaluates to &minus;2 in Python.)\n\n*Example* Return all the users that do not have a "flag" field.\n\n r.table(\'users\').filter(\n lambda users: (~users.has_fields(\'flag\'))\n ).run(conn)\n\n*Example* As above, but prefix-style.\n\n r.table(\'users\').filter(\n lambda users: r.not_(users.has_fields(\'flag\'))\n ).run(conn)\n'),
+ (rethinkdb.not_, b'bool.not_() -> bool\nnot_(bool) -> bool\n(~bool) -> bool\n\nCompute the logical inverse (not) of an expression.\n\n`not_` can be called either via method chaining, immediately after an expression that evaluates as a boolean value, or by passing the expression as a parameter to `not_`. All values that are not `False` or `None` will be converted to `True`.\n\nYou may also use `~` as a shorthand operator.\n\n*Example* Not true is false.\n\n r.not_(True).run(conn)\n r.expr(True).not_().run(conn)\n (~r.expr(True)).run(conn)\n\nThese evaluate to `false`.\n\nNote that when using `~` the expression is wrapped in parentheses. Without this, Python will evaluate `r.expr(True)` *first* rather than using the ReQL operator and return an incorrect value. (`~True` evaluates to &minus;2 in Python.)\n\n*Example* Return all the users that do not have a "flag" field.\n\n r.table(\'users\').filter(\n lambda users: (~users.has_fields(\'flag\'))\n ).run(conn)\n\n*Example* As above, but prefix-style.\n\n r.table(\'users\').filter(\n lambda users: r.not_(users.has_fields(\'flag\'))\n ).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.__or__, b'bool | bool -> bool\nbool.or_(bool[, bool, ...]) -> bool\nr.or_(bool, bool) -> bool\n\nCompute the logical "or" of two or more values. The `or_` command can be used as an infix operator after its first argument (`r.expr(True).or_(False)`) or given all of its arguments as parameters (`r.or_(True, False)`). The standard Python or operator, `|`, may also be used with ReQL.\n\n*Example* Return whether either `a` or `b` evaluate to true.\n\n > a = True\n > b = False\n > (r.expr(a) | b).run(conn)\n \n True\n\n*Example* Return whether any of `x`, `y` or `z` evaluate to true.\n\n > x = False\n > y = False\n > z = False\n > r.or_(x, y, z).run(conn)\n \n False\n\n__Note:__ When using `or` inside a `filter` predicate to test the values of fields that may not exist on the documents being tested, you should use the `default` command with those fields so they explicitly return `False`.\n\n r.table(\'posts\').filter(lambda post:\n post[\'category\'].default(\'foo\').eq(\'article\').or(\n post[\'genre\'].default(\'foo\').eq(\'mystery\'))\n ).run(conn)\n'),
+ (rethinkdb.or_, b'bool | bool -> bool\nbool.or_(bool[, bool, ...]) -> bool\nr.or_(bool, bool) -> bool\n\nCompute the logical "or" of two or more values. The `or_` command can be used as an infix operator after its first argument (`r.expr(True).or_(False)`) or given all of its arguments as parameters (`r.or_(True, False)`). The standard Python or operator, `|`, may also be used with ReQL.\n\n*Example* Return whether either `a` or `b` evaluate to true.\n\n > a = True\n > b = False\n > (r.expr(a) | b).run(conn)\n \n True\n\n*Example* Return whether any of `x`, `y` or `z` evaluate to true.\n\n > x = False\n > y = False\n > z = False\n > r.or_(x, y, z).run(conn)\n \n False\n\n__Note:__ When using `or` inside a `filter` predicate to test the values of fields that may not exist on the documents being tested, you should use the `default` command with those fields so they explicitly return `False`.\n\n r.table(\'posts\').filter(lambda post:\n post[\'category\'].default(\'foo\').eq(\'article\').or(\n post[\'genre\'].default(\'foo\').eq(\'mystery\'))\n ).run(conn)\n'),
+ (rethinkdb.random, b"r.random() -> number\nr.random(number[, number], float=True) -> number\nr.random(integer[, integer]) -> integer\n\nGenerate a random number between given (or implied) bounds. `random` takes zero, one or two arguments.\n\n- With __zero__ arguments, the result will be a floating-point number in the range `[0,1)` (from 0 up to but not including 1).\n- With __one__ argument _x,_ the result will be in the range `[0,x)`, and will be integer unless `float=True` is given as an option. Specifying a floating point number without the `float` option will raise an error.\n- With __two__ arguments _x_ and _y,_ the result will be in the range `[x,y)`, and will be integer unless `float=True` is given as an option. If _x_ and _y_ are equal an error will occur, unless the floating-point option has been specified, in which case _x_ will be returned. Specifying a floating point number without the `float` option will raise an error.\n\nNote: The last argument given will always be the 'open' side of the range, but when\ngenerating a floating-point number, the 'open' side may be less than the 'closed' side.\n\n*Example* Generate a random number in the range `[0,1)`\n\n r.random().run(conn)\n\n*Example* Generate a random integer in the range `[0,100)`\n\n r.random(100).run(conn)\n r.random(0, 100).run(conn)\n\n*Example* Generate a random number in the range `(-2.24,1.59]`\n\n r.random(1.59, -2.24, float=True).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.__sub__, b"number - number -> number\ntime - time -> number\ntime - number -> time\n\nSubtract two numbers.\n\n*Example* It's as easy as 2 - 2 = 0.\n\n (r.expr(2) - 2).run(conn)\n\n*Example* Create a date one year ago today.\n\n r.now() - 365*24*60*60\n\n*Example* Retrieve how many seconds elapsed between today and date\n\n r.now() - date\n\n"),
+ (rethinkdb.sub, b"number - number -> number\ntime - time -> number\ntime - number -> time\n\nSubtract two numbers.\n\n*Example* It's as easy as 2 - 2 = 0.\n\n (r.expr(2) - 2).run(conn)\n\n*Example* Create a date one year ago today.\n\n r.now() - 365*24*60*60\n\n*Example* Retrieve how many seconds elapsed between today and date\n\n r.now() - date\n\n"),
+ (rethinkdb.ast.Table.between, b'table.between(lower_key, upper_key[, index=\'id\', left_bound=\'closed\', right_bound=\'open\'])\n -> selection\n\nGet all documents between two keys. Accepts three optional arguments: `index`, `left_bound`, and `right_bound`. If `index` is set to the name of a secondary index, `between` will return all documents where that index\'s value is in the specified range (it uses the primary key by default). `left_bound` or `right_bound` may be set to `open` or `closed` to indicate whether or not to include that endpoint of the range (by default, `left_bound` is closed and `right_bound` is open).\n\nYou may also use the special constants `r.minval` and `r.maxval` for boundaries, which represent "less than any index key" and "more than any index key" respectively. For instance, if you use `r.minval` as the lower key, then `between` will return all documents whose primary keys (or indexes) are less than the specified upper key.\n\nNote that compound indexes are sorted using [lexicographical order][lo]. Take the following range as an example:\n\n\t[[1, "c"] ... [5, "e"]]\n\nThis range includes all compound keys:\n\n* whose first item is 1 and second item is equal or greater than "c";\n* whose first item is between 1 and 5, *regardless of the value of the second item*;\n* whose first item is 5 and second item is less than or equal to "e".\n\n[lo]: https://en.wikipedia.org/wiki/Lexicographical_order\n\n*Example* Find all users with primary key >= 10 and < 20 (a normal half-open interval).\n\n r.table(\'marvel\').between(10, 20).run(conn)\n\n*Example* Find all users with primary key >= 10 and <= 20 (an interval closed on both sides).\n\n r.table(\'marvel\').between(10, 20, right_bound=\'closed\').run(conn)\n\n*Example* Find all users with primary key < 20.\n\n r.table(\'marvel\').between(r.minval, 20).run(conn)\n\n*Example* Find all users with primary key > 10.\n\n r.table(\'marvel\').between(10, r.maxval, left_bound=\'open\').run(conn)\n\n*Example* Between can be used on secondary indexes too. Just pass an optional index argument giving the secondary index to query.\n\n r.table(\'dc\').between(\'dark_knight\', \'man_of_steel\', index=\'code_name\').run(conn)\n\n*Example* Get all users whose full name is between "John Smith" and "Wade Welles."\n\n r.table("users").between(["Smith", "John"], ["Welles", "Wade"],\n index="full_name").run(conn)\n\n*Example* Subscribe to a [changefeed](http://rethinkdb.com/docs/changefeeds/javascript) of teams ranked in the top 10.\n\n changes = r.table("teams").between(1, 11, index="rank").changes().run(conn)\n\n__Note:__ Between works with secondary indexes on date fields, but will not work with unindexed date fields. To test whether a date value is between two other dates, use the [during](http://rethinkdb.com/api/python/during) command, not `between`.\n\nSecondary indexes can be used in extremely powerful ways with `between` and other commands; read the full article on [secondary indexes](http://rethinkdb.com/docs/secondary-indexes) for examples using boolean operations, `contains` and more.\n\n__Note:__ RethinkDB uses byte-wise ordering for `between` and does not support Unicode collations; non-ASCII characters will be sorted by UTF-8 codepoint.\n\n__Note:__ If you chain `between` after [order_by](http://rethinkdb.com/api/python/order_by), the `between` command must use the index specified in `order_by`, and will default to that index. Trying to specify another index will result in a `RqlRuntimeError`.\n'),
+ (rethinkdb.db, b"r.db(db_name) -> db\n\nReference a database.\n\n*Example* Before we can query a table we have to select the correct database.\n\n r.db('heroes').table('marvel').run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.filter, b'selection.filter(predicate[, default=False]) -> selection\nstream.filter(predicate[, default=False]) -> stream\narray.filter(predicate[, default=False]) -> array\n\nReturn all the elements in a sequence for which the given predicate is true. The return value of `filter` will be the same as the input (sequence, stream, or array). Documents can be filtered in a variety of ways&mdash;ranges, nested values, boolean conditions, and the results of anonymous functions.\n\nBy default, `filter` will silently skip documents with missing fields: if the predicate tries to access a field that doesn\'t exist (for instance, the predicate `{\'age\': 30}` applied to a document with no `age` field), that document will not be returned in the result set, and no error will be generated. This behavior can be changed with the `default` optional argument.\n\n* If `default` is set to `True`, documents with missing fields will be returned rather than skipped.\n* If `default` is set to `r.error()`, an `RqlRuntimeError` will be thrown when a document with a missing field is tested.\n* If `default` is set to `False` (the default), documents with missing fields will be skipped.\n\n*Example* Get all users who are 30 years old.\n\n r.table(\'users\').filter({\'age\': 30}).run(conn)\n\nThe predicate `{\'age\': 30}` selects documents in the `users` table with an `age` field whose value is `30`. Documents with an `age` field set to any other value *or* with no `age` field present are skipped.\n\nWhile the `{\'field\': value}` style of predicate is useful for exact matches, a more general way to write a predicate is to use the [row](http://rethinkdb.com/api/python/row) command with a comparison operator such as [eq](http://rethinkdb.com/api/python/eq) (`==`) or [gt](http://rethinkdb.com/api/python/gt) (`>`), or to use a lambda function that returns `True` or `False`.\n\n r.table(\'users\').filter(r.row["age"] == 30).run(conn)\n\nIn this case, the predicate `r.row["age"] == 30` returns `True` if the field `age` is equal to 30. You can write this predicate as a lambda function instead:\n\n r.table(\'users\').filter(lambda user:\n user["age"] == 30\n ).run(conn)\n\nPredicates to `filter` are evaluated on the server, and must use ReQL expressions. Some Python comparison operators are overloaded by the RethinkDB driver and will be translated to ReQL, such as `==`, `<`/`>` and `|`/`&` (note the single character form, rather than `||`/`&&`).\n\nAlso, predicates must evaluate document fields. They cannot evaluate [secondary indexes](http://rethinkdb.com/docs/secondary-indexes/).\n\n*Example* Get all users who are more than 18 years old.\n\n r.table("users").filter(r.row["age"] > 18).run(conn)\n\n*Example* Get all users who are less than 18 years old and more than 13 years old.\n\n r.table("users").filter((r.row["age"] < 18) & (r.row["age"] > 13)).run(conn)\n\n*Example* Get all users who are more than 18 years old or have their parental consent.\n\n r.table("users").filter(\n (r.row["age"] >= 18) | (r.row["hasParentalConsent"])).run(conn)\n\n*Example* Retrieve all users who subscribed between January 1st, 2012\n(included) and January 1st, 2013 (excluded).\n\n r.table("users").filter(\n lambda user: user["subscription_date"].during(\n r.time(2012, 1, 1, \'Z\'), r.time(2013, 1, 1, \'Z\'))\n ).run(conn)\n\n*Example* Retrieve all users who have a gmail account (whose field `email` ends with `@gmail.com`).\n\n r.table("users").filter(\n lambda user: user["email"].match("@gmail.com$")\n ).run(conn)\n\n*Example* Filter based on the presence of a value in an array.\n\nGiven this schema for the `users` table:\n\n {\n "name": <type \'str\'>\n "places_visited": [<type \'str\'>]\n }\n\nRetrieve all users whose field `places_visited` contains `France`.\n\n r.table("users").filter(lambda user:\n user["places_visited"].contains("France")\n ).run(conn)\n\n*Example* Filter based on nested fields.\n\nGiven this schema for the `users` table:\n\n {\n "id": <type \'str\'>\n "name": {\n "first": <type \'str\'>,\n "middle": <type \'str\'>,\n "last": <type \'str\'>\n }\n }\n\nRetrieve all users named "William Adama" (first name "William", last name\n"Adama"), with any middle name.\n\n r.table("users").filter({\n "name": {\n "first": "William",\n "last": "Adama"\n }\n }).run(conn)\n\nIf you want an exact match for a field that is an object, you will have to use `r.literal`.\n\nRetrieve all users named "William Adama" (first name "William", last name\n"Adama"), and who do not have a middle name.\n\n r.table("users").filter(r.literal({\n "name": {\n "first": "William",\n "last": "Adama"\n }\n })).run(conn)\n\nYou may rewrite these with lambda functions.\n\n r.table("users").filter(\n lambda user:\n (user["name"]["first"] == "William")\n & (user["name"]["last"] == "Adama")\n ).run(conn)\n\n r.table("users").filter(lambda user:\n user["name"] == {\n "first": "William",\n "last": "Adama"\n }\n ).run(conn)\n\nBy default, documents missing fields tested by the `filter` predicate are skipped. In the previous examples, users without an `age` field are not returned. By passing the optional `default` argument to `filter`, you can change this behavior.\n\n*Example* Get all users less than 18 years old or whose `age` field is missing.\n\n r.table("users").filter(r.row["age"] < 18, default=True).run(conn)\n\n*Example* Get all users more than 18 years old. Throw an error if a\ndocument is missing the field `age`.\n\n r.table("users").filter(r.row["age"] > 18, default=r.error()).run(conn)\n\n*Example* Get all users who have given their phone number (all the documents whose field `phone_number` exists and is not `None`).\n\n r.table(\'users\').filter(\n lambda user: user.has_fields(\'phone_number\')\n ).run(conn)\n\n*Example* Get all users with an "editor" role or an "admin" privilege.\n\n r.table(\'users\').filter(\n lambda user: (user[\'role\'] == \'editor\').default(False) |\n (user[\'privilege\'] == \'admin\').default(False)\n ).run(conn)\n\nInstead of using the `default` optional argument to `filter`, we have to use default values on the fields within the `or` clause. Why? If the field on the left side of the `or` clause is missing from a document&mdash;in this case, if the user doesn\'t have a `role` field&mdash;the predicate will generate an error, and will return `False` (or the value the `default` argument is set to) without evaluating the right side of the `or`. By using `.default(False)` on the fields, each side of the `or` will evaluate to either the field\'s value or `False` if the field doesn\'t exist.\n'),
+ (rethinkdb.ast.Table.get, b"table.get(key) -> singleRowSelection\n\nGet a document by primary key.\n\nIf no document exists with that primary key, `get` will return `None`.\n\n*Example* Find a document by UUID.\n\n r.table('posts').get('a9849eef-7176-4411-935b-79a6e3c56a74').run(conn)\n\n*Example* Find a document and merge another document with it.\n\n r.table('heroes').get(3).merge(\n { 'powers': ['invisibility', 'speed'] }\n ).run(conn)\n\n_*Example* Subscribe to a document's [changefeed](http://rethinkdb.com/docs/changefeeds/python).\n\n changes = r.table('heroes').get(3).changes().run(conn)\n"),
+ (rethinkdb.ast.Table.get_all, b"table.get_all(key1[, key2...], [, index='id']) -> selection\n\nGet all documents where the given value matches the value of the requested index.\n\n*Example* Secondary index keys are not guaranteed to be unique so we cannot query via [get](http://rethinkdb.com/api/python/get/) when using a secondary index.\n\n r.table('marvel').get_all('man_of_steel', index='code_name').run(conn)\n\n*Example* Without an index argument, we default to the primary index. While `get` will either return the document or `None` when no document with such a primary key value exists, this will return either a one or zero length stream.\n\n r.table('dc').get_all('superman').run(conn)\n\n*Example* You can get multiple documents in a single call to `get_all`.\n\n r.table('dc').get_all('superman', 'ant man').run(conn)\n\n*Example* You can use [args](http://rethinkdb.com/api/python/args/) with `get_all` to retrieve multiple documents whose keys are in a list. This uses `get_all` to get a list of female superheroes, coerces that to an array, and then gets a list of villains who have those superheroes as enemies.\n\n r.do(\n r.table('heroes').get_all('f', {'index': 'gender'})['id'].coerce_to('array'), \n lamdba heroines: r.table('villains').get_all(r.args(heroines))\n ).run(conn)\n\nSecondary indexes can be used in extremely powerful ways with `get_all` and other commands; read the full article on [secondary indexes](http://rethinkdb.com/docs/secondary-indexes) for examples using boolean operations, `contains` and more.\n"),
+ (rethinkdb.ast.DB.table, b"db.table(name[, use_outdated=False, identifier_format='name']) -> table\n\nReturn all documents in a table. Other commands may be chained after `table` to return a subset of documents (such as `get` and `filter`) or perform further processing.\n\n*Example* Return all documents in the table 'marvel' of the default database.\n\n r.table('marvel').run(conn)\n\n*Example* Return all documents in the table 'marvel' of the database 'heroes'.\n\n r.db('heroes').table('marvel').run(conn)\n\nThere are two optional arguments.\n\n* `use_outdated`: if `True`, this allows potentially out-of-date data to be returned, with potentially faster reads. It also allows you to perform reads from a secondary replica if a primary has failed. Default `False`.\n* `identifier_format`: possible values are `name` and `uuid`, with a default of `name`. If set to `uuid`, then [system tables](http://rethinkdb.com/docs/system-tables/) will refer to servers, databases and tables by UUID rather than name. (This only has an effect when used with system tables.)\n\n*Example* Allow potentially out-of-date data in exchange for faster reads.\n\n r.db('heroes').table('marvel', use_outdated=True).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.downcase, b'string.downcase() -> string\n\nLowercases a string.\n\n*Example*\n\n > r.expr("Sentence about LaTeX.").downcase().run(conn)\n "sentence about latex."\n\n__Note:__ `upcase` and `downcase` only affect ASCII characters.\n'),
+ (rethinkdb.ast.RqlQuery.match, b'string.match(regexp) -> None/object\n\nMatches against a regular expression. If there is a match, returns an object with the fields:\n\n- `str`: The matched string\n- `start`: The matched string\'s start\n- `end`: The matched string\'s end\n- `groups`: The capture groups defined with parentheses\n\nIf no match is found, returns `None`.\n\nAccepts RE2 syntax\n([https://code.google.com/p/re2/wiki/Syntax](https://code.google.com/p/re2/wiki/Syntax)).\nYou can enable case-insensitive matching by prefixing the regular expression with\n`(?i)`. See the linked RE2 documentation for more flags.\n\nThe `match` command does not support backreferences.\n\n*Example* Get all users whose name starts with "A". Because `None` evaluates to `false` in\n`filter`, you can just use the result of `match` for the predicate.\n\n r.table(\'users\').filter(lambda doc:\n doc[\'name\'].match("^A")\n ).run(conn)\n\n*Example* Get all users whose name ends with "n".\n\n r.table(\'users\').filter(lambda doc:\n doc[\'name\'].match("n$")\n ).run(conn)\n\n*Example* Get all users whose name has "li" in it\n\n r.table(\'users\').filter(lambda doc:\n doc[\'name\'].match("li")\n ).run(conn)\n\n*Example* Get all users whose name is "John" with a case-insensitive search.\n\n r.table(\'users\').filter(lambda doc:\n doc[\'name\'].match("(?i)^john$")\n ).run(conn)\n\n*Example* Get all users whose name is composed of only characters between "a" and "z".\n\n r.table(\'users\').filter(lambda doc:\n doc[\'name\'].match("(?i)^[a-z]+$")\n ).run(conn)\n\n*Example* Get all users where the zipcode is a string of 5 digits.\n\n r.table(\'users\').filter(lambda doc:\n doc[\'zipcode\'].match("\\d{5}")\n ).run(conn)\n\n*Example* Retrieve the domain of a basic email\n\n r.expr("name@domain.com").match(".*@(.*)").run(conn)\n\nResult:\n\n {\n "start": 0,\n "end": 20,\n "str": "name@domain.com",\n "groups":[\n {\n "end": 17,\n "start": 7,\n "str": "domain.com"\n }\n ]\n }\n\nYou can then retrieve only the domain with the [\\[\\]](http://rethinkdb.com/api/python/get_field) selector.\n\n r.expr("name@domain.com").match(".*@(.*)")["groups"][0]["str"].run(conn)\n\nReturns `\'domain.com\'`\n\n*Example* Fail to parse out the domain and returns `None`.\n\n r.expr("name[at]domain.com").match(".*@(.*)").run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.split, b'string.split([separator, [max_splits]]) -> array\n\nSplits a string into substrings. Splits on whitespace when called\nwith no arguments. When called with a separator, splits on that\nseparator. When called with a separator and a maximum number of\nsplits, splits on that separator at most `max_splits` times. (Can be\ncalled with `None` as the separator if you want to split on whitespace\nwhile still specifying `max_splits`.)\n\nMimics the behavior of Python\'s `string.split` in edge cases, except\nfor splitting on the empty string, which instead produces an array of\nsingle-character strings.\n\n*Example* Split on whitespace.\n\n > r.expr("foo bar bax").split().run(conn)\n ["foo", "bar", "bax"]\n\n*Example* Split the entries in a CSV file.\n\n > r.expr("12,37,,22,").split(",").run(conn)\n ["12", "37", "", "22", ""]\n\n*Example* Split a string into characters.\n\n > r.expr("mlucy").split("").run(conn)\n ["m", "l", "u", "c", "y"]\n\n*Example* Split the entries in a CSV file, but only at most 3\ntimes.\n\n > r.expr("12,37,,22,").split(",", 3).run(conn)\n ["12", "37", "", "22,"]\n\n*Example* Split on whitespace at most once (i.e. get the first word).\n\n > r.expr("foo bar bax").split(None, 1).run(conn)\n ["foo", "bar bax"]\n'),
+ (rethinkdb.ast.RqlQuery.upcase, b'string.upcase() -> string\n\nUppercases a string.\n\n*Example*\n\n > r.expr("Sentence about LaTeX.").upcase().run(conn)\n "SENTENCE ABOUT LATEX."\n\n__Note:__ `upcase` and `downcase` only affect ASCII characters.\n'),
+ (rethinkdb.ast.RqlQuery.concat_map, b'stream.concat_map(mapping_function) -> stream\narray.concat_map(mapping_function) -> array\n\nConcatenate one or more elements into a single sequence using a mapping function.\n\n`concat_map` works in a similar fashion to `map`, applying the given function to each element in a sequence, but it will always return a single sequence. If the mapping function returns a sequence, `map` would produce a sequence of sequences:\n\n r.expr([1, 2, 3]).map(lambda x: [x, x.mul(2)]).run(conn)\n\nResult:\n\n [[1, 2], [2, 4], [3, 6]]\n\nWhereas `concat_map` with the same mapping function would merge those sequences into one:\n\n r.expr([1, 2, 3]).concat_map(lambda x: [x, x.mul(2)]).run(conn)\n\nResult:\n\n [1, 2, 2, 4, 3, 6]\n\nThe return value, array or stream, will be the same type as the input.\n\n*Example* Construct a sequence of all monsters defeated by Marvel heroes. The field "defeatedMonsters" is an array of one or more monster names.\n\n r.table(\'marvel\').concat_map(lambda hero: hero[\'defeatedMonsters\']).run(conn)\n\n*Example* Simulate an [eq_join](http://rethinkdb.com/api/python/eq_join/) using `concat_map`. (This is how ReQL joins are implemented internally.)\n\n r.table(\'posts\').concat_map(\n lambda post: r.table(\'comments\').get_all(\n post[\'id\'], index=\'post_id\'\n ).map(\n lambda comment: { \'left\': post, \'right\': comment}\n )\n ).run(conn)\n'),
+ (rethinkdb.ast.RqlQuery.is_empty, b"sequence.is_empty() -> bool\n\nTest if a sequence is empty.\n\n*Example* Are there any documents in the marvel table?\n\n r.table('marvel').is_empty().run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.limit, b"sequence.limit(n) -> stream\narray.limit(n) -> array\n\nEnd the sequence after the given number of elements.\n\n*Example* Only so many can fit in our Pantheon of heroes.\n\n r.table('marvel').order_by('belovedness').limit(10).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.map, b"sequence1.map([sequence2, ...], mapping_function) -> stream\narray1.map([sequence2, ...], mapping_function) -> array\nr.map(sequence1[, sequence2, ...], mapping_function) -> stream\nr.map(array1[, array2, ...], mapping_function) -> array\n\nTransform each element of one or more sequences by applying a mapping function to them. If `map` is run with two or more sequences, it will iterate for as many items as there are in the shortest sequence.\n\nNote that `map` can only be applied to sequences, not single values. If you wish to apply a function to a single value/selection (including an array), use the [do](http://rethinkdb.com/api/python/do) command.\n\n*Example* Return the first five squares.\n\n > r.expr([1, 2, 3, 4, 5]).map(lambda val: (val * val)).run(conn)\n \n [1, 4, 9, 16, 25]\n\n*Example* Sum the elements of three sequences.\n\n > sequence1 = [100, 200, 300, 400]\n > sequence2 = [10, 20, 30, 40]\n > sequence3 = [1, 2, 3, 4]\n > r.map(sequence1, sequence2, sequence3,\n lambda val1, val2, val3: (val1 + val2 + val3)).run(conn)\n \n [111, 222, 333, 444]\n\n*Example* Rename a field when retrieving documents using `map` and `merge`.\n\nThis example renames the field `id` to `user_id` when retrieving documents from the table `users`.\n\n r.table('users').map(\n lambda doc: doc.merge({'user_id': doc['id']}).without('id')).run(conn)\n\nNote that in this case, [row](http://rethinkdb.com/api/python/row) may be used as an alternative to writing an anonymous function, as it returns the same value as the function parameter receives:\n\n r.table('users').map(\n r.row.merge({'user_id': r.row['id']}).without('id')).run(conn)\n\n*Example* Assign every superhero an archenemy.\n\n r.table('heroes').map(r.table('villains'),\n lambda hero, villain: hero.merge({'villain': villain})).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.nth, b"sequence.nth(index) -> object\nselection.nth(index) -> selection&lt;object&gt;\n\nGet the *nth* element of a sequence, counting from zero. If the argument is negative, count from the last element.\n\nIn Python, you can use `[]` with an integer as a shorthand for `nth`.\n\n*Example* Select the second element in the array.\n\n r.expr([1,2,3]).nth(1).run(conn)\n r.expr([1,2,3])[1].run(conn)\n\n*Example* Select the bronze medalist from the competitors.\n\n r.table('players').order_by(index=r.desc('score')).nth(3).run(conn)\n\n*Example* Select the last place competitor.\n\n r.table('players').order_by(index=r.desc('score')).nth(-1).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.offsets_of, b"sequence.offsets_of(datum | predicate) -> array\n\nGet the indexes of an element in a sequence. If the argument is a predicate, get the indexes of all elements matching it.\n\n*Example* Find the position of the letter 'c'.\n\n r.expr(['a','b','c']).offsets_of('c').run(conn)\n\n*Example* Find the popularity ranking of invisible heroes.\n\n r.table('marvel').union(r.table('dc')).order_by('popularity').offsets_of(\n r.row['superpowers'].contains('invisibility')\n ).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.order_by, b'table.order_by([key1...], index=index_name) -> selection<stream>\nselection.order_by(key1, [key2...]) -> selection<array>\nsequence.order_by(key1, [key2...]) -> array\n\nSort the sequence by document values of the given key(s). To specify\nthe ordering, wrap the attribute with either `r.asc` or `r.desc`\n(defaults to ascending).\n\n__Note:__ RethinkDB uses byte-wise ordering for `orderBy` and does not support Unicode collations; non-ASCII characters will be sorted by UTF-8 codepoint. For more information on RethinkDB\'s sorting order, read the section in [ReQL data types](http://rethinkdb.com/docs/data-types/#sorting-order).\n\nSorting without an index requires the server to hold the sequence in\nmemory, and is limited to 100,000 documents (or the setting of the `arrayLimit` option for [run](http://rethinkdb.com/api/python/run)). Sorting with an index can\nbe done on arbitrarily large tables, or after a `between` command\nusing the same index.\n\n*Example* Order all the posts using the index `date`. \n\n r.table(\'posts\').order_by(index=\'date\').run(conn)\n\nThe index must either be the primary key or have been previously created with [index_create](http://rethinkdb.com/api/python/index_create/).\n\n r.table(\'posts\').index_create(\'date\').run(conn)\n\nYou can also select a descending ordering:\n\n r.table(\'posts\').order_by(index=r.desc(\'date\')).run(conn, callback)\n\n*Example* Order a sequence without an index.\n\n r.table(\'posts\').get(1)[\'comments\'].order_by(\'date\')\n\nYou can also select a descending ordering:\n\n r.table(\'posts\').get(1)[\'comments\'].order_by(r.desc(\'date\'))\n\nIf you\'re doing ad-hoc analysis and know your table won\'t have more then 100,000\nelements (or you\'ve changed the setting of the `arrayLimit` option for [run](http://rethinkdb.com/api/python/run)) you can run `order_by` without an index:\n\n r.table(\'small_table\').order_by(\'date\')\n\n*Example* You can efficiently order using multiple fields by using a\n[compound index](http://www.rethinkdb.com/docs/secondary-indexes/python/).\n\nOrder by date and title.\n\n r.table(\'posts\').order_by(index=\'date_and_title\').run(conn)\n\nThe index must have been previously created with [index_create](http://rethinkdb.com/api/python/index_create/).\n\n r.table(\'posts\').index_create(\'date_and_title\', lambda post:\n [post["date"], post["title"]]).run(conn)\n\n_Note_: You cannot specify multiple orders in a compound index. See [issue #2306](https://github.com/rethinkdb/rethinkdb/issues/2306)\nto track progress.\n\n*Example* If you have a sequence with fewer documents than the `array_limit`, you can order it\nby multiple fields without an index.\n\n r.table(\'small_table\').order_by(\'date\', r.desc(\'title\'))\n\n*Example* Notice that an index ordering always has highest\nprecedence. The following query orders posts by date, and if multiple\nposts were published on the same date, they will be ordered by title.\n\n r.table(\'post\').order_by(\'title\', index=\'date\').run(conn)\n*Example* You can use [nested field](http://rethinkdb.com/docs/cookbook/python/#filtering-based-on-nested-fields) syntax to sort on fields from subdocuments. (You can also create indexes on nested fields using this syntax with `index_create`.)\n\n r.table(\'user\').order_by(lambda user: user[\'group\'][\'id\']).run(conn)\n\n*Example* You can efficiently order data on arbitrary expressions using indexes.\n\n r.table(\'posts\').order_by(index=\'votes\').run(conn)\n\nThe index must have been previously created with [index_create](http://rethinkdb.com/api/ruby/index_create/).\n\n r.table(\'posts\').index_create(\'votes\', lambda post:\n post["upvotes"]-post["downvotes"]\n ).run(conn)\n\n*Example* If you have a sequence with fewer documents than the `array_limit`, you can order it with an arbitrary function directly.\n\n r.table(\'small_table\').order_by(lambda doc:\n doc[\'upvotes\']-doc[\'downvotes\']\n );\n\nYou can also select a descending ordering:\n\n r.table(\'small_table\').order_by(r.desc(lambda doc:\n doc[\'upvotes\']-doc[\'downvotes\']\n ));\n\n*Example* Ordering after a `between` command can be done as long as the same index is being used.\n\n r.table("posts").between(r.time(2013, 1, 1, \'+00:00\'), r.time(2013, 1, 1, \'+00:00\'), index=\'date\')\n .order_by(index=\'date\').run(conn);\n\n'),
+ (rethinkdb.ast.RqlQuery.sample, b"sequence.sample(number) -> selection\nstream.sample(number) -> array\narray.sample(number) -> array\n\nSelect a given number of elements from a sequence with uniform random distribution. Selection is done without replacement.\n\nIf the sequence has less than the requested number of elements (i.e., calling `sample(10)` on a sequence with only five elements), `sample` will return the entire sequence in a random order.\n\n*Example* Select 3 random heroes.\n\n r.table('marvel').sample(3).run(conn)\n"),
+ (rethinkdb.ast.RqlQuery.skip, b"sequence.skip(n) -> stream\narray.skip(n) -> array\n\nSkip a number of elements from the head of the sequence.\n\n*Example* Here in conjunction with `order_by` we choose to ignore the most successful heroes.\n\n r.table('marvel').order_by('successMetric').skip(10).run(conn)\n\n"),
+ (rethinkdb.ast.RqlQuery.slice, b"selection.slice(start_index[, end_index, left_bound='closed', right_bound='open']) -> selection\nstream.slice(start_index[, end_index, left_bound='closed', right_bound='open']) -> stream\narray.slice(start_index[, end_index, left_bound='closed', right_bound='open']) -> array\nbinary.slice(start_index[, end_index, left_bound='closed', right_bound='open']) -> binary\n\nReturn the elements of a sequence within the specified range.\n\n`slice` returns the range between `start_index` and `end_index`. If only `start_index` is specified, `slice` returns the range from that index to the end of the sequence. Specify `left_bound` or `right_bound` as `open` or `closed` to indicate whether to include that endpoint of the range by default: `closed` returns that endpoint, while `open` does not. By default, `left_bound` is closed and `right_bound` is open, so the range `(10,13)` will return the tenth, eleventh and twelfth elements in the sequence.\n\nIf `end_index` is past the end of the sequence, all elements from `start_index` to the end of the sequence will be returned. If `start_index` is past the end of the sequence or `end_index` is less than `start_index`, a zero-element sequence will be returned (although see below for negative `end_index` values). An error will be raised on a negative `start_index`.\n\nA negative `end_index` is allowed with arrays; in that case, the returned range counts backward from the array's end. That is, the range of `(2,-1)` returns the second element through the next-to-last element of the range. A negative `end_index` is not allowed with a stream. (An `end_index` of &minus;1 *is* allowed with a stream if `right_bound` is closed; this behaves as if no `end_index` was specified.)\n\nIf `slice` is used with a [binary](http://rethinkdb.com/api/python/binary) object, the indexes refer to byte positions within the object. That is, the range `(10,20)` will refer to the 10th byte through the 19th byte.\n\nIf you are only specifying the indexes and not the bounding options, you may use Python's slice operator as a shorthand: `[start_index:end_index]`.\n\n**Example:** Return the fourth, fifth and sixth youngest players. (The youngest player is at index 0, so those are elements 3&ndash;5.)\n\n r.table('players').order_by(index='age').slice(3,6).run(conn)\n\nOr, using Python's slice operator:\n\n r.table('players').filter({'class': 'amateur'})[10:20].run(conn)\n\n**Example:** Return all but the top three players who have a red flag.\n\n r.table('players').filter({'flag': 'red'}).order_by(index=r.desc('score')).slice(3).run(conn)\n\n**Example:** Return holders of tickets `X` through `Y`, assuming tickets are numbered sequentially. We want to include ticket `Y`.\n\n r.table('users').order_by(index='ticket').slice(x, y, right_bound='closed').run(conn)\n\n**Example:** Return the elements of an array from the second through two from the end (that is, not including the last two).\n\n r.expr([0,1,2,3,4,5]).slice(2,-2).run(conn)\n\nResult:\n\n [2,3]\n"),
+ (rethinkdb.ast.RqlQuery.union, b"stream.union(sequence[, sequence, ...]) -> stream\narray.union(sequence[, sequence, ...]) -> array\n\nConcatenate two or more sequences.\n\n*Example* Construct a stream of all heroes.\n\n r.table('marvel').union(r.table('dc')).run(conn)\n\n*Example* Combine four arrays into one.\n\n r.expr([1, 2]).union([3, 4], [5, 6], [7, 8, 9]).run(conn)\n \n [1, 2, 3, 4, 5, 6, 7, 8, 9]\n"),
+ (rethinkdb.ast.RqlQuery.with_fields, b"sequence.with_fields([selector1, selector2...]) -> stream\narray.with_fields([selector1, selector2...]) -> array\n\nPlucks one or more attributes from a sequence of objects, filtering out any objects in the sequence that do not have the specified fields. Functionally, this is identical to `has_fields` followed by `pluck` on a sequence.\n\n*Example* Get a list of users and their posts, excluding any users who have not made any posts.\n\nExisting table structure:\n\n [\n { 'id': 1, 'user': 'bob', 'email': 'bob@foo.com', 'posts': [ 1, 4, 5 ] },\n { 'id': 2, 'user': 'george', 'email': 'george@foo.com' },\n { 'id': 3, 'user': 'jane', 'email': 'jane@foo.com', 'posts': [ 2, 3, 6 ] }\n ]\n\nCommand and output:\n\n r.table('users').with_fields('id', 'user', 'posts').run(conn)\n \n [\n { 'id': 1, 'user': 'bob', 'posts': [ 1, 4, 5 ] },\n { 'id': 3, 'user': 'jane', 'posts': [ 2, 3, 6 ] }\n ]\n\n*Example* Use the [nested field syntax](http://rethinkdb.com/docs/nested-fields/) to get a list of users with cell phone numbers in their contacts.\n\n r.table('users').with_fields('id', 'user', {contact: {'phone': 'work'}).run(conn)\n"),
+ (rethinkdb.ast.Table.delete, b'table.delete([durability="hard", return_changes=False])\n -> object\nselection.delete([durability="hard", return_changes=False])\n -> object\nsingleSelection.delete([durability="hard", return_changes=False])\n -> object\n\nDelete one or more documents from a table.\n\nThe optional arguments are:\n\n- `durability`: possible values are `hard` and `soft`. This option will override the\ntable or query\'s durability setting (set in [run](http://rethinkdb.com/api/python/run/)). \nIn soft durability mode RethinkDB will acknowledge the write immediately after\nreceiving it, but before the write has been committed to disk.\n- `return_changes`:\n - `True`: return a `changes` array consisting of `old_val`/`new_val` objects describing the changes made, only including the documents actually updated.\n - `False`: do not return a `changes` array (the default).\n - `"always"`: behave as `True`, but include all documents the command tried to update whether or not the update was successful. (This was the behavior of `True` pre-2.0.)\n\nDelete returns an object that contains the following attributes:\n\n- `deleted`: the number of documents that were deleted.\n- `skipped`: the number of documents that were skipped. \nFor example, if you attempt to delete a batch of documents, and another concurrent query\ndeletes some of those documents first, they will be counted as skipped.\n- `errors`: the number of errors encountered while performing the delete.\n- `first_error`: If errors were encountered, contains the text of the first error.\n- `inserted`, `replaced`, and `unchanged`: all 0 for a delete operation.\n- `changes`: if `return_changes` is set to `True`, this will be an array of objects, one for each objected affected by the `delete` operation. Each object will have two keys: `{"new_val": None, "old_val": <old value>}`.\n\n*Example* Delete a single document from the table `comments`.\n\n r.table("comments").get("7eab9e63-73f1-4f33-8ce4-95cbea626f59").delete().run(conn)\n\n*Example* Delete all documents from the table `comments`.\n\n r.table("comments").delete().run(conn)\n\n*Example* Delete all comments where the field `id_post` is `3`.\n\n r.table("comments").filter({"id_post": 3}).delete().run(conn)\n\n*Example* Delete a single document from the table `comments` and return its value.\n\n r.table("comments").get("7eab9e63-73f1-4f33-8ce4-95cbea626f59").delete(return_changes=True).run(conn)\n\nThe result will look like:\n\n {\n "deleted": 1,\n "errors": 0,\n "inserted": 0,\n "changes": [\n {\n "new_val": None,\n "old_val": {\n "id": "7eab9e63-73f1-4f33-8ce4-95cbea626f59",\n "author": "William",\n "comment": "Great post",\n "id_post": 3\n }\n }\n ],\n "replaced": 0,\n "skipped": 0,\n "unchanged": 0\n }\n\n*Example* Delete all documents from the table `comments` without waiting for the\noperation to be flushed to disk.\n\n r.table("comments").delete(durability="soft"}).run(conn)\n'),
+ (rethinkdb.ast.Table.insert, b'table.insert(object | [object1, object2, ...][, durability="hard", return_changes=False, conflict="error"])\n -> object\n\nInsert documents into a table. Accepts a single document or an array of\ndocuments.\n\nThe optional arguments are:\n\n- `durability`: possible values are `hard` and `soft`. This option will override the table or query\'s durability setting (set in [run](http://rethinkdb.com/api/python/run/)). In soft durability mode RethinkDB will acknowledge the write immediately after receiving and caching it, but before the write has been committed to disk.\n- `return_changes`:\n - `True`: return a `changes` array consisting of `old_val`/`new_val` objects describing the changes made, only including the documents actually updated.\n - `False`: do not return a `changes` array (the default).\n - `"always"`: behave as `True`, but include all documents the command tried to update whether or not the update was successful. (This was the behavior of `True` pre-2.0.)\n- `conflict`: Determine handling of inserting documents with the same primary key as existing entries. Possible values are `"error"`, `"replace"` or `"update"`.\n - `"error"`: Do not insert the new document and record the conflict as an error. This is the default.\n - `"replace"`: [Replace](http://rethinkdb.com/api/python/replace/) the old document in its entirety with the new one.\n - `"update"`: [Update](http://rethinkdb.com/api/python/update/) fields of the old document with fields from the new one.\n\nInsert returns an object that contains the following attributes:\n\n- `inserted`: the number of documents successfully inserted.\n- `replaced`: the number of documents updated when `conflict` is set to `"replace"` or `"update"`.\n- `unchanged`: the number of documents whose fields are identical to existing documents with the same primary key when `conflict` is set to `"replace"` or `"update"`.\n- `errors`: the number of errors encountered while performing the insert.\n- `first_error`: If errors were encountered, contains the text of the first error.\n- `deleted` and `skipped`: 0 for an insert operation.\n- `generated_keys`: a list of generated primary keys for inserted documents whose primary keys were not specified (capped to 100,000).\n- `warnings`: if the field `generated_keys` is truncated, you will get the warning _"Too many generated keys (&lt;X&gt;), array truncated to 100000."_.\n- `changes`: if `return_changes` is set to `True`, this will be an array of objects, one for each objected affected by the `insert` operation. Each object will have two keys: `{"new_val": <new value>, "old_val": None}`.\n\n*Example* Insert a document into the table `posts`.\n\n r.table("posts").insert({\n "id": 1,\n "title": "Lorem ipsum",\n "content": "Dolor sit amet"\n }).run(conn)\n\nThe result will be:\n\n {\n "deleted": 0,\n "errors": 0,\n "inserted": 1,\n "replaced": 0,\n "skipped": 0,\n "unchanged": 0\n }\n\n*Example* Insert a document without a defined primary key into the table `posts` where the\nprimary key is `id`.\n\n r.table("posts").insert({\n "title": "Lorem ipsum",\n "content": "Dolor sit amet"\n }).run(conn)\n\nRethinkDB will generate a primary key and return it in `generated_keys`.\n\n {\n "deleted": 0,\n "errors": 0,\n "generated_keys": [\n "dd782b64-70a7-43e4-b65e-dd14ae61d947"\n ],\n "inserted": 1,\n "replaced": 0,\n "skipped": 0,\n "unchanged": 0\n }\n\nRetrieve the document you just inserted with:\n\n r.table("posts").get("dd782b64-70a7-43e4-b65e-dd14ae61d947").run(conn)\n\nAnd you will get back:\n\n {\n "id": "dd782b64-70a7-43e4-b65e-dd14ae61d947",\n "title": "Lorem ipsum",\n "content": "Dolor sit amet",\n }\n\n*Example* Insert multiple documents into the table `users`.\n\n r.table("users").insert([\n {"id": "william", "email": "william@rethinkdb.com"},\n {"id": "lara", "email": "lara@rethinkdb.com"}\n ]).run(conn)\n\n*Example* Insert a document into the table `users`, replacing the document if the document\nalready exists. \n\n r.table("users").insert(\n {"id": "william", "email": "william@rethinkdb.com"},\n conflict="error"\n ).run(conn)\n\n*Example* Copy the documents from `posts` to `posts_backup`.\n\n r.table("posts_backup").insert( r.table("posts") ).run(conn)\n\n*Example* Get back a copy of the inserted document (with its generated primary key).\n\n r.table("posts").insert(\n {"title": "Lorem ipsum", "content": "Dolor sit amet"},\n return_changes=True\n ).run(conn)\n\nThe result will be\n\n {\n "deleted": 0,\n "errors": 0,\n "generated_keys": [\n "dd782b64-70a7-43e4-b65e-dd14ae61d947"\n ],\n "inserted": 1,\n "replaced": 0,\n "skipped": 0,\n "unchanged": 0,\n "changes": [\n {\n "old_val": None,\n "new_val": {\n "id": "dd782b64-70a7-43e4-b65e-dd14ae61d947",\n "title": "Lorem ipsum",\n "content": "Dolor sit amet"\n }\n }\n ]\n }\n'),
+ (rethinkdb.ast.Table.replace, b'table.replace(object | expr[, durability="hard", return_changes=False, non_atomic=False])\n -> object\nselection.replace(object | expr[, durability="hard", return_changes=False, non_atomic=False])\n -> object\nsingleSelection.replace(object | expr[, durability="hard", return_changes=False, non_atomic=False])\n -> object\n\nReplace documents in a table. Accepts a JSON document or a ReQL expression, and replaces\nthe original document with the new one. The new document must have the same primary key\nas the original document.\n\nThe optional arguments are:\n\n- `durability`: possible values are `hard` and `soft`. This option will override the\ntable or query\'s durability setting (set in [run](http://rethinkdb.com/api/python/run/)). \nIn soft durability mode RethinkDB will acknowledge the write immediately after\nreceiving it, but before the write has been committed to disk.\n- `return_changes`:\n - `True`: return a `changes` array consisting of `old_val`/`new_val` objects describing the changes made, only including the documents actually updated.\n - `False`: do not return a `changes` array (the default).\n - `"always"`: behave as `True`, but include all documents the command tried to update whether or not the update was successful. (This was the behavior of `True` pre-2.0.)\n- `non_atomic`: if set to `True`, executes the replacement and distributes the result to replicas in a non-atomic fashion. This flag is required to perform non-deterministic updates, such as those that require reading data from another table.\n\nReplace returns an object that contains the following attributes:\n\n- `replaced`: the number of documents that were replaced\n- `unchanged`: the number of documents that would have been modified, except that the\nnew value was the same as the old value\n- `inserted`: the number of new documents added. You can have new documents inserted if\nyou do a point-replace on a key that isn\'t in the table or you do a replace on a\nselection and one of the documents you are replacing has been deleted\n- `deleted`: the number of deleted documents when doing a replace with `None`\n- `errors`: the number of errors encountered while performing the replace.\n- `first_error`: If errors were encountered, contains the text of the first error.\n- `skipped`: 0 for a replace operation\n- `changes`: if `return_changes` is set to `True`, this will be an array of objects, one for each objected affected by the `replace` operation. Each object will have two keys: `{"new_val": <new value>, "old_val": <old value>}`.\n\n*Example* Replace the document with the primary key `1`.\n\n r.table("posts").get(1).replace({\n "id": 1,\n "title": "Lorem ipsum",\n "content": "Aleas jacta est",\n "status": "draft"\n }).run(conn)\n\n*Example* Remove the field `status` from all posts.\n\n r.table("posts").replace(lambda post:\n post.without("status")\n ).run(conn)\n\n*Example* Remove all the fields that are not `id`, `title` or `content`.\n\n r.table("posts").replace(lambda post:\n post.pluck("id", "title", "content")\n ).run(conn)\n\n*Example* Replace the document with the primary key `1` using soft durability.\n\n r.table("posts").get(1).replace({\n "id": 1,\n "title": "Lorem ipsum",\n "content": "Aleas jacta est",\n "status": "draft"\n }, durability="soft").run(conn)\n\n*Example* Replace the document with the primary key `1` and return the values of the document before\nand after the replace operation.\n\n r.table("posts").get(1).replace({\n "id": 1,\n "title": "Lorem ipsum",\n "content": "Aleas jacta est",\n "status": "published"\n }, return_changes=True).run(conn)\n\nThe result will have a `changes` field:\n\n {\n "deleted": 0,\n "errors": 0,\n "inserted": 0,\n "changes": [\n {\n "new_val": {\n "id":1,\n "title": "Lorem ipsum"\n "content": "Aleas jacta est",\n "status": "published",\n },\n "old_val": {\n "id":1,\n "title": "Lorem ipsum"\n "content": "TODO",\n "status": "draft",\n "author": "William",\n }\n }\n ], \n "replaced": 1,\n "skipped": 0,\n "unchanged": 0\n }\n'),
+ (rethinkdb.ast.Table.sync, b'table.sync() -> object\n\n`sync` ensures that writes on a given table are written to permanent storage. Queries\nthat specify soft durability (`durability=\'soft\'`) do not give such guarantees, so\n`sync` can be used to ensure the state of these queries. A call to `sync` does not return\nuntil all previous writes to the table are persisted.\n\nIf successful, the operation returns an object: `{"synced": 1}`.\n\n*Example* After having updated multiple heroes with soft durability, we now want to wait\nuntil these changes are persisted.\n\n r.table(\'marvel\').sync().run(conn)\n\n'),
+ (rethinkdb.ast.Table.update, b'table.update(object | expr[, durability="hard", return_changes=False, non_atomic=False])\n -> object\nselection.update(object | expr[, durability="hard", return_changes=False, non_atomic=False])\n -> object\nsingleSelection.update(object | expr[, durability="hard", return_changes=False, non_atomic=False])\n -> object\n\nUpdate JSON documents in a table. Accepts a JSON document, a ReQL expression, or a combination of the two.\n\nThe optional arguments are:\n\n- `durability`: possible values are `hard` and `soft`. This option will override the table or query\'s durability setting (set in [run](http://rethinkdb.com/api/python/run/)). In soft durability mode RethinkDB will acknowledge the write immediately after receiving it, but before the write has been committed to disk.\n- `return_changes`:\n - `True`: return a `changes` array consisting of `old_val`/`new_val` objects describing the changes made, only including the documents actually updated.\n - `False`: do not return a `changes` array (the default).\n - `"always"`: behave as `True`, but include all documents the command tried to update whether or not the update was successful. (This was the behavior of `True` pre-2.0.)\n- `non_atomic`: if set to `True`, executes the update and distributes the result to replicas in a non-atomic fashion. This flag is required to perform non-deterministic updates, such as those that require reading data from another table.\n\nUpdate returns an object that contains the following attributes:\n\n- `replaced`: the number of documents that were updated.\n- `unchanged`: the number of documents that would have been modified except the new value was the same as the old value.\n- `skipped`: the number of documents that were skipped because the document didn\'t exist.\n- `errors`: the number of errors encountered while performing the update.\n- `first_error`: If errors were encountered, contains the text of the first error.\n- `deleted` and `inserted`: 0 for an update operation.\n- `changes`: if `return_changes` is set to `True`, this will be an array of objects, one for each objected affected by the `update` operation. Each object will have two keys: `{"new_val": <new value>, "old_val": <old value>}`.\n\n*Example* Update the status of the post with `id` of `1` to `published`.\n\n r.table("posts").get(1).update({"status": "published"}).run(conn)\n\n*Example* Update the status of all posts to `published`.\n\n r.table("posts").update({"status": "published"}).run(conn)\n\n*Example* Update the status of all the posts written by William.\n\n r.table("posts").filter({"author": "William"}).update({"status": "published"}).run(conn)\n\n*Example* Increment the field `view` with `id` of `1`.\nThis query will throw an error if the field `views` doesn\'t exist.\n\n r.table("posts").get(1).update({\n "views": r.row["views"]+1\n }).run(conn)\n\n*Example* Increment the field `view` of the post with `id` of `1`.\nIf the field `views` does not exist, it will be set to `0`.\n\n r.table("posts").update({\n "views": (r.row["views"]+1).default(0)\n }).run(conn)\n\n*Example* Perform a conditional update. \nIf the post has more than 100 views, set the `type` of a post to `hot`, else set it to `normal`.\n\n r.table("posts").get(1).update(lambda post:\n r.branch(\n post["views"] > 100,\n {"type": "hot"},\n {"type": "normal"}\n )\n ).run(conn)\n\n*Example* Update the field `num_comments` with the result of a sub-query. Because this update is not atomic, you must pass the `non_atomic` flag.\n\n r.table("posts").get(1).update({\n "num_comments": r.table("comments").filter({"id_post": 1}).count()\n }, non_atomic=True).run(conn)\n\nIf you forget to specify the `non_atomic` flag, you will get a `RqlRuntimeError`:\n\nRqlRuntimeError: Could not prove function deterministic. Maybe you want to use the non_atomic flag? \n\n*Example* Update the field `num_comments` with a random value between 0 and 100. This update cannot be proven deterministic because of `r.js` (and in fact is not), so you must pass the `non_atomic` flag.\n\n r.table("posts").get(1).update({\n "num_comments": r.js("Math.floor(Math.random()*100)")\n }, non_atomic=True).run(conn)\n\n*Example* Update the status of the post with `id` of `1` using soft durability.\n\n r.table("posts").get(1).update({status: "published"}, durability="soft").run(conn)\n\n*Example* Increment the field `views` and return the values of the document before and after the update operation.\n\n r.table("posts").get(1).update({\n "views": r.row["views"]+1\n }, return_changes=True).run(conn)\n\nThe result will now include a `changes` field:\n\n {\n "deleted": 1,\n "errors": 0,\n "inserted": 0,\n "changes": [\n {\n "new_val": {\n "id": 1,\n "author": "Julius_Caesar",\n "title": "Commentarii de Bello Gallico",\n "content": "Aleas jacta est",\n "views": 207\n },\n "old_val": {\n "id": 1,\n "author": "Julius_Caesar",\n "title": "Commentarii de Bello Gallico",\n "content": "Aleas jacta est",\n "views": 206\n }\n }\n ],\n "replaced": 0,\n "skipped": 0,\n "unchanged": 0\n }\n\nThe `update` command supports RethinkDB\'s [nested field][nf] syntax to update subdocuments. Consider a user table with contact information in this format:\n\n[nf]: /docs/nested-fields/python\n\n {\n "id": 10001,\n "name": "Bob Smith",\n "contact": {\n "phone": {\n "work": "408-555-1212",\n "home": "408-555-1213",\n "cell": "408-555-1214"\n },\n "email": {\n "work": "bob@smith.com",\n "home": "bobsmith@example.com",\n "other": "bobbys@moosecall.net"\n },\n "im": {\n "skype": "Bob Smith",\n "aim": "bobmoose",\n "icq": "nobodyremembersicqnumbers"\n }\n },\n "notes": [\n {\n "date": r.time(2014,1,1,\'Z\'),\n "from": "John Doe",\n "subject": "My name is even more boring than Bob\'s"\n },\n {\n "date": r.time(2014,2,2,\'Z\'),\n "from": "Bob Smith Sr",\n "subject": "Happy Second of February"\n }\n ]\n }\n\n*Example* Update Bob Smith\'s cell phone number.\n\n r.table("users").get(10001).update(\n {"contact": {"phone": {"cell": "408-555-4242"}}}\n ).run(conn)\n\n*Example* Add another note to Bob Smith\'s record.\n\n new_note = {\n "date": r.now(),\n "from": "Inigo Montoya",\n "subject": "You killed my father"\n }\n r.table("users").get(10001).update(\n {"notes": r.row["notes"].append(new_note)}\n ).run(conn)\n\n*Example* Send a note to every user with an ICQ number.\n\n icq_note = {\n "date": r.now(),\n "from": "Admin",\n "subject": "Welcome to the future"\n }\n r.table("users").filter(\n r.row.has_fields({"contact": {"im": "icq"}})\n ).update(\n {"notes": r.row["notes"].append(icq_note)}\n ).run(conn)\n\n*Example* Replace all of Bob\'s IM records. Normally, `update` will merge nested documents together; to replace the entire `"im"` document, use the [literal][] command.\n\n[literal]: /api/python/literal/\n\n r.table(\'users\').get(10001).update(\n {"contact": {"im": r.literal({"aim": "themoosemeister"})}}\n ).run(conn)\n'),
+]
+
+for function, text in docsSource:
+ try:
+ text = str(text.decode('utf-8'))
+ except UnicodeEncodeError:
+ pass
+ if hasattr(function, "__func__"):
+ function.__func__.__doc__ = text
+ else:
+ function.__doc__ = text
diff --git a/ext/librethinkdbxx/reql/ql2.proto b/ext/librethinkdbxx/reql/ql2.proto
new file mode 100644
index 00000000..e40c5be5
--- /dev/null
+++ b/ext/librethinkdbxx/reql/ql2.proto
@@ -0,0 +1,843 @@
+////////////////////////////////////////////////////////////////////////////////
+// THE HIGH-LEVEL VIEW //
+////////////////////////////////////////////////////////////////////////////////
+
+// Process: When you first open a connection, send the magic number
+// for the version of the protobuf you're targeting (in the [Version]
+// enum). This should **NOT** be sent as a protobuf; just send the
+// little-endian 32-bit integer over the wire raw. This number should
+// only be sent once per connection.
+
+// The magic number shall be followed by an authorization key. The
+// first 4 bytes are the length of the key to be sent as a little-endian
+// 32-bit integer, followed by the key string. Even if there is no key,
+// an empty string should be sent (length 0 and no data).
+
+// Following the authorization key, the client shall send a magic number
+// for the communication protocol they want to use (in the [Protocol]
+// enum). This shall be a little-endian 32-bit integer.
+
+// The server will then respond with a NULL-terminated string response.
+// "SUCCESS" indicates that the connection has been accepted. Any other
+// response indicates an error, and the response string should describe
+// the error.
+
+// Next, for each query you want to send, construct a [Query] protobuf
+// and serialize it to a binary blob. Send the blob's size to the
+// server encoded as a little-endian 32-bit integer, followed by the
+// blob itself. You will recieve a [Response] protobuf back preceded
+// by its own size, once again encoded as a little-endian 32-bit
+// integer. You can see an example exchange below in **EXAMPLE**.
+
+// A query consists of a [Term] to evaluate and a unique-per-connection
+// [token].
+
+// Tokens are used for two things:
+// * Keeping track of which responses correspond to which queries.
+// * Batched queries. Some queries return lots of results, so we send back
+// batches of <1000, and you need to send a [CONTINUE] query with the same
+// token to get more results from the original query.
+////////////////////////////////////////////////////////////////////////////////
+
+message VersionDummy { // We need to wrap it like this for some
+ // non-conforming protobuf libraries
+ // This enum contains the magic numbers for your version. See **THE HIGH-LEVEL
+ // VIEW** for what to do with it.
+ enum Version {
+ V0_1 = 0x3f61ba36;
+ V0_2 = 0x723081e1; // Authorization key during handshake
+ V0_3 = 0x5f75e83e; // Authorization key and protocol during handshake
+ V0_4 = 0x400c2d20; // Queries execute in parallel
+ V1_0 = 0x34c2bdc3; // Users and permissions
+ }
+
+ // The protocol to use after the handshake, specified in V0_3
+ enum Protocol {
+ PROTOBUF = 0x271ffc41;
+ JSON = 0x7e6970c7;
+ }
+}
+
+// You send one of:
+// * A [START] query with a [Term] to evaluate and a unique-per-connection token.
+// * A [CONTINUE] query with the same token as a [START] query that returned
+// [SUCCESS_PARTIAL] in its [Response].
+// * A [STOP] query with the same token as a [START] query that you want to stop.
+// * A [NOREPLY_WAIT] query with a unique per-connection token. The server answers
+// with a [WAIT_COMPLETE] [Response].
+// * A [SERVER_INFO] query. The server answers with a [SERVER_INFO] [Response].
+message Query {
+ enum QueryType {
+ START = 1; // Start a new query.
+ CONTINUE = 2; // Continue a query that returned [SUCCESS_PARTIAL]
+ // (see [Response]).
+ STOP = 3; // Stop a query partway through executing.
+ NOREPLY_WAIT = 4; // Wait for noreply operations to finish.
+ SERVER_INFO = 5; // Get server information.
+ }
+ optional QueryType type = 1;
+ // A [Term] is how we represent the operations we want a query to perform.
+ optional Term query = 2; // only present when [type] = [START]
+ optional int64 token = 3;
+ // This flag is ignored on the server. `noreply` should be added
+ // to `global_optargs` instead (the key "noreply" should map to
+ // either true or false).
+ optional bool OBSOLETE_noreply = 4 [default = false];
+
+ // If this is set to [true], then [Datum] values will sometimes be
+ // of [DatumType] [R_JSON] (see below). This can provide enormous
+ // speedups in languages with poor protobuf libraries.
+ optional bool accepts_r_json = 5 [default = false];
+
+ message AssocPair {
+ optional string key = 1;
+ optional Term val = 2;
+ }
+ repeated AssocPair global_optargs = 6;
+}
+
+// A backtrace frame (see `backtrace` in Response below)
+message Frame {
+ enum FrameType {
+ POS = 1; // Error occurred in a positional argument.
+ OPT = 2; // Error occurred in an optional argument.
+ }
+ optional FrameType type = 1;
+ optional int64 pos = 2; // The index of the positional argument.
+ optional string opt = 3; // The name of the optional argument.
+}
+message Backtrace {
+ repeated Frame frames = 1;
+}
+
+// You get back a response with the same [token] as your query.
+message Response {
+ enum ResponseType {
+ // These response types indicate success.
+ SUCCESS_ATOM = 1; // Query returned a single RQL datatype.
+ SUCCESS_SEQUENCE = 2; // Query returned a sequence of RQL datatypes.
+ SUCCESS_PARTIAL = 3; // Query returned a partial sequence of RQL
+ // datatypes. If you send a [CONTINUE] query with
+ // the same token as this response, you will get
+ // more of the sequence. Keep sending [CONTINUE]
+ // queries until you get back [SUCCESS_SEQUENCE].
+ WAIT_COMPLETE = 4; // A [NOREPLY_WAIT] query completed.
+ SERVER_INFO = 5; // The data for a [SERVER_INFO] request. This is
+ // the same as `SUCCESS_ATOM` except that there will
+ // never be profiling data.
+
+ // These response types indicate failure.
+ CLIENT_ERROR = 16; // Means the client is buggy. An example is if the
+ // client sends a malformed protobuf, or tries to
+ // send [CONTINUE] for an unknown token.
+ COMPILE_ERROR = 17; // Means the query failed during parsing or type
+ // checking. For example, if you pass too many
+ // arguments to a function.
+ RUNTIME_ERROR = 18; // Means the query failed at runtime. An example is
+ // if you add together two values from a table, but
+ // they turn out at runtime to be booleans rather
+ // than numbers.
+ }
+ optional ResponseType type = 1;
+
+ // If `ResponseType` is `RUNTIME_ERROR`, this may be filled in with more
+ // information about the error.
+ enum ErrorType {
+ INTERNAL = 1000000;
+ RESOURCE_LIMIT = 2000000;
+ QUERY_LOGIC = 3000000;
+ NON_EXISTENCE = 3100000;
+ OP_FAILED = 4100000;
+ OP_INDETERMINATE = 4200000;
+ USER = 5000000;
+ PERMISSION_ERROR = 6000000;
+ }
+ optional ErrorType error_type = 7;
+
+ // ResponseNotes are used to provide information about the query
+ // response that may be useful for people writing drivers or ORMs.
+ // Currently all the notes we send indicate that a stream has certain
+ // special properties.
+ enum ResponseNote {
+ // The stream is a changefeed stream (e.g. `r.table('test').changes()`).
+ SEQUENCE_FEED = 1;
+ // The stream is a point changefeed stream
+ // (e.g. `r.table('test').get(0).changes()`).
+ ATOM_FEED = 2;
+ // The stream is an order_by_limit changefeed stream
+ // (e.g. `r.table('test').order_by(index: 'id').limit(5).changes()`).
+ ORDER_BY_LIMIT_FEED = 3;
+ // The stream is a union of multiple changefeed types that can't be
+ // collapsed to a single type
+ // (e.g. `r.table('test').changes().union(r.table('test').get(0).changes())`).
+ UNIONED_FEED = 4;
+ // The stream is a changefeed stream and includes notes on what state
+ // the changefeed stream is in (e.g. objects of the form `{state:
+ // 'initializing'}`).
+ INCLUDES_STATES = 5;
+ }
+ repeated ResponseNote notes = 6;
+
+ optional int64 token = 2; // Indicates what [Query] this response corresponds to.
+
+ // [response] contains 1 RQL datum if [type] is [SUCCESS_ATOM] or
+ // [SERVER_INFO]. [response] contains many RQL data if [type] is
+ // [SUCCESS_SEQUENCE] or [SUCCESS_PARTIAL]. [response] contains 1
+ // error message (of type [R_STR]) in all other cases.
+ repeated Datum response = 3;
+
+ // If [type] is [CLIENT_ERROR], [TYPE_ERROR], or [RUNTIME_ERROR], then a
+ // backtrace will be provided. The backtrace says where in the query the
+ // error occurred. Ideally this information will be presented to the user as
+ // a pretty-printed version of their query with the erroneous section
+ // underlined. A backtrace is a series of 0 or more [Frame]s, each of which
+ // specifies either the index of a positional argument or the name of an
+ // optional argument. (Those words will make more sense if you look at the
+ // [Term] message below.)
+ optional Backtrace backtrace = 4; // Contains n [Frame]s when you get back an error.
+
+ // If the [global_optargs] in the [Query] that this [Response] is a
+ // response to contains a key "profile" which maps to a static value of
+ // true then [profile] will contain a [Datum] which provides profiling
+ // information about the execution of the query. This field should be
+ // returned to the user along with the result that would normally be
+ // returned (a datum or a cursor). In official drivers this is accomplished
+ // by putting them inside of an object with "value" mapping to the return
+ // value and "profile" mapping to the profile object.
+ optional Datum profile = 5;
+}
+
+// A [Datum] is a chunk of data that can be serialized to disk or returned to
+// the user in a Response. Currently we only support JSON types, but we may
+// support other types in the future (e.g., a date type or an integer type).
+message Datum {
+ enum DatumType {
+ R_NULL = 1;
+ R_BOOL = 2;
+ R_NUM = 3; // a double
+ R_STR = 4;
+ R_ARRAY = 5;
+ R_OBJECT = 6;
+ // This [DatumType] will only be used if [accepts_r_json] is
+ // set to [true] in [Query]. [r_str] will be filled with a
+ // JSON encoding of the [Datum].
+ R_JSON = 7; // uses r_str
+ }
+ optional DatumType type = 1;
+ optional bool r_bool = 2;
+ optional double r_num = 3;
+ optional string r_str = 4;
+
+ repeated Datum r_array = 5;
+ message AssocPair {
+ optional string key = 1;
+ optional Datum val = 2;
+ }
+ repeated AssocPair r_object = 6;
+}
+
+// A [Term] is either a piece of data (see **Datum** above), or an operator and
+// its operands. If you have a [Datum], it's stored in the member [datum]. If
+// you have an operator, its positional arguments are stored in [args] and its
+// optional arguments are stored in [optargs].
+//
+// A note about type signatures:
+// We use the following notation to denote types:
+// arg1_type, arg2_type, argrest_type... -> result_type
+// So, for example, if we have a function `avg` that takes any number of
+// arguments and averages them, we might write:
+// NUMBER... -> NUMBER
+// Or if we had a function that took one number modulo another:
+// NUMBER, NUMBER -> NUMBER
+// Or a function that takes a table and a primary key of any Datum type, then
+// retrieves the entry with that primary key:
+// Table, DATUM -> OBJECT
+// Some arguments must be provided as literal values (and not the results of sub
+// terms). These are marked with a `!`.
+// Optional arguments are specified within curly braces as argname `:` value
+// type (e.x `{noreply:BOOL}`)
+// Many RQL operations are polymorphic. For these, alterantive type signatures
+// are separated by `|`.
+//
+// The RQL type hierarchy is as follows:
+// Top
+// DATUM
+// NULL
+// BOOL
+// NUMBER
+// STRING
+// OBJECT
+// SingleSelection
+// ARRAY
+// Sequence
+// ARRAY
+// Stream
+// StreamSelection
+// Table
+// Database
+// Function
+// Ordering - used only by ORDER_BY
+// Pathspec -- an object, string, or array that specifies a path
+// Error
+message Term {
+ enum TermType {
+ // A RQL datum, stored in `datum` below.
+ DATUM = 1;
+
+ MAKE_ARRAY = 2; // DATUM... -> ARRAY
+ // Evaluate the terms in [optargs] and make an object
+ MAKE_OBJ = 3; // {...} -> OBJECT
+
+ // * Compound types
+
+ // Takes an integer representing a variable and returns the value stored
+ // in that variable. It's the responsibility of the client to translate
+ // from their local representation of a variable to a unique _non-negative_
+ // integer for that variable. (We do it this way instead of letting
+ // clients provide variable names as strings to discourage
+ // variable-capturing client libraries, and because it's more efficient
+ // on the wire.)
+ VAR = 10; // !NUMBER -> DATUM
+ // Takes some javascript code and executes it.
+ JAVASCRIPT = 11; // STRING {timeout: !NUMBER} -> DATUM |
+ // STRING {timeout: !NUMBER} -> Function(*)
+ UUID = 169; // () -> DATUM
+
+ // Takes an HTTP URL and gets it. If the get succeeds and
+ // returns valid JSON, it is converted into a DATUM
+ HTTP = 153; // STRING {data: OBJECT | STRING,
+ // timeout: !NUMBER,
+ // method: STRING,
+ // params: OBJECT,
+ // header: OBJECT | ARRAY,
+ // attempts: NUMBER,
+ // redirects: NUMBER,
+ // verify: BOOL,
+ // page: FUNC | STRING,
+ // page_limit: NUMBER,
+ // auth: OBJECT,
+ // result_format: STRING,
+ // } -> STRING | STREAM
+
+ // Takes a string and throws an error with that message.
+ // Inside of a `default` block, you can omit the first
+ // argument to rethrow whatever error you catch (this is most
+ // useful as an argument to the `default` filter optarg).
+ ERROR = 12; // STRING -> Error | -> Error
+ // Takes nothing and returns a reference to the implicit variable.
+ IMPLICIT_VAR = 13; // -> DATUM
+
+ // * Data Operators
+ // Returns a reference to a database.
+ DB = 14; // STRING -> Database
+ // Returns a reference to a table.
+ TABLE = 15; // Database, STRING, {read_mode:STRING, identifier_format:STRING} -> Table
+ // STRING, {read_mode:STRING, identifier_format:STRING} -> Table
+ // Gets a single element from a table by its primary or a secondary key.
+ GET = 16; // Table, STRING -> SingleSelection | Table, NUMBER -> SingleSelection |
+ // Table, STRING -> NULL | Table, NUMBER -> NULL |
+ GET_ALL = 78; // Table, DATUM..., {index:!STRING} => ARRAY
+
+ // Simple DATUM Ops
+ EQ = 17; // DATUM... -> BOOL
+ NE = 18; // DATUM... -> BOOL
+ LT = 19; // DATUM... -> BOOL
+ LE = 20; // DATUM... -> BOOL
+ GT = 21; // DATUM... -> BOOL
+ GE = 22; // DATUM... -> BOOL
+ NOT = 23; // BOOL -> BOOL
+ // ADD can either add two numbers or concatenate two arrays.
+ ADD = 24; // NUMBER... -> NUMBER | STRING... -> STRING
+ SUB = 25; // NUMBER... -> NUMBER
+ MUL = 26; // NUMBER... -> NUMBER
+ DIV = 27; // NUMBER... -> NUMBER
+ MOD = 28; // NUMBER, NUMBER -> NUMBER
+
+ FLOOR = 183; // NUMBER -> NUMBER
+ CEIL = 184; // NUMBER -> NUMBER
+ ROUND = 185; // NUMBER -> NUMBER
+
+ // DATUM Array Ops
+ // Append a single element to the end of an array (like `snoc`).
+ APPEND = 29; // ARRAY, DATUM -> ARRAY
+ // Prepend a single element to the end of an array (like `cons`).
+ PREPEND = 80; // ARRAY, DATUM -> ARRAY
+ //Remove the elements of one array from another array.
+ DIFFERENCE = 95; // ARRAY, ARRAY -> ARRAY
+
+ // DATUM Set Ops
+ // Set ops work on arrays. They don't use actual sets and thus have
+ // performance characteristics you would expect from arrays rather than
+ // from sets. All set operations have the post condition that they
+ // array they return contains no duplicate values.
+ SET_INSERT = 88; // ARRAY, DATUM -> ARRAY
+ SET_INTERSECTION = 89; // ARRAY, ARRAY -> ARRAY
+ SET_UNION = 90; // ARRAY, ARRAY -> ARRAY
+ SET_DIFFERENCE = 91; // ARRAY, ARRAY -> ARRAY
+
+ SLICE = 30; // Sequence, NUMBER, NUMBER -> Sequence
+ SKIP = 70; // Sequence, NUMBER -> Sequence
+ LIMIT = 71; // Sequence, NUMBER -> Sequence
+ OFFSETS_OF = 87; // Sequence, DATUM -> Sequence | Sequence, Function(1) -> Sequence
+ CONTAINS = 93; // Sequence, (DATUM | Function(1))... -> BOOL
+
+ // Stream/Object Ops
+ // Get a particular field from an object, or map that over a
+ // sequence.
+ GET_FIELD = 31; // OBJECT, STRING -> DATUM
+ // | Sequence, STRING -> Sequence
+ // Return an array containing the keys of the object.
+ KEYS = 94; // OBJECT -> ARRAY
+ // Return an array containing the values of the object.
+ VALUES = 186; // OBJECT -> ARRAY
+ // Creates an object
+ OBJECT = 143; // STRING, DATUM, ... -> OBJECT
+ // Check whether an object contains all the specified fields,
+ // or filters a sequence so that all objects inside of it
+ // contain all the specified fields.
+ HAS_FIELDS = 32; // OBJECT, Pathspec... -> BOOL
+ // x.with_fields(...) <=> x.has_fields(...).pluck(...)
+ WITH_FIELDS = 96; // Sequence, Pathspec... -> Sequence
+ // Get a subset of an object by selecting some attributes to preserve,
+ // or map that over a sequence. (Both pick and pluck, polymorphic.)
+ PLUCK = 33; // Sequence, Pathspec... -> Sequence | OBJECT, Pathspec... -> OBJECT
+ // Get a subset of an object by selecting some attributes to discard, or
+ // map that over a sequence. (Both unpick and without, polymorphic.)
+ WITHOUT = 34; // Sequence, Pathspec... -> Sequence | OBJECT, Pathspec... -> OBJECT
+ // Merge objects (right-preferential)
+ MERGE = 35; // OBJECT... -> OBJECT | Sequence -> Sequence
+
+ // Sequence Ops
+ // Get all elements of a sequence between two values.
+ // Half-open by default, but the openness of either side can be
+ // changed by passing 'closed' or 'open for `right_bound` or
+ // `left_bound`.
+ BETWEEN_DEPRECATED = 36; // Deprecated version of between, which allows `null` to specify unboundedness
+ // With the newer version, clients should use `r.minval` and `r.maxval` for unboundedness
+ BETWEEN = 182; // StreamSelection, DATUM, DATUM, {index:!STRING, right_bound:STRING, left_bound:STRING} -> StreamSelection
+ REDUCE = 37; // Sequence, Function(2) -> DATUM
+ MAP = 38; // Sequence, Function(1) -> Sequence
+ // The arity of the function should be
+ // Sequence..., Function(sizeof...(Sequence)) -> Sequence
+
+ FOLD = 187; // Sequence, Datum, Function(2), {Function(3), Function(1)
+
+ // Filter a sequence with either a function or a shortcut
+ // object (see API docs for details). The body of FILTER is
+ // wrapped in an implicit `.default(false)`, and you can
+ // change the default value by specifying the `default`
+ // optarg. If you make the default `r.error`, all errors
+ // caught by `default` will be rethrown as if the `default`
+ // did not exist.
+ FILTER = 39; // Sequence, Function(1), {default:DATUM} -> Sequence |
+ // Sequence, OBJECT, {default:DATUM} -> Sequence
+ // Map a function over a sequence and then concatenate the results together.
+ CONCAT_MAP = 40; // Sequence, Function(1) -> Sequence
+ // Order a sequence based on one or more attributes.
+ ORDER_BY = 41; // Sequence, (!STRING | Ordering)..., {index: (!STRING | Ordering)} -> Sequence
+ // Get all distinct elements of a sequence (like `uniq`).
+ DISTINCT = 42; // Sequence -> Sequence
+ // Count the number of elements in a sequence, or only the elements that match
+ // a given filter.
+ COUNT = 43; // Sequence -> NUMBER | Sequence, DATUM -> NUMBER | Sequence, Function(1) -> NUMBER
+ IS_EMPTY = 86; // Sequence -> BOOL
+ // Take the union of multiple sequences (preserves duplicate elements! (use distinct)).
+ UNION = 44; // Sequence... -> Sequence
+ // Get the Nth element of a sequence.
+ NTH = 45; // Sequence, NUMBER -> DATUM
+ // do NTH or GET_FIELD depending on target object
+ BRACKET = 170; // Sequence | OBJECT, NUMBER | STRING -> DATUM
+ // OBSOLETE_GROUPED_MAPREDUCE = 46;
+ // OBSOLETE_GROUPBY = 47;
+
+ INNER_JOIN = 48; // Sequence, Sequence, Function(2) -> Sequence
+ OUTER_JOIN = 49; // Sequence, Sequence, Function(2) -> Sequence
+ // An inner-join that does an equality comparison on two attributes.
+ EQ_JOIN = 50; // Sequence, !STRING, Sequence, {index:!STRING} -> Sequence
+ ZIP = 72; // Sequence -> Sequence
+ RANGE = 173; // -> Sequence [0, +inf)
+ // NUMBER -> Sequence [0, a)
+ // NUMBER, NUMBER -> Sequence [a, b)
+
+ // Array Ops
+ // Insert an element in to an array at a given index.
+ INSERT_AT = 82; // ARRAY, NUMBER, DATUM -> ARRAY
+ // Remove an element at a given index from an array.
+ DELETE_AT = 83; // ARRAY, NUMBER -> ARRAY |
+ // ARRAY, NUMBER, NUMBER -> ARRAY
+ // Change the element at a given index of an array.
+ CHANGE_AT = 84; // ARRAY, NUMBER, DATUM -> ARRAY
+ // Splice one array in to another array.
+ SPLICE_AT = 85; // ARRAY, NUMBER, ARRAY -> ARRAY
+
+ // * Type Ops
+ // Coerces a datum to a named type (e.g. "bool").
+ // If you previously used `stream_to_array`, you should use this instead
+ // with the type "array".
+ COERCE_TO = 51; // Top, STRING -> Top
+ // Returns the named type of a datum (e.g. TYPE_OF(true) = "BOOL")
+ TYPE_OF = 52; // Top -> STRING
+
+ // * Write Ops (the OBJECTs contain data about number of errors etc.)
+ // Updates all the rows in a selection. Calls its Function with the row
+ // to be updated, and then merges the result of that call.
+ UPDATE = 53; // StreamSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT |
+ // SingleSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT |
+ // StreamSelection, OBJECT, {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT |
+ // SingleSelection, OBJECT, {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT
+ // Deletes all the rows in a selection.
+ DELETE = 54; // StreamSelection, {durability:STRING, return_changes:BOOL} -> OBJECT | SingleSelection -> OBJECT
+ // Replaces all the rows in a selection. Calls its Function with the row
+ // to be replaced, and then discards it and stores the result of that
+ // call.
+ REPLACE = 55; // StreamSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT | SingleSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT
+ // Inserts into a table. If `conflict` is replace, overwrites
+ // entries with the same primary key. If `conflict` is
+ // update, does an update on the entry. If `conflict` is
+ // error, or is omitted, conflicts will trigger an error.
+ INSERT = 56; // Table, OBJECT, {conflict:STRING, durability:STRING, return_changes:BOOL} -> OBJECT | Table, Sequence, {conflict:STRING, durability:STRING, return_changes:BOOL} -> OBJECT
+
+ // * Administrative OPs
+ // Creates a database with a particular name.
+ DB_CREATE = 57; // STRING -> OBJECT
+ // Drops a database with a particular name.
+ DB_DROP = 58; // STRING -> OBJECT
+ // Lists all the databases by name. (Takes no arguments)
+ DB_LIST = 59; // -> ARRAY
+ // Creates a table with a particular name in a particular
+ // database. (You may omit the first argument to use the
+ // default database.)
+ TABLE_CREATE = 60; // Database, STRING, {primary_key:STRING, shards:NUMBER, replicas:NUMBER, primary_replica_tag:STRING} -> OBJECT
+ // Database, STRING, {primary_key:STRING, shards:NUMBER, replicas:OBJECT, primary_replica_tag:STRING} -> OBJECT
+ // STRING, {primary_key:STRING, shards:NUMBER, replicas:NUMBER, primary_replica_tag:STRING} -> OBJECT
+ // STRING, {primary_key:STRING, shards:NUMBER, replicas:OBJECT, primary_replica_tag:STRING} -> OBJECT
+ // Drops a table with a particular name from a particular
+ // database. (You may omit the first argument to use the
+ // default database.)
+ TABLE_DROP = 61; // Database, STRING -> OBJECT
+ // STRING -> OBJECT
+ // Lists all the tables in a particular database. (You may
+ // omit the first argument to use the default database.)
+ TABLE_LIST = 62; // Database -> ARRAY
+ // -> ARRAY
+ // Returns the row in the `rethinkdb.table_config` or `rethinkdb.db_config` table
+ // that corresponds to the given database or table.
+ CONFIG = 174; // Database -> SingleSelection
+ // Table -> SingleSelection
+ // Returns the row in the `rethinkdb.table_status` table that corresponds to the
+ // given table.
+ STATUS = 175; // Table -> SingleSelection
+ // Called on a table, waits for that table to be ready for read/write operations.
+ // Called on a database, waits for all of the tables in the database to be ready.
+ // Returns the corresponding row or rows from the `rethinkdb.table_status` table.
+ WAIT = 177; // Table -> OBJECT
+ // Database -> OBJECT
+ // Generates a new config for the given table, or all tables in the given database
+ // The `shards` and `replicas` arguments are required. If `emergency_repair` is
+ // specified, it will enter a completely different mode of repairing a table
+ // which has lost half or more of its replicas.
+ RECONFIGURE = 176; // Database|Table, {shards:NUMBER, replicas:NUMBER [,
+ // dry_run:BOOLEAN]
+ // } -> OBJECT
+ // Database|Table, {shards:NUMBER, replicas:OBJECT [,
+ // primary_replica_tag:STRING,
+ // nonvoting_replica_tags:ARRAY,
+ // dry_run:BOOLEAN]
+ // } -> OBJECT
+ // Table, {emergency_repair:STRING, dry_run:BOOLEAN} -> OBJECT
+ // Balances the table's shards but leaves everything else the same. Can also be
+ // applied to an entire database at once.
+ REBALANCE = 179; // Table -> OBJECT
+ // Database -> OBJECT
+
+ // Ensures that previously issued soft-durability writes are complete and
+ // written to disk.
+ SYNC = 138; // Table -> OBJECT
+
+ // Set global, database, or table-specific permissions
+ GRANT = 188; // -> OBJECT
+ // Database -> OBJECT
+ // Table -> OBJECT
+
+ // * Secondary indexes OPs
+ // Creates a new secondary index with a particular name and definition.
+ INDEX_CREATE = 75; // Table, STRING, Function(1), {multi:BOOL} -> OBJECT
+ // Drops a secondary index with a particular name from the specified table.
+ INDEX_DROP = 76; // Table, STRING -> OBJECT
+ // Lists all secondary indexes on a particular table.
+ INDEX_LIST = 77; // Table -> ARRAY
+ // Gets information about whether or not a set of indexes are ready to
+ // be accessed. Returns a list of objects that look like this:
+ // {index:STRING, ready:BOOL[, progress:NUMBER]}
+ INDEX_STATUS = 139; // Table, STRING... -> ARRAY
+ // Blocks until a set of indexes are ready to be accessed. Returns the
+ // same values INDEX_STATUS.
+ INDEX_WAIT = 140; // Table, STRING... -> ARRAY
+ // Renames the given index to a new name
+ INDEX_RENAME = 156; // Table, STRING, STRING, {overwrite:BOOL} -> OBJECT
+
+ // * Control Operators
+ // Calls a function on data
+ FUNCALL = 64; // Function(*), DATUM... -> DATUM
+ // Executes its first argument, and returns its second argument if it
+ // got [true] or its third argument if it got [false] (like an `if`
+ // statement).
+ BRANCH = 65; // BOOL, Top, Top -> Top
+ // Returns true if any of its arguments returns true (short-circuits).
+ OR = 66; // BOOL... -> BOOL
+ // Returns true if all of its arguments return true (short-circuits).
+ AND = 67; // BOOL... -> BOOL
+ // Calls its Function with each entry in the sequence
+ // and executes the array of terms that Function returns.
+ FOR_EACH = 68; // Sequence, Function(1) -> OBJECT
+
+////////////////////////////////////////////////////////////////////////////////
+////////// Special Terms
+////////////////////////////////////////////////////////////////////////////////
+
+ // An anonymous function. Takes an array of numbers representing
+ // variables (see [VAR] above), and a [Term] to execute with those in
+ // scope. Returns a function that may be passed an array of arguments,
+ // then executes the Term with those bound to the variable names. The
+ // user will never construct this directly. We use it internally for
+ // things like `map` which take a function. The "arity" of a [Function] is
+ // the number of arguments it takes.
+ // For example, here's what `_X_.map{|x| x+2}` turns into:
+ // Term {
+ // type = MAP;
+ // args = [_X_,
+ // Term {
+ // type = Function;
+ // args = [Term {
+ // type = DATUM;
+ // datum = Datum {
+ // type = R_ARRAY;
+ // r_array = [Datum { type = R_NUM; r_num = 1; }];
+ // };
+ // },
+ // Term {
+ // type = ADD;
+ // args = [Term {
+ // type = VAR;
+ // args = [Term {
+ // type = DATUM;
+ // datum = Datum { type = R_NUM;
+ // r_num = 1};
+ // }];
+ // },
+ // Term {
+ // type = DATUM;
+ // datum = Datum { type = R_NUM; r_num = 2; };
+ // }];
+ // }];
+ // }];
+ FUNC = 69; // ARRAY, Top -> ARRAY -> Top
+
+ // Indicates to ORDER_BY that this attribute is to be sorted in ascending order.
+ ASC = 73; // !STRING -> Ordering
+ // Indicates to ORDER_BY that this attribute is to be sorted in descending order.
+ DESC = 74; // !STRING -> Ordering
+
+ // Gets info about anything. INFO is most commonly called on tables.
+ INFO = 79; // Top -> OBJECT
+
+ // `a.match(b)` returns a match object if the string `a`
+ // matches the regular expression `b`.
+ MATCH = 97; // STRING, STRING -> DATUM
+
+ // Change the case of a string.
+ UPCASE = 141; // STRING -> STRING
+ DOWNCASE = 142; // STRING -> STRING
+
+ // Select a number of elements from sequence with uniform distribution.
+ SAMPLE = 81; // Sequence, NUMBER -> Sequence
+
+ // Evaluates its first argument. If that argument returns
+ // NULL or throws an error related to the absence of an
+ // expected value (for instance, accessing a non-existent
+ // field or adding NULL to an integer), DEFAULT will either
+ // return its second argument or execute it if it's a
+ // function. If the second argument is a function, it will be
+ // passed either the text of the error or NULL as its
+ // argument.
+ DEFAULT = 92; // Top, Top -> Top
+
+ // Parses its first argument as a json string and returns it as a
+ // datum.
+ JSON = 98; // STRING -> DATUM
+ // Returns the datum as a JSON string.
+ // N.B.: we would really prefer this be named TO_JSON and that exists as
+ // an alias in Python and JavaScript drivers; however it conflicts with the
+ // standard `to_json` method defined by Ruby's standard json library.
+ TO_JSON_STRING = 172; // DATUM -> STRING
+
+ // Parses its first arguments as an ISO 8601 time and returns it as a
+ // datum.
+ ISO8601 = 99; // STRING -> PSEUDOTYPE(TIME)
+ // Prints a time as an ISO 8601 time.
+ TO_ISO8601 = 100; // PSEUDOTYPE(TIME) -> STRING
+
+ // Returns a time given seconds since epoch in UTC.
+ EPOCH_TIME = 101; // NUMBER -> PSEUDOTYPE(TIME)
+ // Returns seconds since epoch in UTC given a time.
+ TO_EPOCH_TIME = 102; // PSEUDOTYPE(TIME) -> NUMBER
+
+ // The time the query was received by the server.
+ NOW = 103; // -> PSEUDOTYPE(TIME)
+ // Puts a time into an ISO 8601 timezone.
+ IN_TIMEZONE = 104; // PSEUDOTYPE(TIME), STRING -> PSEUDOTYPE(TIME)
+ // a.during(b, c) returns whether a is in the range [b, c)
+ DURING = 105; // PSEUDOTYPE(TIME), PSEUDOTYPE(TIME), PSEUDOTYPE(TIME) -> BOOL
+ // Retrieves the date portion of a time.
+ DATE = 106; // PSEUDOTYPE(TIME) -> PSEUDOTYPE(TIME)
+ // x.time_of_day == x.date - x
+ TIME_OF_DAY = 126; // PSEUDOTYPE(TIME) -> NUMBER
+ // Returns the timezone of a time.
+ TIMEZONE = 127; // PSEUDOTYPE(TIME) -> STRING
+
+ // These access the various components of a time.
+ YEAR = 128; // PSEUDOTYPE(TIME) -> NUMBER
+ MONTH = 129; // PSEUDOTYPE(TIME) -> NUMBER
+ DAY = 130; // PSEUDOTYPE(TIME) -> NUMBER
+ DAY_OF_WEEK = 131; // PSEUDOTYPE(TIME) -> NUMBER
+ DAY_OF_YEAR = 132; // PSEUDOTYPE(TIME) -> NUMBER
+ HOURS = 133; // PSEUDOTYPE(TIME) -> NUMBER
+ MINUTES = 134; // PSEUDOTYPE(TIME) -> NUMBER
+ SECONDS = 135; // PSEUDOTYPE(TIME) -> NUMBER
+
+ // Construct a time from a date and optional timezone or a
+ // date+time and optional timezone.
+ TIME = 136; // NUMBER, NUMBER, NUMBER, STRING -> PSEUDOTYPE(TIME) |
+ // NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, STRING -> PSEUDOTYPE(TIME) |
+
+ // Constants for ISO 8601 days of the week.
+ MONDAY = 107; // -> 1
+ TUESDAY = 108; // -> 2
+ WEDNESDAY = 109; // -> 3
+ THURSDAY = 110; // -> 4
+ FRIDAY = 111; // -> 5
+ SATURDAY = 112; // -> 6
+ SUNDAY = 113; // -> 7
+
+ // Constants for ISO 8601 months.
+ JANUARY = 114; // -> 1
+ FEBRUARY = 115; // -> 2
+ MARCH = 116; // -> 3
+ APRIL = 117; // -> 4
+ MAY = 118; // -> 5
+ JUNE = 119; // -> 6
+ JULY = 120; // -> 7
+ AUGUST = 121; // -> 8
+ SEPTEMBER = 122; // -> 9
+ OCTOBER = 123; // -> 10
+ NOVEMBER = 124; // -> 11
+ DECEMBER = 125; // -> 12
+
+ // Indicates to MERGE to replace, or remove in case of an empty literal, the
+ // other object rather than merge it.
+ LITERAL = 137; // -> Merging
+ // JSON -> Merging
+
+ // SEQUENCE, STRING -> GROUPED_SEQUENCE | SEQUENCE, FUNCTION -> GROUPED_SEQUENCE
+ GROUP = 144;
+ SUM = 145;
+ AVG = 146;
+ MIN = 147;
+ MAX = 148;
+
+ // `str.split()` splits on whitespace
+ // `str.split(" ")` splits on spaces only
+ // `str.split(" ", 5)` splits on spaces with at most 5 results
+ // `str.split(nil, 5)` splits on whitespace with at most 5 results
+ SPLIT = 149; // STRING -> ARRAY | STRING, STRING -> ARRAY | STRING, STRING, NUMBER -> ARRAY | STRING, NULL, NUMBER -> ARRAY
+
+ UNGROUP = 150; // GROUPED_DATA -> ARRAY
+
+ // Takes a range of numbers and returns a random number within the range
+ RANDOM = 151; // NUMBER, NUMBER {float:BOOL} -> DATUM
+
+ CHANGES = 152; // TABLE -> STREAM
+ ARGS = 154; // ARRAY -> SPECIAL (used to splice arguments)
+
+ // BINARY is client-only at the moment, it is not supported on the server
+ BINARY = 155; // STRING -> PSEUDOTYPE(BINARY)
+
+ GEOJSON = 157; // OBJECT -> PSEUDOTYPE(GEOMETRY)
+ TO_GEOJSON = 158; // PSEUDOTYPE(GEOMETRY) -> OBJECT
+ POINT = 159; // NUMBER, NUMBER -> PSEUDOTYPE(GEOMETRY)
+ LINE = 160; // (ARRAY | PSEUDOTYPE(GEOMETRY))... -> PSEUDOTYPE(GEOMETRY)
+ POLYGON = 161; // (ARRAY | PSEUDOTYPE(GEOMETRY))... -> PSEUDOTYPE(GEOMETRY)
+ DISTANCE = 162; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) {geo_system:STRING, unit:STRING} -> NUMBER
+ INTERSECTS = 163; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) -> BOOL
+ INCLUDES = 164; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) -> BOOL
+ CIRCLE = 165; // PSEUDOTYPE(GEOMETRY), NUMBER {num_vertices:NUMBER, geo_system:STRING, unit:STRING, fill:BOOL} -> PSEUDOTYPE(GEOMETRY)
+ GET_INTERSECTING = 166; // TABLE, PSEUDOTYPE(GEOMETRY) {index:!STRING} -> StreamSelection
+ FILL = 167; // PSEUDOTYPE(GEOMETRY) -> PSEUDOTYPE(GEOMETRY)
+ GET_NEAREST = 168; // TABLE, PSEUDOTYPE(GEOMETRY) {index:!STRING, max_results:NUM, max_dist:NUM, geo_system:STRING, unit:STRING} -> ARRAY
+ POLYGON_SUB = 171; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) -> PSEUDOTYPE(GEOMETRY)
+
+ // Constants for specifying key ranges
+ MINVAL = 180;
+ MAXVAL = 181;
+ }
+ optional TermType type = 1;
+
+ // This is only used when type is DATUM.
+ optional Datum datum = 2;
+
+ repeated Term args = 3; // Holds the positional arguments of the query.
+ message AssocPair {
+ optional string key = 1;
+ optional Term val = 2;
+ }
+ repeated AssocPair optargs = 4; // Holds the optional arguments of the query.
+ // (Note that the order of the optional arguments doesn't matter; think of a
+ // Hash.)
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// EXAMPLE //
+////////////////////////////////////////////////////////////////////////////////
+// ```ruby
+// r.table('tbl', {:read_mode => 'outdated'}).insert([{:id => 0}, {:id => 1}])
+// ```
+// Would turn into:
+// Term {
+// type = INSERT;
+// args = [Term {
+// type = TABLE;
+// args = [Term {
+// type = DATUM;
+// datum = Datum { type = R_STR; r_str = "tbl"; };
+// }];
+// optargs = [["read_mode",
+// Term {
+// type = DATUM;
+// datum = Datum { type = R_STR; r_bool = "outdated"; };
+// }]];
+// },
+// Term {
+// type = MAKE_ARRAY;
+// args = [Term {
+// type = DATUM;
+// datum = Datum { type = R_OBJECT; r_object = [["id", 0]]; };
+// },
+// Term {
+// type = DATUM;
+// datum = Datum { type = R_OBJECT; r_object = [["id", 1]]; };
+// }];
+// }]
+// }
+// And the server would reply:
+// Response {
+// type = SUCCESS_ATOM;
+// token = 1;
+// response = [Datum { type = R_OBJECT; r_object = [["inserted", 2]]; }];
+// }
+// Or, if there were an error:
+// Response {
+// type = RUNTIME_ERROR;
+// token = 1;
+// response = [Datum { type = R_STR; r_str = "The table `tbl` doesn't exist!"; }];
+// backtrace = [Frame { type = POS; pos = 0; }, Frame { type = POS; pos = 0; }];
+// }
diff --git a/ext/librethinkdbxx/src/connection.cc b/ext/librethinkdbxx/src/connection.cc
new file mode 100644
index 00000000..53d106ec
--- /dev/null
+++ b/ext/librethinkdbxx/src/connection.cc
@@ -0,0 +1,434 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+
+#include <netdb.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cstring>
+#include <cinttypes>
+#include <memory>
+
+#include "connection.h"
+#include "connection_p.h"
+#include "json_p.h"
+#include "exceptions.h"
+#include "term.h"
+#include "cursor_p.h"
+
+#include "rapidjson-config.h"
+#include "rapidjson/rapidjson.h"
+#include "rapidjson/encodedstream.h"
+#include "rapidjson/document.h"
+
+namespace RethinkDB {
+
+using QueryType = Protocol::Query::QueryType;
+
+// constants
+const int debug_net = 0;
+const uint32_t version_magic =
+ static_cast<uint32_t>(Protocol::VersionDummy::Version::V0_4);
+const uint32_t json_magic =
+ static_cast<uint32_t>(Protocol::VersionDummy::Protocol::JSON);
+
+std::unique_ptr<Connection> connect(std::string host, int port, std::string auth_key) {
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ char port_str[16];
+ snprintf(port_str, 16, "%d", port);
+ struct addrinfo *servinfo;
+ int ret = getaddrinfo(host.c_str(), port_str, &hints, &servinfo);
+ if (ret) throw Error("getaddrinfo: %s\n", gai_strerror(ret));
+
+ struct addrinfo *p;
+ Error error;
+ int sockfd;
+ for (p = servinfo; p != NULL; p = p->ai_next) {
+ sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+ if (sockfd == -1) {
+ error = Error::from_errno("socket");
+ continue;
+ }
+
+ if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ ::close(sockfd);
+ error = Error::from_errno("connect");
+ continue;
+ }
+
+ break;
+ }
+
+ if (p == NULL) {
+ throw error;
+ }
+
+ freeaddrinfo(servinfo);
+
+ std::unique_ptr<ConnectionPrivate> conn_private(new ConnectionPrivate(sockfd));
+ WriteLock writer(conn_private.get());
+ {
+ size_t size = auth_key.size();
+ char buf[12 + size];
+ memcpy(buf, &version_magic, 4);
+ uint32_t n = size;
+ memcpy(buf + 4, &n, 4);
+ memcpy(buf + 8, auth_key.data(), size);
+ memcpy(buf + 8 + size, &json_magic, 4);
+ writer.send(buf, sizeof buf);
+ }
+
+ ReadLock reader(conn_private.get());
+ {
+ const size_t max_response_length = 1024;
+ char buf[max_response_length + 1];
+ size_t len = reader.recv_cstring(buf, max_response_length);
+ if (len == max_response_length || strcmp(buf, "SUCCESS")) {
+ buf[len] = 0;
+ ::close(sockfd);
+ throw Error("Server rejected connection with message: %s", buf);
+ }
+ }
+
+ return std::unique_ptr<Connection>(new Connection(conn_private.release()));
+}
+
+Connection::Connection(ConnectionPrivate *dd) : d(dd) { }
+Connection::~Connection() {
+ // close();
+ if (d->guarded_sockfd >= 0)
+ ::close(d->guarded_sockfd);
+}
+
+size_t ReadLock::recv_some(char* buf, size_t size, double wait) {
+ if (wait != FOREVER) {
+ while (true) {
+ fd_set readfds;
+ struct timeval tv;
+
+ FD_ZERO(&readfds);
+ FD_SET(conn->guarded_sockfd, &readfds);
+
+ tv.tv_sec = (int)wait;
+ tv.tv_usec = (int)((wait - (int)wait) / MICROSECOND);
+ int rv = select(conn->guarded_sockfd + 1, &readfds, NULL, NULL, &tv);
+ if (rv == -1) {
+ throw Error::from_errno("select");
+ } else if (rv == 0) {
+ throw TimeoutException();
+ }
+
+ if (FD_ISSET(conn->guarded_sockfd, &readfds)) {
+ break;
+ }
+ }
+ }
+
+ ssize_t numbytes = ::recv(conn->guarded_sockfd, buf, size, 0);
+ if (numbytes <= 0) throw Error::from_errno("recv");
+ if (debug_net > 1) {
+ fprintf(stderr, "<< %s\n", write_datum(std::string(buf, numbytes)).c_str());
+ }
+
+ return numbytes;
+}
+
+void ReadLock::recv(char* buf, size_t size, double wait) {
+ while (size) {
+ size_t numbytes = recv_some(buf, size, wait);
+
+ buf += numbytes;
+ size -= numbytes;
+ }
+}
+
+size_t ReadLock::recv_cstring(char* buf, size_t max_size){
+ size_t size = 0;
+ for (; size < max_size; size++) {
+ recv(buf, 1, FOREVER);
+ if (*buf == 0) {
+ break;
+ }
+ buf++;
+ }
+ return size;
+}
+
+void WriteLock::send(const char* buf, size_t size) {
+ while (size) {
+ ssize_t numbytes = ::write(conn->guarded_sockfd, buf, size);
+ if (numbytes == -1) throw Error::from_errno("write");
+ if (debug_net > 1) {
+ fprintf(stderr, ">> %s\n", write_datum(std::string(buf, numbytes)).c_str());
+ }
+
+ buf += numbytes;
+ size -= numbytes;
+ }
+}
+
+void WriteLock::send(const std::string data) {
+ send(data.data(), data.size());
+}
+
+std::string ReadLock::recv(size_t size) {
+ char buf[size];
+ recv(buf, size, FOREVER);
+ return buf;
+}
+
+void Connection::close() {
+ CacheLock guard(d.get());
+ for (auto& it : d->guarded_cache) {
+ stop_query(it.first);
+ }
+
+ int ret = ::close(d->guarded_sockfd);
+ if (ret == -1) {
+ throw Error::from_errno("close");
+ }
+ d->guarded_sockfd = -1;
+}
+
+Response ConnectionPrivate::wait_for_response(uint64_t token_want, double wait) {
+ CacheLock guard(this);
+ ConnectionPrivate::TokenCache& cache = guarded_cache[token_want];
+
+ while (true) {
+ if (!cache.responses.empty()) {
+ Response response(std::move(cache.responses.front()));
+ cache.responses.pop();
+ if (cache.closed && cache.responses.empty()) {
+ guarded_cache.erase(token_want);
+ }
+
+ return response;
+ }
+
+ if (cache.closed) {
+ throw Error("Trying to read from a closed token");
+ }
+
+ if (guarded_loop_active) {
+ cache.cond.wait(guard.inner_lock);
+ } else {
+ break;
+ }
+ }
+
+ ReadLock reader(this);
+ return reader.read_loop(token_want, std::move(guard), wait);
+}
+
+Response ReadLock::read_loop(uint64_t token_want, CacheLock&& guard, double wait) {
+ if (!guard.inner_lock) {
+ guard.lock();
+ }
+ if (conn->guarded_loop_active) {
+ throw Error("Cannot run more than one read loop on the same connection");
+ }
+ conn->guarded_loop_active = true;
+ guard.unlock();
+
+ try {
+ while (true) {
+ char buf[12];
+ bzero(buf, sizeof(buf));
+ recv(buf, 12, wait);
+ uint64_t token_got;
+ memcpy(&token_got, buf, 8);
+ uint32_t length;
+ memcpy(&length, buf + 8, 4);
+
+ std::unique_ptr<char[]> bufmem(new char[length + 1]);
+ char *buffer = bufmem.get();
+ bzero(buffer, length + 1);
+ recv(buffer, length, wait);
+ buffer[length] = '\0';
+
+ rapidjson::Document json;
+ json.ParseInsitu(buffer);
+ if (json.HasParseError()) {
+ fprintf(stderr, "json parse error, code: %d, position: %d\n",
+ (int)json.GetParseError(), (int)json.GetErrorOffset());
+ } else if (json.IsNull()) {
+ fprintf(stderr, "null value, read: %s\n", buffer);
+ }
+
+ Datum datum = read_datum(json);
+ if (debug_net > 0) {
+ fprintf(stderr, "[%" PRIu64 "] << %s\n", token_got, write_datum(datum).c_str());
+ }
+
+ Response response(std::move(datum));
+
+ if (token_got == token_want) {
+ guard.lock();
+ if (response.type != Protocol::Response::ResponseType::SUCCESS_PARTIAL) {
+ auto it = conn->guarded_cache.find(token_got);
+ if (it != conn->guarded_cache.end()) {
+ it->second.closed = true;
+ it->second.cond.notify_all();
+ }
+ conn->guarded_cache.erase(it);
+ }
+ conn->guarded_loop_active = false;
+ for (auto& it : conn->guarded_cache) {
+ it.second.cond.notify_all();
+ }
+ return response;
+ } else {
+ guard.lock();
+ auto it = conn->guarded_cache.find(token_got);
+ if (it == conn->guarded_cache.end()) {
+ // drop the response
+ } else if (!it->second.closed) {
+ it->second.responses.emplace(std::move(response));
+ if (response.type != Protocol::Response::ResponseType::SUCCESS_PARTIAL) {
+ it->second.closed = true;
+ }
+ }
+ it->second.cond.notify_all();
+ guard.unlock();
+ }
+ }
+ } catch (const TimeoutException &e) {
+ if (!guard.inner_lock){
+ guard.lock();
+ }
+ conn->guarded_loop_active = false;
+ throw e;
+ }
+}
+
+void ConnectionPrivate::run_query(Query query, bool no_reply) {
+ WriteLock writer(this);
+ writer.send(query.serialize());
+}
+
+Cursor Connection::start_query(Term *term, OptArgs&& opts) {
+ bool no_reply = false;
+ auto it = opts.find("noreply");
+ if (it != opts.end()) {
+ no_reply = *(it->second.datum.get_boolean());
+ }
+
+ uint64_t token = d->new_token();
+ {
+ CacheLock guard(d.get());
+ d->guarded_cache[token];
+ }
+
+ d->run_query(Query{QueryType::START, token, term->datum, std::move(opts)});
+ if (no_reply) {
+ return Cursor(new CursorPrivate(token, this, Nil()));
+ }
+
+ Cursor cursor(new CursorPrivate(token, this));
+ Response response = d->wait_for_response(token, FOREVER);
+ cursor.d->add_response(std::move(response));
+ return cursor;
+}
+
+void Connection::stop_query(uint64_t token) {
+ const auto& it = d->guarded_cache.find(token);
+ if (it != d->guarded_cache.end() && !it->second.closed) {
+ d->run_query(Query{QueryType::STOP, token}, true);
+ }
+}
+
+void Connection::continue_query(uint64_t token) {
+ d->run_query(Query{QueryType::CONTINUE, token}, true);
+}
+
+Error Response::as_error() {
+ std::string repr;
+ if (result.size() == 1) {
+ std::string* string = result[0].get_string();
+ if (string) {
+ repr = *string;
+ } else {
+ repr = write_datum(result[0]);
+ }
+ } else {
+ repr = write_datum(Datum(result));
+ }
+ std::string err;
+ using RT = Protocol::Response::ResponseType;
+ using ET = Protocol::Response::ErrorType;
+ switch (type) {
+ case RT::SUCCESS_SEQUENCE: err = "unexpected response: SUCCESS_SEQUENCE"; break;
+ case RT::SUCCESS_PARTIAL: err = "unexpected response: SUCCESS_PARTIAL"; break;
+ case RT::SUCCESS_ATOM: err = "unexpected response: SUCCESS_ATOM"; break;
+ case RT::WAIT_COMPLETE: err = "unexpected response: WAIT_COMPLETE"; break;
+ case RT::SERVER_INFO: err = "unexpected response: SERVER_INFO"; break;
+ case RT::CLIENT_ERROR: err = "ReqlDriverError"; break;
+ case RT::COMPILE_ERROR: err = "ReqlCompileError"; break;
+ case RT::RUNTIME_ERROR:
+ switch (error_type) {
+ case ET::INTERNAL: err = "ReqlInternalError"; break;
+ case ET::RESOURCE_LIMIT: err = "ReqlResourceLimitError"; break;
+ case ET::QUERY_LOGIC: err = "ReqlQueryLogicError"; break;
+ case ET::NON_EXISTENCE: err = "ReqlNonExistenceError"; break;
+ case ET::OP_FAILED: err = "ReqlOpFailedError"; break;
+ case ET::OP_INDETERMINATE: err = "ReqlOpIndeterminateError"; break;
+ case ET::USER: err = "ReqlUserError"; break;
+ case ET::PERMISSION_ERROR: err = "ReqlPermissionError"; break;
+ default: err = "ReqlRuntimeError"; break;
+ }
+ }
+ throw Error("%s: %s", err.c_str(), repr.c_str());
+}
+
+Protocol::Response::ResponseType response_type(double t) {
+ int n = static_cast<int>(t);
+ using RT = Protocol::Response::ResponseType;
+ switch (n) {
+ case static_cast<int>(RT::SUCCESS_ATOM):
+ return RT::SUCCESS_ATOM;
+ case static_cast<int>(RT::SUCCESS_SEQUENCE):
+ return RT::SUCCESS_SEQUENCE;
+ case static_cast<int>(RT::SUCCESS_PARTIAL):
+ return RT::SUCCESS_PARTIAL;
+ case static_cast<int>(RT::WAIT_COMPLETE):
+ return RT::WAIT_COMPLETE;
+ case static_cast<int>(RT::CLIENT_ERROR):
+ return RT::CLIENT_ERROR;
+ case static_cast<int>(RT::COMPILE_ERROR):
+ return RT::COMPILE_ERROR;
+ case static_cast<int>(RT::RUNTIME_ERROR):
+ return RT::RUNTIME_ERROR;
+ default:
+ throw Error("Unknown response type");
+ }
+}
+
+Protocol::Response::ErrorType runtime_error_type(double t) {
+ int n = static_cast<int>(t);
+ using ET = Protocol::Response::ErrorType;
+ switch (n) {
+ case static_cast<int>(ET::INTERNAL):
+ return ET::INTERNAL;
+ case static_cast<int>(ET::RESOURCE_LIMIT):
+ return ET::RESOURCE_LIMIT;
+ case static_cast<int>(ET::QUERY_LOGIC):
+ return ET::QUERY_LOGIC;
+ case static_cast<int>(ET::NON_EXISTENCE):
+ return ET::NON_EXISTENCE;
+ case static_cast<int>(ET::OP_FAILED):
+ return ET::OP_FAILED;
+ case static_cast<int>(ET::OP_INDETERMINATE):
+ return ET::OP_INDETERMINATE;
+ case static_cast<int>(ET::USER):
+ return ET::USER;
+ default:
+ throw Error("Unknown error type");
+ }
+}
+
+}
diff --git a/ext/librethinkdbxx/src/connection.h b/ext/librethinkdbxx/src/connection.h
new file mode 100644
index 00000000..d3882857
--- /dev/null
+++ b/ext/librethinkdbxx/src/connection.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <string>
+#include <queue>
+#include <mutex>
+#include <memory>
+#include <condition_variable>
+
+#include "protocol_defs.h"
+#include "datum.h"
+#include "error.h"
+
+#define FOREVER (-1)
+#define SECOND 1
+#define MICROSECOND 0.000001
+
+namespace RethinkDB {
+
+class Term;
+using OptArgs = std::map<std::string, Term>;
+
+// A connection to a RethinkDB server
+// It contains:
+// * A socket
+// * Read and write locks
+// * A cache of responses that have not been read by the corresponding Cursor
+class ConnectionPrivate;
+class Connection {
+public:
+ Connection() = delete;
+ Connection(const Connection&) noexcept = delete;
+ Connection(Connection&&) noexcept = delete;
+ Connection& operator=(Connection&&) noexcept = delete;
+ Connection& operator=(const Connection&) noexcept = delete;
+ ~Connection();
+
+ void close();
+
+private:
+ explicit Connection(ConnectionPrivate *dd);
+ std::unique_ptr<ConnectionPrivate> d;
+
+ Cursor start_query(Term *term, OptArgs&& args);
+ void stop_query(uint64_t);
+ void continue_query(uint64_t);
+
+ friend class Cursor;
+ friend class CursorPrivate;
+ friend class Token;
+ friend class Term;
+ friend std::unique_ptr<Connection>
+ connect(std::string host, int port, std::string auth_key);
+
+};
+
+// $doc(connect)
+std::unique_ptr<Connection> connect(std::string host = "localhost", int port = 28015, std::string auth_key = "");
+
+}
diff --git a/ext/librethinkdbxx/src/connection_p.h b/ext/librethinkdbxx/src/connection_p.h
new file mode 100644
index 00000000..d8a95e3c
--- /dev/null
+++ b/ext/librethinkdbxx/src/connection_p.h
@@ -0,0 +1,133 @@
+#ifndef CONNECTION_P_H
+#define CONNECTION_P_H
+
+#include <inttypes.h>
+
+#include "connection.h"
+#include "term.h"
+#include "json_p.h"
+
+namespace RethinkDB {
+
+extern const int debug_net;
+
+struct Query {
+ Protocol::Query::QueryType type;
+ uint64_t token;
+ Datum term;
+ OptArgs optArgs;
+
+ std::string serialize() {
+ Array query_arr{static_cast<double>(type)};
+ if (term.is_valid()) query_arr.emplace_back(term);
+ if (!optArgs.empty())
+ query_arr.emplace_back(Term(std::move(optArgs)).datum);
+
+ std::string query_str = write_datum(query_arr);
+ if (debug_net > 0) {
+ fprintf(stderr, "[%" PRIu64 "] >> %s\n", token, query_str.c_str());
+ }
+
+ char header[12];
+ memcpy(header, &token, 8);
+ uint32_t size = query_str.size();
+ memcpy(header + 8, &size, 4);
+ query_str.insert(0, header, 12);
+ return query_str;
+ }
+};
+
+// Used internally to convert a raw response type into an enum
+Protocol::Response::ResponseType response_type(double t);
+Protocol::Response::ErrorType runtime_error_type(double t);
+
+// Contains a response from the server. Use the Cursor class to interact with these responses
+class Response {
+public:
+ Response() = delete;
+ explicit Response(Datum&& datum) :
+ type(response_type(std::move(datum).extract_field("t").extract_number())),
+ error_type(datum.get_field("e") ?
+ runtime_error_type(std::move(datum).extract_field("e").extract_number()) :
+ Protocol::Response::ErrorType(0)),
+ result(std::move(datum).extract_field("r").extract_array()) { }
+ Error as_error();
+ Protocol::Response::ResponseType type;
+ Protocol::Response::ErrorType error_type;
+ Array result;
+};
+
+class Token;
+class ConnectionPrivate {
+public:
+ ConnectionPrivate(int sockfd)
+ : guarded_next_token(1), guarded_sockfd(sockfd), guarded_loop_active(false)
+ { }
+
+ void run_query(Query query, bool no_reply = false);
+
+ Response wait_for_response(uint64_t, double);
+ uint64_t new_token() {
+ return guarded_next_token++;
+ }
+
+ std::mutex read_lock;
+ std::mutex write_lock;
+ std::mutex cache_lock;
+
+ struct TokenCache {
+ bool closed = false;
+ std::condition_variable cond;
+ std::queue<Response> responses;
+ };
+
+ std::map<uint64_t, TokenCache> guarded_cache;
+ uint64_t guarded_next_token;
+ int guarded_sockfd;
+ bool guarded_loop_active;
+};
+
+class CacheLock {
+public:
+ CacheLock(ConnectionPrivate* conn) : inner_lock(conn->cache_lock) { }
+
+ void lock() {
+ inner_lock.lock();
+ }
+
+ void unlock() {
+ inner_lock.unlock();
+ }
+
+ std::unique_lock<std::mutex> inner_lock;
+};
+
+class ReadLock {
+public:
+ ReadLock(ConnectionPrivate* conn_) : lock(conn_->read_lock), conn(conn_) { }
+
+ size_t recv_some(char*, size_t, double wait);
+ void recv(char*, size_t, double wait);
+ std::string recv(size_t);
+ size_t recv_cstring(char*, size_t);
+
+ Response read_loop(uint64_t, CacheLock&&, double);
+
+ std::lock_guard<std::mutex> lock;
+ ConnectionPrivate* conn;
+};
+
+class WriteLock {
+public:
+ WriteLock(ConnectionPrivate* conn_) : lock(conn_->write_lock), conn(conn_) { }
+
+ void send(const char*, size_t);
+ void send(std::string);
+
+ std::lock_guard<std::mutex> lock;
+ ConnectionPrivate* conn;
+};
+
+} // namespace RethinkDB
+
+#endif // CONNECTION_P_H
diff --git a/ext/librethinkdbxx/src/cursor.cc b/ext/librethinkdbxx/src/cursor.cc
new file mode 100644
index 00000000..df0621eb
--- /dev/null
+++ b/ext/librethinkdbxx/src/cursor.cc
@@ -0,0 +1,223 @@
+#include "cursor.h"
+#include "cursor_p.h"
+#include "exceptions.h"
+
+namespace RethinkDB {
+
+// for type completion, in order to forward declare with unique_ptr
+Cursor::Cursor(Cursor&&) = default;
+Cursor& Cursor::operator=(Cursor&&) = default;
+
+CursorPrivate::CursorPrivate(uint64_t token_, Connection *conn_)
+ : single(false), no_more(false), index(0),
+ token(token_), conn(conn_)
+{ }
+
+CursorPrivate::CursorPrivate(uint64_t token_, Connection *conn_, Datum&& datum)
+ : single(true), no_more(true), index(0), buffer(Array{std::move(datum)}),
+ token(token_), conn(conn_)
+{ }
+
+Cursor::Cursor(CursorPrivate *dd) : d(dd) {}
+
+Cursor::~Cursor() {
+ try {
+ if (d && d->conn) {
+ close();
+ }
+ } catch ( ... ) {}
+}
+
+Datum& Cursor::next(double wait) const {
+ if (!has_next(wait)) {
+ throw Error("next: No more data");
+ }
+
+ return d->buffer[d->index++];
+}
+
+Datum& Cursor::peek(double wait) const {
+ if (!has_next(wait)) {
+ throw Error("next: No more data");
+ }
+
+ return d->buffer[d->index];
+}
+
+void Cursor::each(std::function<void(Datum&&)> f, double wait) const {
+ while (has_next(wait)) {
+ f(std::move(d->buffer[d->index++]));
+ }
+}
+
+void CursorPrivate::convert_single() const {
+ if (index != 0) {
+ throw Error("Cursor: already consumed");
+ }
+
+ if (buffer.size() != 1) {
+ throw Error("Cursor: invalid response from server");
+ }
+
+ if (!buffer[0].is_array()) {
+ throw Error("Cursor: not an array");
+ }
+
+ buffer.swap(buffer[0].extract_array());
+ single = false;
+}
+
+void CursorPrivate::clear_and_read_all() const {
+ if (single) {
+ convert_single();
+ }
+ if (index != 0) {
+ buffer.erase(buffer.begin(), buffer.begin() + index);
+ index = 0;
+ }
+ while (!no_more) {
+ add_response(conn->d->wait_for_response(token, FOREVER));
+ }
+}
+
+Array&& Cursor::to_array() && {
+ d->clear_and_read_all();
+ return std::move(d->buffer);
+}
+
+Array Cursor::to_array() const & {
+ d->clear_and_read_all();
+ return d->buffer;
+}
+
+Datum Cursor::to_datum() const & {
+ if (d->single) {
+ if (d->index != 0) {
+ throw Error("to_datum: already consumed");
+ }
+ return d->buffer[0];
+ }
+
+ d->clear_and_read_all();
+ return d->buffer;
+}
+
+Datum Cursor::to_datum() && {
+ Datum ret((Nil()));
+ if (d->single) {
+ if (d->index != 0) {
+ throw Error("to_datum: already consumed");
+ }
+ ret = std::move(d->buffer[0]);
+ } else {
+ d->clear_and_read_all();
+ ret = std::move(d->buffer);
+ }
+
+ return ret;
+}
+
+void Cursor::close() const {
+ d->conn->stop_query(d->token);
+ d->no_more = true;
+}
+
+bool Cursor::has_next(double wait) const {
+ if (d->single) {
+ d->convert_single();
+ }
+
+ while (true) {
+ if (d->index >= d->buffer.size()) {
+ if (d->no_more) {
+ return false;
+ }
+ d->add_response(d->conn->d->wait_for_response(d->token, wait));
+ } else {
+ return true;
+ }
+ }
+}
+
+bool Cursor::is_single() const {
+ return d->single;
+}
+
+void CursorPrivate::add_results(Array&& results) const {
+ if (index >= buffer.size()) {
+ buffer = std::move(results);
+ index = 0;
+ } else {
+ for (auto& it : results) {
+ buffer.emplace_back(std::move(it));
+ }
+ }
+}
+
+void CursorPrivate::add_response(Response&& response) const {
+ using RT = Protocol::Response::ResponseType;
+ switch (response.type) {
+ case RT::SUCCESS_SEQUENCE:
+ add_results(std::move(response.result));
+ no_more = true;
+ break;
+ case RT::SUCCESS_PARTIAL:
+ conn->continue_query(token);
+ add_results(std::move(response.result));
+ break;
+ case RT::SUCCESS_ATOM:
+ add_results(std::move(response.result));
+ single = true;
+ no_more = true;
+ break;
+ case RT::SERVER_INFO:
+ add_results(std::move(response.result));
+ single = true;
+ no_more = true;
+ break;
+ case RT::WAIT_COMPLETE:
+ case RT::CLIENT_ERROR:
+ case RT::COMPILE_ERROR:
+ case RT::RUNTIME_ERROR:
+ no_more = true;
+ throw response.as_error();
+ }
+}
+
+Cursor::iterator Cursor::begin() {
+ return iterator(this);
+}
+
+Cursor::iterator Cursor::end() {
+ return iterator(nullptr);
+}
+
+Cursor::iterator::iterator(Cursor* cursor_) : cursor(cursor_) {}
+
+Cursor::iterator& Cursor::iterator::operator++ () {
+ if (cursor == nullptr) {
+ throw Error("incrementing an exhausted Cursor iterator");
+ }
+
+ cursor->next();
+ return *this;
+}
+
+Datum& Cursor::iterator::operator* () {
+ if (cursor == nullptr) {
+ throw Error("reading from empty Cursor iterator");
+ }
+
+ return cursor->peek();
+}
+
+bool Cursor::iterator::operator!= (const Cursor::iterator& other) const {
+ if (cursor == other.cursor) {
+ return false;
+ }
+
+ return !((cursor == nullptr && !other.cursor->has_next()) ||
+ (other.cursor == nullptr && !cursor->has_next()));
+}
+
+}
diff --git a/ext/librethinkdbxx/src/cursor.h b/ext/librethinkdbxx/src/cursor.h
new file mode 100644
index 00000000..60ae1817
--- /dev/null
+++ b/ext/librethinkdbxx/src/cursor.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include "connection.h"
+
+namespace RethinkDB {
+
+// The response from the server, as returned by run.
+// The response is either a single datum or a stream:
+// * If it is a stream, the cursor represents each element of the stream.
+// - Batches are fetched from the server as needed.
+// * If it is a single datum, is_single() returns true.
+// - If it is an array, the cursor represents each element of that array
+// - Otherwise, to_datum() returns the datum and iteration throws an exception.
+// The cursor can only be iterated over once, it discards data that has already been read.
+class CursorPrivate;
+class Cursor {
+public:
+ Cursor() = delete;
+ ~Cursor();
+
+ Cursor(Cursor&&); // movable
+ Cursor& operator=(Cursor&&);
+ Cursor(const Cursor&) = delete; // not copyable
+ Cursor& operator=(const Cursor&) = delete;
+
+ // Returned by begin() and end()
+ class iterator {
+ public:
+ iterator(Cursor*);
+ iterator& operator++ ();
+ Datum& operator* ();
+ bool operator!= (const iterator&) const;
+
+ private:
+ Cursor *cursor;
+ };
+
+ // Consume the next element
+ Datum& next(double wait = FOREVER) const;
+
+ // Peek at the next element
+ Datum& peek(double wait = FOREVER) const;
+
+ // Call f on every element of the Cursor
+ void each(std::function<void(Datum&&)> f, double wait = FOREVER) const;
+
+ // Consume and return all elements
+ Array&& to_array() &&;
+
+ // If is_single(), returns the single datum. Otherwise returns to_array().
+ Datum to_datum() &&;
+ Datum to_datum() const &;
+
+ // Efficiently consume and return all elements
+ Array to_array() const &;
+
+ // Close the cursor
+ void close() const;
+
+ // Returns false if there are no more elements
+ bool has_next(double wait = FOREVER) const;
+
+ // Returns false if the cursor is a stream
+ bool is_single() const;
+
+ iterator begin();
+ iterator end();
+
+private:
+ explicit Cursor(CursorPrivate *dd);
+ std::unique_ptr<CursorPrivate> d;
+
+ friend class Connection;
+};
+
+}
diff --git a/ext/librethinkdbxx/src/cursor_p.h b/ext/librethinkdbxx/src/cursor_p.h
new file mode 100644
index 00000000..ce584cd7
--- /dev/null
+++ b/ext/librethinkdbxx/src/cursor_p.h
@@ -0,0 +1,29 @@
+#ifndef CURSOR_P_H
+#define CURSOR_P_H
+
+#include "connection_p.h"
+
+namespace RethinkDB {
+
+class CursorPrivate {
+public:
+ CursorPrivate(uint64_t token, Connection *conn);
+ CursorPrivate(uint64_t token, Connection *conn, Datum&&);
+
+ void add_response(Response&&) const;
+ void add_results(Array&&) const;
+ void clear_and_read_all() const;
+ void convert_single() const;
+
+ mutable bool single = false;
+ mutable bool no_more = false;
+ mutable size_t index = 0;
+ mutable Array buffer;
+
+ uint64_t token;
+ Connection *conn;
+};
+
+} // namespace RethinkDB
+
+#endif // CURSOR_P_H \ No newline at end of file
diff --git a/ext/librethinkdbxx/src/datum.cc b/ext/librethinkdbxx/src/datum.cc
new file mode 100644
index 00000000..e4dbc8dc
--- /dev/null
+++ b/ext/librethinkdbxx/src/datum.cc
@@ -0,0 +1,449 @@
+#include <float.h>
+#include <cmath>
+
+#include "datum.h"
+#include "json_p.h"
+#include "utils.h"
+#include "cursor.h"
+
+#include "rapidjson-config.h"
+#include "rapidjson/prettywriter.h"
+#include "rapidjson/stringbuffer.h"
+
+namespace RethinkDB {
+
+using TT = Protocol::Term::TermType;
+
+bool Datum::is_nil() const {
+ return type == Type::NIL;
+}
+
+bool Datum::is_boolean() const {
+ return type == Type::BOOLEAN;
+}
+
+bool Datum::is_number() const {
+ return type == Type::NUMBER;
+}
+
+bool Datum::is_string() const {
+ return type == Type::STRING;
+}
+
+bool Datum::is_object() const {
+ return type == Type::OBJECT;
+}
+
+bool Datum::is_array() const {
+ return type == Type::ARRAY;
+}
+
+bool Datum::is_binary() const {
+ return type == Type::BINARY;
+}
+
+bool Datum::is_time() const {
+ return type == Type::TIME;
+}
+
+bool* Datum::get_boolean() {
+ if (type == Type::BOOLEAN) {
+ return &value.boolean;
+ } else {
+ return NULL;
+ }
+}
+
+const bool* Datum::get_boolean() const {
+ if (type == Type::BOOLEAN) {
+ return &value.boolean;
+ } else {
+ return NULL;
+ }
+}
+
+double* Datum::get_number() {
+ if (type == Type::NUMBER) {
+ return &value.number;
+ } else {
+ return NULL;
+ }
+}
+
+const double* Datum::get_number() const {
+ if (type == Type::NUMBER) {
+ return &value.number;
+ } else {
+ return NULL;
+ }
+}
+
+std::string* Datum::get_string() {
+ if (type == Type::STRING) {
+ return &value.string;
+ } else {
+ return NULL;
+ }
+}
+
+const std::string* Datum::get_string() const {
+ if (type == Type::STRING) {
+ return &value.string;
+ } else {
+ return NULL;
+ }
+}
+
+Datum* Datum::get_field(std::string key) {
+ if (type != Type::OBJECT) {
+ return NULL;
+ }
+ auto it = value.object.find(key);
+ if (it == value.object.end()) {
+ return NULL;
+ }
+ return &it->second;
+}
+
+const Datum* Datum::get_field(std::string key) const {
+ if (type != Type::OBJECT) {
+ return NULL;
+ }
+ auto it = value.object.find(key);
+ if (it == value.object.end()) {
+ return NULL;
+ }
+ return &it->second;
+}
+
+Datum* Datum::get_nth(size_t i) {
+ if (type != Type::ARRAY) {
+ return NULL;
+ }
+ if (i >= value.array.size()) {
+ return NULL;
+ }
+ return &value.array[i];
+}
+
+const Datum* Datum::get_nth(size_t i) const {
+ if (type != Type::ARRAY) {
+ return NULL;
+ }
+ if (i >= value.array.size()) {
+ return NULL;
+ }
+ return &value.array[i];
+}
+
+Object* Datum::get_object() {
+ if (type == Type::OBJECT) {
+ return &value.object;
+ } else {
+ return NULL;
+ }
+}
+
+const Object* Datum::get_object() const {
+ if (type == Type::OBJECT) {
+ return &value.object;
+ } else {
+ return NULL;
+ }
+}
+
+Array* Datum::get_array() {
+ if (type == Type::ARRAY) {
+ return &value.array;
+ } else {
+ return NULL;
+ }
+}
+
+const Array* Datum::get_array() const {
+ if (type == Type::ARRAY) {
+ return &value.array;
+ } else {
+ return NULL;
+ }
+}
+
+Binary* Datum::get_binary() {
+ if (type == Type::BINARY) {
+ return &value.binary;
+ } else {
+ return NULL;
+ }
+}
+
+const Binary* Datum::get_binary() const {
+ if (type == Type::BINARY) {
+ return &value.binary;
+ } else {
+ return NULL;
+ }
+}
+
+Time* Datum::get_time() {
+ if (type == Type::TIME) {
+ return &value.time;
+ } else {
+ return NULL;
+ }
+}
+
+const Time* Datum::get_time() const {
+ if (type == Type::TIME) {
+ return &value.time;
+ } else {
+ return NULL;
+ }
+}
+
+bool& Datum::extract_boolean() {
+ if (type != Type::BOOLEAN) {
+ throw Error("extract_bool: Not a boolean");
+ }
+ return value.boolean;
+}
+
+double& Datum::extract_number() {
+ if (type != Type::NUMBER) {
+ throw Error("extract_number: Not a number: %s", write_datum(*this).c_str());
+ }
+ return value.number;
+}
+
+std::string& Datum::extract_string() {
+ if (type != Type::STRING) {
+ throw Error("extract_string: Not a string");
+ }
+ return value.string;
+}
+
+Object& Datum::extract_object() {
+ if (type != Type::OBJECT) {
+ throw Error("extract_object: Not an object");
+ }
+ return value.object;
+}
+
+Datum& Datum::extract_field(std::string key) {
+ if (type != Type::OBJECT) {
+ throw Error("extract_field: Not an object");
+ }
+ auto it = value.object.find(key);
+ if (it == value.object.end()) {
+ throw Error("extract_field: No such key in object");
+ }
+ return it->second;
+}
+
+Datum& Datum::extract_nth(size_t i) {
+ if (type != Type::ARRAY) {
+ throw Error("extract_nth: Not an array");
+ }
+ if (i >= value.array.size()) {
+ throw Error("extract_nth: index too large");
+ }
+ return value.array[i];
+}
+
+Array& Datum::extract_array() {
+ if (type != Type::ARRAY) {
+ throw Error("get_array: Not an array");
+ }
+ return value.array;
+}
+
+Binary& Datum::extract_binary() {
+ if (type != Type::BINARY) {
+ throw Error("get_binary: Not a binary");
+ }
+ return value.binary;
+}
+
+Time& Datum::extract_time() {
+ if (type != Type::TIME) {
+ throw Error("get_time: Not a time");
+ }
+ return value.time;
+}
+
+int Datum::compare(const Datum& other) const {
+#define COMPARE(a, b) do { \
+ if (a < b) { return -1; } \
+ if (a > b) { return 1; } } while(0)
+#define COMPARE_OTHER(x) COMPARE(x, other.x)
+
+ COMPARE_OTHER(type);
+ int c;
+ switch (type) {
+ case Type::NIL: case Type::INVALID: break;
+ case Type::BOOLEAN: COMPARE_OTHER(value.boolean); break;
+ case Type::NUMBER: COMPARE_OTHER(value.number); break;
+ case Type::STRING:
+ c = value.string.compare(other.value.string);
+ COMPARE(c, 0);
+ break;
+ case Type::BINARY:
+ c = value.binary.data.compare(other.value.binary.data);
+ COMPARE(c, 0);
+ break;
+ case Type::TIME:
+ COMPARE(value.time.epoch_time, other.value.time.epoch_time);
+ COMPARE(value.time.utc_offset, other.value.time.utc_offset);
+ break;
+ case Type::ARRAY:
+ COMPARE_OTHER(value.array.size());
+ for (size_t i = 0; i < value.array.size(); i++) {
+ c = value.array[i].compare(other.value.array[i]);
+ COMPARE(c, 0);
+ }
+ break;
+ case Type::OBJECT:
+ COMPARE_OTHER(value.object.size());
+ for (Object::const_iterator l = value.object.begin(),
+ r = other.value.object.begin();
+ l != value.object.end();
+ ++l, ++r) {
+ COMPARE(l->first, r->first);
+ c = l->second.compare(r->second);
+ COMPARE(c, 0);
+ }
+ break;
+ default:
+ throw Error("cannot compare invalid datum");
+ }
+ return 0;
+#undef COMPARE_OTHER
+#undef COMPARE
+}
+
+bool Datum::operator== (const Datum& other) const {
+ return compare(other) == 0;
+}
+
+Datum Datum::from_raw() const {
+ do {
+ const Datum* type_field = get_field("$reql_type$");
+ if (!type_field) break;
+ const std::string* type = type_field->get_string();
+ if (!type) break;;
+ if (!strcmp(type->c_str(), "BINARY")) {
+ const Datum* data_field = get_field("data");
+ if (!data_field) break;
+ const std::string* encoded_data = data_field->get_string();
+ if (!encoded_data) break;
+ Binary binary("");
+ if (base64_decode(*encoded_data, binary.data)) {
+ return binary;
+ }
+ } else if (!strcmp(type->c_str(), "TIME")) {
+ const Datum* epoch_field = get_field("epoch_time");
+ if (!epoch_field) break;
+ const Datum* tz_field = get_field("timezone");
+ if (!tz_field) break;
+ const double* epoch_time = epoch_field->get_number();
+ if (!epoch_time) break;
+ const std::string* tz = tz_field->get_string();
+ if (!tz) break;
+ double offset;
+ if (!Time::parse_utc_offset(*tz, &offset)) break;
+ return Time(*epoch_time, offset);
+ }
+ } while (0);
+ return *this;
+}
+
+Datum Datum::to_raw() const {
+ if (type == Type::BINARY) {
+ return Object{
+ {"$reql_type$", "BINARY"},
+ {"data", base64_encode(value.binary.data)}};
+ } else if (type == Type::TIME) {
+ return Object{
+ {"$reql_type$", "TIME"},
+ {"epoch_time", value.time.epoch_time},
+ {"timezone", Time::utc_offset_string(value.time.utc_offset)}};
+ }
+ return *this;
+}
+
+Datum::Datum(Cursor&& cursor) : Datum(cursor.to_datum()) { }
+Datum::Datum(const Cursor& cursor) : Datum(cursor.to_datum()) { }
+
+static const double max_dbl_int = 0x1LL << DBL_MANT_DIG;
+static const double min_dbl_int = max_dbl_int * -1;
+bool number_as_integer(double d, int64_t *i_out) {
+ static_assert(DBL_MANT_DIG == 53, "Doubles are wrong size.");
+
+ if (min_dbl_int <= d && d <= max_dbl_int) {
+ int64_t i = d;
+ if (static_cast<double>(i) == d) {
+ *i_out = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+template void Datum::write_json(
+ rapidjson::Writer<rapidjson::StringBuffer> *writer) const;
+template void Datum::write_json(
+ rapidjson::PrettyWriter<rapidjson::StringBuffer> *writer) const;
+
+template <class json_writer_t>
+void Datum::write_json(json_writer_t *writer) const {
+ switch (type) {
+ case Type::NIL: writer->Null(); break;
+ case Type::BOOLEAN: writer->Bool(value.boolean); break;
+ case Type::NUMBER: {
+ const double d = value.number;
+ // Always print -0.0 as a double since integers cannot represent -0.
+ // Otherwise check if the number is an integer and print it as such.
+ int64_t i;
+ if (!(d == 0.0 && std::signbit(d)) && number_as_integer(d, &i)) {
+ writer->Int64(i);
+ } else {
+ writer->Double(d);
+ }
+ } break;
+ case Type::STRING: writer->String(value.string.data(), value.string.size()); break;
+ case Type::ARRAY: {
+ writer->StartArray();
+ for (auto it : value.array) {
+ it.write_json(writer);
+ }
+ writer->EndArray();
+ } break;
+ case Type::OBJECT: {
+ writer->StartObject();
+ for (auto it : value.object) {
+ writer->Key(it.first.data(), it.first.size());
+ it.second.write_json(writer);
+ }
+ writer->EndObject();
+ } break;
+
+ case Type::BINARY:
+ case Type::TIME:
+ to_raw().write_json(writer);
+ break;
+ default:
+ throw Error("cannot write invalid datum");
+ }
+}
+
+std::string Datum::as_json() const {
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ write_json(&writer);
+ return std::string(buffer.GetString(), buffer.GetSize());
+}
+
+Datum Datum::from_json(const std::string& json) {
+ return read_datum(json);
+}
+
+} // namespace RethinkDB
diff --git a/ext/librethinkdbxx/src/datum.h b/ext/librethinkdbxx/src/datum.h
new file mode 100644
index 00000000..051e2ca2
--- /dev/null
+++ b/ext/librethinkdbxx/src/datum.h
@@ -0,0 +1,287 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <map>
+#include <functional>
+
+#include "protocol_defs.h"
+#include "error.h"
+#include "types.h"
+
+namespace RethinkDB {
+
+class Cursor;
+
+// The type of data stored in a RethinkDB database.
+// The following JSON types are represented in a Datum as
+// * null -> Nil
+// * boolean -> bool
+// * number -> double
+// * unicode strings -> std::string
+// * array -> Array (aka std::vector<Datum>
+// * object -> Object (aka std::map<std::string, Datum>>
+// Datums can also contain one of the following extra types
+// * binary strings -> Binary
+// * timestamps -> Time
+// * points. lines and polygons -> not implemented
+class Datum {
+public:
+ Datum() : type(Type::INVALID), value() {}
+ Datum(Nil) : type(Type::NIL), value() { }
+ Datum(bool boolean_) : type(Type::BOOLEAN), value(boolean_) { }
+ Datum(double number_) : type(Type::NUMBER), value(number_) { }
+ Datum(const std::string& string_) : type(Type::STRING), value(string_) { }
+ Datum(std::string&& string_) : type(Type::STRING), value(std::move(string_)) { }
+ Datum(const Array& array_) : type(Type::ARRAY), value(array_) { }
+ Datum(Array&& array_) : type(Type::ARRAY), value(std::move(array_)) { }
+ Datum(const Binary& binary) : type(Type::BINARY), value(binary) { }
+ Datum(Binary&& binary) : type(Type::BINARY), value(std::move(binary)) { }
+ Datum(const Time time) : type(Type::TIME), value(time) { }
+ Datum(const Object& object_) : type(Type::OBJECT), value(object_) { }
+ Datum(Object&& object_) : type(Type::OBJECT), value(std::move(object_)) { }
+ Datum(const Datum& other) : type(other.type), value(other.type, other.value) { }
+ Datum(Datum&& other) : type(other.type), value(other.type, std::move(other.value)) { }
+
+ Datum& operator=(const Datum& other) {
+ value.destroy(type);
+ type = other.type;
+ value.set(type, other.value);
+ return *this;
+ }
+
+ Datum& operator=(Datum&& other) {
+ value.destroy(type);
+ type = other.type;
+ value.set(type, std::move(other.value));
+ return *this;
+ }
+
+ Datum(unsigned short number_) : Datum(static_cast<double>(number_)) { }
+ Datum(signed short number_) : Datum(static_cast<double>(number_)) { }
+ Datum(unsigned int number_) : Datum(static_cast<double>(number_)) { }
+ Datum(signed int number_) : Datum(static_cast<double>(number_)) { }
+ Datum(unsigned long number_) : Datum(static_cast<double>(number_)) { }
+ Datum(signed long number_) : Datum(static_cast<double>(number_)) { }
+ Datum(unsigned long long number_) : Datum(static_cast<double>(number_)) { }
+ Datum(signed long long number_) : Datum(static_cast<double>(number_)) { }
+
+ Datum(Protocol::Term::TermType type) : Datum(static_cast<double>(type)) { }
+ Datum(const char* string) : Datum(static_cast<std::string>(string)) { }
+
+ // Cursors are implicitly converted into datums
+ Datum(Cursor&&);
+ Datum(const Cursor&);
+
+ template <class T>
+ Datum(const std::map<std::string, T>& map) : type(Type::OBJECT), value(Object()) {
+ for (const auto& it : map) {
+ value.object.emplace(it.left, Datum(it.right));
+ }
+ }
+
+ template <class T>
+ Datum(std::map<std::string, T>&& map) : type(Type::OBJECT), value(Object()) {
+ for (auto& it : map) {
+ value.object.emplace(it.first, Datum(std::move(it.second)));
+ }
+ }
+
+ template <class T>
+ Datum(const std::vector<T>& vec) : type(Type::ARRAY), value(Array()) {
+ for (const auto& it : vec) {
+ value.array.emplace_back(it);
+ }
+ }
+
+ template <class T>
+ Datum(std::vector<T>&& vec) : type(Type::ARRAY), value(Array()) {
+ for (auto& it : vec) {
+ value.array.emplace_back(std::move(it));
+ }
+ }
+
+ ~Datum() {
+ value.destroy(type);
+ }
+
+ // Apply a visitor
+ template <class R, class F, class ...A>
+ R apply(F f, A&& ...args) const & {
+ switch (type) {
+ case Type::NIL: return f(Nil(), std::forward<A>(args)...); break;
+ case Type::BOOLEAN: return f(value.boolean, std::forward<A>(args)...); break;
+ case Type::NUMBER: return f(value.number, std::forward<A>(args)...); break;
+ case Type::STRING: return f(value.string, std::forward<A>(args)...); break;
+ case Type::OBJECT: return f(value.object, std::forward<A>(args)...); break;
+ case Type::ARRAY: return f(value.array, std::forward<A>(args)...); break;
+ case Type::BINARY: return f(value.binary, std::forward<A>(args)...); break;
+ case Type::TIME: return f(value.time, std::forward<A>(args)...); break;
+ default:
+ throw Error("internal error: no such datum type %d", static_cast<int>(type));
+ }
+ }
+
+ template <class R, class F, class ...A>
+ R apply(F f, A&& ...args) && {
+ switch (type) {
+ case Type::NIL: return f(Nil(), std::forward<A>(args)...); break;
+ case Type::BOOLEAN: return f(std::move(value.boolean), std::forward<A>(args)...); break;
+ case Type::NUMBER: return f(std::move(value.number), std::forward<A>(args)...); break;
+ case Type::STRING: return f(std::move(value.string), std::forward<A>(args)...); break;
+ case Type::OBJECT: return f(std::move(value.object), std::forward<A>(args)...); break;
+ case Type::ARRAY: return f(std::move(value.array), std::forward<A>(args)...); break;
+ case Type::BINARY: return f(std::move(value.binary), std::forward<A>(args)...); break;
+ case Type::TIME: return f(std::move(value.time), std::forward<A>(args)...); break;
+ default:
+ throw Error("internal error: no such datum type %d", static_cast<int>(type));
+ }
+ }
+
+ bool is_nil() const;
+ bool is_boolean() const;
+ bool is_number() const;
+ bool is_string() const;
+ bool is_object() const;
+ bool is_array() const;
+ bool is_binary() const;
+ bool is_time() const;
+
+ // get_* returns nullptr if the datum has a different type
+
+ bool* get_boolean();
+ const bool* get_boolean() const;
+ double* get_number();
+ const double* get_number() const;
+ std::string* get_string();
+ const std::string* get_string() const;
+ Object* get_object();
+ const Object* get_object() const;
+ Datum* get_field(std::string);
+ const Datum* get_field(std::string) const;
+ Array* get_array();
+ const Array* get_array() const;
+ Datum* get_nth(size_t);
+ const Datum* get_nth(size_t) const;
+ Binary* get_binary();
+ const Binary* get_binary() const;
+ Time* get_time();
+ const Time* get_time() const;
+
+ // extract_* throws an exception if the types don't match
+
+ bool& extract_boolean();
+ double& extract_number();
+ std::string& extract_string();
+ Object& extract_object();
+ Datum& extract_field(std::string);
+ Array& extract_array();
+ Datum& extract_nth(size_t);
+ Binary& extract_binary();
+ Time& extract_time();
+
+ // negative, zero or positive if this datum is smaller, identical or larger than the other one, respectively
+ // This is meant to match the results of RethinkDB's comparison operators
+ int compare(const Datum&) const;
+
+ // Deep equality
+ bool operator== (const Datum&) const;
+
+ // Recusively replace non-JSON types into objects that represent them
+ Datum to_raw() const;
+
+ // Recursively replace objects with a $reql_type$ field into the datum they represent
+ Datum from_raw() const;
+
+ template <class json_writer_t> void write_json(json_writer_t *writer) const;
+
+ std::string as_json() const;
+ static Datum from_json(const std::string&);
+
+ bool is_valid() const { return type != Type::INVALID; }
+
+private:
+ enum class Type {
+ INVALID, // default constructed
+ ARRAY, BOOLEAN, NIL, NUMBER, OBJECT, BINARY, STRING, TIME
+ // POINT, LINE, POLYGON
+ };
+ Type type;
+
+ union datum_value {
+ bool boolean;
+ double number;
+ std::string string;
+ Object object;
+ Array array;
+ Binary binary;
+ Time time;
+
+ datum_value() { }
+ datum_value(bool boolean_) : boolean(boolean_) { }
+ datum_value(double number_) : number(number_) { }
+ datum_value(const std::string& string_) : string(string_) { }
+ datum_value(std::string&& string_) : string(std::move(string_)) { }
+ datum_value(const Object& object_) : object(object_) { }
+ datum_value(Object&& object_) : object(std::move(object_)) { }
+ datum_value(const Array& array_) : array(array_) { }
+ datum_value(Array&& array_) : array(std::move(array_)) { }
+ datum_value(const Binary& binary_) : binary(binary_) { }
+ datum_value(Binary&& binary_) : binary(std::move(binary_)) { }
+ datum_value(Time time) : time(std::move(time)) { }
+
+ datum_value(Type type, const datum_value& other){
+ set(type, other);
+ }
+
+ datum_value(Type type, datum_value&& other){
+ set(type, std::move(other));
+ }
+
+ void set(Type type, datum_value&& other) {
+ switch(type){
+ case Type::NIL: case Type::INVALID: break;
+ case Type::BOOLEAN: new (this) bool(other.boolean); break;
+ case Type::NUMBER: new (this) double(other.number); break;
+ case Type::STRING: new (this) std::string(std::move(other.string)); break;
+ case Type::OBJECT: new (this) Object(std::move(other.object)); break;
+ case Type::ARRAY: new (this) Array(std::move(other.array)); break;
+ case Type::BINARY: new (this) Binary(std::move(other.binary)); break;
+ case Type::TIME: new (this) Time(std::move(other.time)); break;
+ }
+ }
+
+ void set(Type type, const datum_value& other) {
+ switch(type){
+ case Type::NIL: case Type::INVALID: break;
+ case Type::BOOLEAN: new (this) bool(other.boolean); break;
+ case Type::NUMBER: new (this) double(other.number); break;
+ case Type::STRING: new (this) std::string(other.string); break;
+ case Type::OBJECT: new (this) Object(other.object); break;
+ case Type::ARRAY: new (this) Array(other.array); break;
+ case Type::BINARY: new (this) Binary(other.binary); break;
+ case Type::TIME: new (this) Time(other.time); break;
+ }
+ }
+
+ void destroy(Type type) {
+ switch(type){
+ case Type::INVALID: break;
+ case Type::NIL: break;
+ case Type::BOOLEAN: break;
+ case Type::NUMBER: break;
+ case Type::STRING: { typedef std::string str; string.~str(); } break;
+ case Type::OBJECT: object.~Object(); break;
+ case Type::ARRAY: array.~Array(); break;
+ case Type::BINARY: binary.~Binary(); break;
+ case Type::TIME: time.~Time(); break;
+ }
+ }
+
+ ~datum_value() { }
+ };
+
+ datum_value value;
+};
+
+}
diff --git a/ext/librethinkdbxx/src/error.h b/ext/librethinkdbxx/src/error.h
new file mode 100644
index 00000000..ab75e248
--- /dev/null
+++ b/ext/librethinkdbxx/src/error.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <cstdarg>
+#include <cstring>
+#include <string>
+#include <cerrno>
+
+namespace RethinkDB {
+
+// All errors thrown by the server have this type
+struct Error {
+ template <class ...T>
+ explicit Error(const char* format_, T... A) {
+ format(format_, A...);
+ }
+
+ Error() = default;
+ Error(Error&&) = default;
+ Error(const Error&) = default;
+
+ Error& operator= (Error&& other) {
+ message = std::move(other.message);
+ return *this;
+ }
+
+ static Error from_errno(const char* str){
+ return Error("%s: %s", str, strerror(errno));
+ }
+
+ // The error message
+ std::string message;
+
+private:
+ const size_t max_message_size = 2048;
+
+ void format(const char* format_, ...) {
+ va_list args;
+ va_start(args, format_);
+ char message_[max_message_size];
+ vsnprintf(message_, max_message_size, format_, args);
+ va_end(args);
+ message = message_;
+ }
+};
+
+}
diff --git a/ext/librethinkdbxx/src/exceptions.h b/ext/librethinkdbxx/src/exceptions.h
new file mode 100644
index 00000000..08c0b0a0
--- /dev/null
+++ b/ext/librethinkdbxx/src/exceptions.h
@@ -0,0 +1,13 @@
+#ifndef EXCEPTIONS_H
+#define EXCEPTIONS_H
+
+namespace RethinkDB {
+
+class TimeoutException : public std::exception {
+public:
+ const char *what() const throw () { return "operation timed out"; }
+};
+
+}
+
+#endif // EXCEPTIONS_H
diff --git a/ext/librethinkdbxx/src/json.cc b/ext/librethinkdbxx/src/json.cc
new file mode 100644
index 00000000..c908eefb
--- /dev/null
+++ b/ext/librethinkdbxx/src/json.cc
@@ -0,0 +1,62 @@
+#include "json_p.h"
+#include "error.h"
+#include "utils.h"
+
+#include "rapidjson-config.h"
+#include "rapidjson/document.h"
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
+#include "rapidjson/prettywriter.h"
+
+namespace RethinkDB {
+
+Datum read_datum(const std::string& json) {
+ rapidjson::Document document;
+ document.Parse(json);
+ return read_datum(document);
+}
+
+Datum read_datum(const rapidjson::Value &json) {
+ switch(json.GetType()) {
+ case rapidjson::kNullType: return Nil();
+ case rapidjson::kFalseType: return false;
+ case rapidjson::kTrueType: return true;
+ case rapidjson::kNumberType: return json.GetDouble();
+ case rapidjson::kStringType:
+ return std::string(json.GetString(), json.GetStringLength());
+
+ case rapidjson::kObjectType: {
+ Object result;
+ for (rapidjson::Value::ConstMemberIterator it = json.MemberBegin();
+ it != json.MemberEnd(); ++it) {
+ result.insert(std::make_pair(std::string(it->name.GetString(),
+ it->name.GetStringLength()),
+ read_datum(it->value)));
+ }
+
+ if (result.count("$reql_type$"))
+ return Datum(std::move(result)).from_raw();
+ return std::move(result);
+ } break;
+ case rapidjson::kArrayType: {
+ Array result;
+ result.reserve(json.Size());
+ for (rapidjson::Value::ConstValueIterator it = json.Begin();
+ it != json.End(); ++it) {
+ result.push_back(read_datum(*it));
+ }
+ return std::move(result);
+ } break;
+ default:
+ throw Error("invalid rapidjson value");
+ }
+}
+
+std::string write_datum(const Datum& datum) {
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ datum.write_json(&writer);
+ return std::string(buffer.GetString(), buffer.GetSize());
+}
+
+}
diff --git a/ext/librethinkdbxx/src/json_p.h b/ext/librethinkdbxx/src/json_p.h
new file mode 100644
index 00000000..ebf537a9
--- /dev/null
+++ b/ext/librethinkdbxx/src/json_p.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "datum.h"
+
+namespace rapidjson {
+ class CrtAllocator;
+ template<typename> struct UTF8;
+ template <typename, typename> class GenericValue;
+ template <typename> class MemoryPoolAllocator;
+ typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
+}
+
+namespace RethinkDB {
+
+Datum read_datum(const std::string&);
+Datum read_datum(const rapidjson::Value &json);
+std::string write_datum(const Datum&);
+
+}
diff --git a/ext/librethinkdbxx/src/rapidjson-config.h b/ext/librethinkdbxx/src/rapidjson-config.h
new file mode 100644
index 00000000..320c4048
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson-config.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#define RAPIDJSON_HAS_STDSTRING 1
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag
diff --git a/ext/librethinkdbxx/src/rapidjson/allocators.h b/ext/librethinkdbxx/src/rapidjson/allocators.h
new file mode 100644
index 00000000..c7059697
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/allocators.h
@@ -0,0 +1,263 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ALLOCATORS_H_
+#define RAPIDJSON_ALLOCATORS_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+ \brief Concept for allocating, resizing and freeing memory block.
+
+ Note that Malloc() and Realloc() are non-static but Free() is static.
+
+ So if an allocator need to support Free(), it needs to put its pointer in
+ the header of memory block.
+
+\code
+concept Allocator {
+ static const bool kNeedFree; //!< Whether this allocator needs to call Free().
+
+ // Allocate a memory block.
+ // \param size of the memory block in bytes.
+ // \returns pointer to the memory block.
+ void* Malloc(size_t size);
+
+ // Resize a memory block.
+ // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+ // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+ // \param newSize the new size in bytes.
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+ // Free a memory block.
+ // \param pointer to the memory block. Null pointer is permitted.
+ static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+ \note implements Allocator concept
+*/
+class CrtAllocator {
+public:
+ static const bool kNeedFree = true;
+ void* Malloc(size_t size) {
+ if (size) // behavior of malloc(0) is implementation defined.
+ return std::malloc(size);
+ else
+ return NULL; // standardize to returning NULL.
+ }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ (void)originalSize;
+ if (newSize == 0) {
+ std::free(originalPtr);
+ return NULL;
+ }
+ return std::realloc(originalPtr, newSize);
+ }
+ static void Free(void *ptr) { std::free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks.
+
+ It does not free memory blocks. And Realloc() only allocate new memory.
+
+ The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+ User may also supply a buffer as the first chunk.
+
+ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+ The user-buffer is not deallocated by this allocator.
+
+ \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+ \note implements Allocator concept
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+ static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+ //! Constructor with chunkSize.
+ /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ }
+
+ //! Constructor with user-supplied buffer.
+ /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+ The user buffer will not be deallocated when this allocator is destructed.
+
+ \param buffer User supplied buffer.
+ \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+ \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ RAPIDJSON_ASSERT(buffer != 0);
+ RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+ chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
+ chunkHead_->capacity = size - sizeof(ChunkHeader);
+ chunkHead_->size = 0;
+ chunkHead_->next = 0;
+ }
+
+ //! Destructor.
+ /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+ */
+ ~MemoryPoolAllocator() {
+ Clear();
+ RAPIDJSON_DELETE(ownBaseAllocator_);
+ }
+
+ //! Deallocates all memory chunks, excluding the user-supplied buffer.
+ void Clear() {
+ while (chunkHead_ && chunkHead_ != userBuffer_) {
+ ChunkHeader* next = chunkHead_->next;
+ baseAllocator_->Free(chunkHead_);
+ chunkHead_ = next;
+ }
+ if (chunkHead_ && chunkHead_ == userBuffer_)
+ chunkHead_->size = 0; // Clear user buffer
+ }
+
+ //! Computes the total capacity of allocated memory chunks.
+ /*! \return total capacity in bytes.
+ */
+ size_t Capacity() const {
+ size_t capacity = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ capacity += c->capacity;
+ return capacity;
+ }
+
+ //! Computes the memory blocks allocated.
+ /*! \return total used bytes.
+ */
+ size_t Size() const {
+ size_t size = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ size += c->size;
+ return size;
+ }
+
+ //! Allocates a memory block. (concept Allocator)
+ void* Malloc(size_t size) {
+ if (!size)
+ return NULL;
+
+ size = RAPIDJSON_ALIGN(size);
+ if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+ AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+
+ void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
+ chunkHead_->size += size;
+ return buffer;
+ }
+
+ //! Resizes a memory block (concept Allocator)
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ if (originalPtr == 0)
+ return Malloc(newSize);
+
+ if (newSize == 0)
+ return NULL;
+
+ originalSize = RAPIDJSON_ALIGN(originalSize);
+ newSize = RAPIDJSON_ALIGN(newSize);
+
+ // Do not shrink if new size is smaller than original
+ if (originalSize >= newSize)
+ return originalPtr;
+
+ // Simply expand it if it is the last allocation and there is sufficient space
+ if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
+ size_t increment = static_cast<size_t>(newSize - originalSize);
+ if (chunkHead_->size + increment <= chunkHead_->capacity) {
+ chunkHead_->size += increment;
+ return originalPtr;
+ }
+ }
+
+ // Realloc process: allocate and copy memory, do not free original buffer.
+ void* newBuffer = Malloc(newSize);
+ RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
+ if (originalSize)
+ std::memcpy(newBuffer, originalPtr, originalSize);
+ return newBuffer;
+ }
+
+ //! Frees a memory block (concept Allocator)
+ static void Free(void *ptr) { (void)ptr; } // Do nothing
+
+private:
+ //! Copy constructor is not permitted.
+ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
+ //! Copy assignment operator is not permitted.
+ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
+
+ //! Creates a new chunk.
+ /*! \param capacity Capacity of the chunk in bytes.
+ */
+ void AddChunk(size_t capacity) {
+ if (!baseAllocator_)
+ ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
+ ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity));
+ chunk->capacity = capacity;
+ chunk->size = 0;
+ chunk->next = chunkHead_;
+ chunkHead_ = chunk;
+ }
+
+ static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+ //! Chunk header for perpending to each chunk.
+ /*! Chunks are stored as a singly linked list.
+ */
+ struct ChunkHeader {
+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
+ size_t size; //!< Current size of allocated memory in bytes.
+ ChunkHeader *next; //!< Next chunk in the linked list.
+ };
+
+ ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+ size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
+ void *userBuffer_; //!< User supplied buffer.
+ BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
+ BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/document.h b/ext/librethinkdbxx/src/rapidjson/document.h
new file mode 100644
index 00000000..f7f846f2
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/document.h
@@ -0,0 +1,2575 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+/*! \file document.h */
+
+#include "reader.h"
+#include "internal/meta.h"
+#include "internal/strfunc.h"
+#include "memorystream.h"
+#include "encodedstream.h"
+#include <new> // placement new
+#include <limits>
+
+RAPIDJSON_DIAG_PUSH
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_OFF(effc++)
+#if __GNUC__ >= 6
+RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
+#endif
+#endif // __GNUC__
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include <iterator> // std::iterator, std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// Forward declaration.
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+template <typename Encoding, typename Allocator, typename StackAllocator>
+class GenericDocument;
+
+//! Name-value pair in a JSON object value.
+/*!
+ This class was internal to GenericValue. It used to be a inner struct.
+ But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
+ https://code.google.com/p/rapidjson/issues/detail?id=64
+*/
+template <typename Encoding, typename Allocator>
+struct GenericMember {
+ GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
+ GenericValue<Encoding, Allocator> value; //!< value of member.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericMemberIterator
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+
+//! (Constant) member iterator for a JSON object value
+/*!
+ \tparam Const Is this a constant iterator?
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+
+ This class implements a Random Access Iterator for GenericMember elements
+ of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
+
+ \note This iterator implementation is mainly intended to avoid implicit
+ conversions from iterator values to \c NULL,
+ e.g. from GenericValue::FindMember.
+
+ \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
+ pointer-based implementation, if your platform doesn't provide
+ the C++ <iterator> header.
+
+ \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
+ */
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator
+ : public std::iterator<std::random_access_iterator_tag
+ , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
+
+ friend class GenericValue<Encoding,Allocator>;
+ template <bool, typename, typename> friend class GenericMemberIterator;
+
+ typedef GenericMember<Encoding,Allocator> PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
+
+public:
+ //! Iterator type itself
+ typedef GenericMemberIterator Iterator;
+ //! Constant iterator type
+ typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
+ //! Non-constant iterator type
+ typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
+
+ //! Pointer to (const) GenericMember
+ typedef typename BaseType::pointer Pointer;
+ //! Reference to (const) GenericMember
+ typedef typename BaseType::reference Reference;
+ //! Signed integer type (e.g. \c ptrdiff_t)
+ typedef typename BaseType::difference_type DifferenceType;
+
+ //! Default constructor (singular value)
+ /*! Creates an iterator pointing to no element.
+ \note All operations, except for comparisons, are undefined on such values.
+ */
+ GenericMemberIterator() : ptr_() {}
+
+ //! Iterator conversions to more const
+ /*!
+ \param it (Non-const) iterator to copy from
+
+ Allows the creation of an iterator from another GenericMemberIterator
+ that is "less const". Especially, creating a non-constant iterator
+ from a constant iterator are disabled:
+ \li const -> non-const (not ok)
+ \li const -> const (ok)
+ \li non-const -> const (ok)
+ \li non-const -> non-const (ok)
+
+ \note If the \c Const template parameter is already \c false, this
+ constructor effectively defines a regular copy-constructor.
+ Otherwise, the copy constructor is implicitly defined.
+ */
+ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+ Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
+
+ //! @name stepping
+ //@{
+ Iterator& operator++(){ ++ptr_; return *this; }
+ Iterator& operator--(){ --ptr_; return *this; }
+ Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
+ Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
+ //@}
+
+ //! @name increment/decrement
+ //@{
+ Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
+ Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
+
+ Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
+ Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
+ //@}
+
+ //! @name relations
+ //@{
+ bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
+ bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
+ bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
+ bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
+ bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
+ bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
+ //@}
+
+ //! @name dereference
+ //@{
+ Reference operator*() const { return *ptr_; }
+ Pointer operator->() const { return ptr_; }
+ Reference operator[](DifferenceType n) const { return ptr_[n]; }
+ //@}
+
+ //! Distance
+ DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
+
+private:
+ //! Internal constructor from plain pointer
+ explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
+
+ Pointer ptr_; //!< raw pointer
+};
+
+#else // RAPIDJSON_NOMEMBERITERATORCLASS
+
+// class-based member iterator implementation disabled, use plain pointers
+
+template <bool Const, typename Encoding, typename Allocator>
+struct GenericMemberIterator;
+
+//! non-const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<false,Encoding,Allocator> {
+ //! use plain pointer as iterator type
+ typedef GenericMember<Encoding,Allocator>* Iterator;
+};
+//! const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<true,Encoding,Allocator> {
+ //! use plain const pointer as iterator type
+ typedef const GenericMember<Encoding,Allocator>* Iterator;
+};
+
+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericStringRef
+
+//! Reference to a constant string (not taking a copy)
+/*!
+ \tparam CharType character type of the string
+
+ This helper class is used to automatically infer constant string
+ references for string literals, especially from \c const \b (!)
+ character arrays.
+
+ The main use is for creating JSON string values without copying the
+ source string via an \ref Allocator. This requires that the referenced
+ string pointers have a sufficient lifetime, which exceeds the lifetime
+ of the associated GenericValue.
+
+ \b Example
+ \code
+ Value v("foo"); // ok, no need to copy & calculate length
+ const char foo[] = "foo";
+ v.SetString(foo); // ok
+
+ const char* bar = foo;
+ // Value x(bar); // not ok, can't rely on bar's lifetime
+ Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
+ Value y(StringRef(bar, 3)); // ok, explicitly pass length
+ \endcode
+
+ \see StringRef, GenericValue::SetString
+*/
+template<typename CharType>
+struct GenericStringRef {
+ typedef CharType Ch; //!< character type of the string
+
+ //! Create string reference from \c const character array
+#ifndef __clang__ // -Wdocumentation
+ /*!
+ This constructor implicitly creates a constant string reference from
+ a \c const character array. It has better performance than
+ \ref StringRef(const CharType*) by inferring the string \ref length
+ from the array length, and also supports strings containing null
+ characters.
+
+ \tparam N length of the string, automatically inferred
+
+ \param str Constant character array, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note Constant complexity.
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+#endif
+ template<SizeType N>
+ GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
+ : s(str), length(N-1) {}
+
+ //! Explicitly create string reference from \c const character pointer
+#ifndef __clang__ // -Wdocumentation
+ /*!
+ This constructor can be used to \b explicitly create a reference to
+ a constant string pointer.
+
+ \see StringRef(const CharType*)
+
+ \param str Constant character pointer, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+#endif
+ explicit GenericStringRef(const CharType* str)
+ : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); }
+
+ //! Create constant string reference from pointer and length
+#ifndef __clang__ // -Wdocumentation
+ /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param len length of the string, excluding the trailing NULL terminator
+
+ \post \ref s == str && \ref length == len
+ \note Constant complexity.
+ */
+#endif
+ GenericStringRef(const CharType* str, SizeType len)
+ : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); }
+
+ GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
+
+ GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
+
+ //! implicit conversion to plain CharType pointer
+ operator const Ch *() const { return s; }
+
+ const Ch* const s; //!< plain CharType pointer
+ const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
+
+private:
+ //! Disallow construction from non-const array
+ template<SizeType N>
+ GenericStringRef(CharType (&str)[N]) /* = delete */;
+};
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+ \tparam CharType Character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+
+ \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str) {
+ return GenericStringRef<CharType>(str, internal::StrLen(str));
+}
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ This version has better performance with supplied length, and also
+ supports string containing null characters.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param length The length of source string.
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
+ return GenericStringRef<CharType>(str, SizeType(length));
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+//! Mark a string object as constant string
+/*! Mark a string object (e.g. \c std::string) as a "string literal".
+ This function can be used to avoid copying a string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
+ return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue type traits
+namespace internal {
+
+template <typename T, typename Encoding = void, typename Allocator = void>
+struct IsGenericValueImpl : FalseType {};
+
+// select candidates according to nested encoding and allocator types
+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
+ : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
+
+// helper to match arbitrary GenericValue instantiations, including derived classes
+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// TypeHelper
+
+namespace internal {
+
+template <typename ValueType, typename T>
+struct TypeHelper {};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, bool> {
+ static bool Is(const ValueType& v) { return v.IsBool(); }
+ static bool Get(const ValueType& v) { return v.GetBool(); }
+ static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
+ static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, int> {
+ static bool Is(const ValueType& v) { return v.IsInt(); }
+ static int Get(const ValueType& v) { return v.GetInt(); }
+ static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
+ static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, unsigned> {
+ static bool Is(const ValueType& v) { return v.IsUint(); }
+ static unsigned Get(const ValueType& v) { return v.GetUint(); }
+ static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
+ static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, int64_t> {
+ static bool Is(const ValueType& v) { return v.IsInt64(); }
+ static int64_t Get(const ValueType& v) { return v.GetInt64(); }
+ static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
+ static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, uint64_t> {
+ static bool Is(const ValueType& v) { return v.IsUint64(); }
+ static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
+ static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
+ static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, double> {
+ static bool Is(const ValueType& v) { return v.IsDouble(); }
+ static double Get(const ValueType& v) { return v.GetDouble(); }
+ static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
+ static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, float> {
+ static bool Is(const ValueType& v) { return v.IsFloat(); }
+ static float Get(const ValueType& v) { return v.GetFloat(); }
+ static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
+ static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, const typename ValueType::Ch*> {
+ typedef const typename ValueType::Ch* StringType;
+ static bool Is(const ValueType& v) { return v.IsString(); }
+ static StringType Get(const ValueType& v) { return v.GetString(); }
+ static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
+ static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
+};
+
+#if RAPIDJSON_HAS_STDSTRING
+template<typename ValueType>
+struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
+ typedef std::basic_string<typename ValueType::Ch> StringType;
+ static bool Is(const ValueType& v) { return v.IsString(); }
+ static StringType Get(const ValueType& v) { return v.GetString(); }
+ static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
+};
+#endif
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::Array> {
+ typedef typename ValueType::Array ArrayType;
+ static bool Is(const ValueType& v) { return v.IsArray(); }
+ static ArrayType Get(ValueType& v) { return v.GetArray(); }
+ static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
+ static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::ConstArray> {
+ typedef typename ValueType::ConstArray ArrayType;
+ static bool Is(const ValueType& v) { return v.IsArray(); }
+ static ArrayType Get(const ValueType& v) { return v.GetArray(); }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::Object> {
+ typedef typename ValueType::Object ObjectType;
+ static bool Is(const ValueType& v) { return v.IsObject(); }
+ static ObjectType Get(ValueType& v) { return v.GetObject(); }
+ static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
+ static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; }
+};
+
+template<typename ValueType>
+struct TypeHelper<ValueType, typename ValueType::ConstObject> {
+ typedef typename ValueType::ConstObject ObjectType;
+ static bool Is(const ValueType& v) { return v.IsObject(); }
+ static ObjectType Get(const ValueType& v) { return v.GetObject(); }
+};
+
+} // namespace internal
+
+// Forward declarations
+template <bool, typename> class GenericArray;
+template <bool, typename> class GenericObject;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+ A JSON value can be one of 7 types. This class is a variant type supporting
+ these types.
+
+ Use the Value if UTF8 and default allocator
+
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericValue {
+public:
+ //! Name-value pair in an object.
+ typedef GenericMember<Encoding, Allocator> Member;
+ typedef Encoding EncodingType; //!< Encoding type from template parameter.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
+ typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
+ typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
+ typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
+ typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
+ typedef GenericArray<false, ValueType> Array;
+ typedef GenericArray<true, ValueType> ConstArray;
+ typedef GenericObject<false, ValueType> Object;
+ typedef GenericObject<true, ValueType> ConstObject;
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor creates a null value.
+ GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
+ rhs.data_.f.flags = kNullFlag; // give up contents
+ }
+#endif
+
+private:
+ //! Copy constructor is not permitted.
+ GenericValue(const GenericValue& rhs);
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Moving from a GenericDocument is not permitted.
+ template <typename StackAllocator>
+ GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
+
+ //! Move assignment from a GenericDocument is not permitted.
+ template <typename StackAllocator>
+ GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
+#endif
+
+public:
+
+ //! Constructor with JSON value type.
+ /*! This creates a Value of specified type with default content.
+ \param type Type of the value.
+ \note Default content for number is zero.
+ */
+ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
+ static const uint16_t defaultFlags[7] = {
+ kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
+ kNumberAnyFlag
+ };
+ RAPIDJSON_ASSERT(type <= kNumberType);
+ data_.f.flags = defaultFlags[type];
+
+ // Use ShortString to store empty string.
+ if (type == kStringType)
+ data_.ss.SetLength(0);
+ }
+
+ //! Explicit copy constructor (with allocator)
+ /*! Creates a copy of a Value by using the given Allocator
+ \tparam SourceAllocator allocator of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
+ \see CopyFrom()
+ */
+ template< typename SourceAllocator >
+ GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+
+ //! Constructor for boolean value.
+ /*! \param b Boolean value
+ \note This constructor is limited to \em real boolean values and rejects
+ implicitly converted types like arbitrary pointers. Use an explicit cast
+ to \c bool, if you want to construct a boolean JSON value in such cases.
+ */
+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
+ template <typename T>
+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
+#else
+ explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
+#endif
+ : data_() {
+ // safe-guard against failing SFINAE
+ RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+ data_.f.flags = b ? kTrueFlag : kFalseFlag;
+ }
+
+ //! Constructor for int value.
+ explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.i64 = i;
+ data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
+ }
+
+ //! Constructor for unsigned value.
+ explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.u64 = u;
+ data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
+ }
+
+ //! Constructor for int64_t value.
+ explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.i64 = i64;
+ data_.f.flags = kNumberInt64Flag;
+ if (i64 >= 0) {
+ data_.f.flags |= kNumberUint64Flag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ data_.f.flags |= kUintFlag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ data_.f.flags |= kIntFlag;
+ }
+ else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ data_.f.flags |= kIntFlag;
+ }
+
+ //! Constructor for uint64_t value.
+ explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
+ data_.n.u64 = u64;
+ data_.f.flags = kNumberUint64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+ data_.f.flags |= kInt64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ data_.f.flags |= kUintFlag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ data_.f.flags |= kIntFlag;
+ }
+
+ //! Constructor for double value.
+ explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor for copy-string from a string object (i.e. do make a copy of string)
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
+#endif
+
+ //! Constructor for Array.
+ /*!
+ \param a An array obtained by \c GetArray().
+ \note \c Array is always pass-by-value.
+ \note the source array is moved into this value and the sourec array becomes empty.
+ */
+ GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
+ a.value_.data_ = Data();
+ a.value_.data_.f.flags = kArrayFlag;
+ }
+
+ //! Constructor for Object.
+ /*!
+ \param o An object obtained by \c GetObject().
+ \note \c Object is always pass-by-value.
+ \note the source object is moved into this value and the sourec object becomes empty.
+ */
+ GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
+ o.value_.data_ = Data();
+ o.value_.data_.f.flags = kObjectFlag;
+ }
+
+ //! Destructor.
+ /*! Need to destruct elements of array, members of object, or copy-string.
+ */
+ ~GenericValue() {
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+ switch(data_.f.flags) {
+ case kArrayFlag:
+ {
+ GenericValue* e = GetElementsPointer();
+ for (GenericValue* v = e; v != e + data_.a.size; ++v)
+ v->~GenericValue();
+ Allocator::Free(e);
+ }
+ break;
+
+ case kObjectFlag:
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ Allocator::Free(GetMembersPointer());
+ break;
+
+ case kCopyStringFlag:
+ Allocator::Free(const_cast<Ch*>(GetStringPointer()));
+ break;
+
+ default:
+ break; // Do nothing for other types.
+ }
+ }
+ }
+
+ //@}
+
+ //!@name Assignment operators
+ //@{
+
+ //! Assignment with move semantics.
+ /*! \param rhs Source of the assignment. It will become a null value after assignment.
+ */
+ GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_ASSERT(this != &rhs);
+ this->~GenericValue();
+ RawAssign(rhs);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+ return *this = rhs.Move();
+ }
+#endif
+
+ //! Assignment of constant string reference (no copy)
+ /*! \param str Constant string reference to be assigned
+ \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
+ \see GenericStringRef, operator=(T)
+ */
+ GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
+ GenericValue s(str);
+ return *this = s;
+ }
+
+ //! Assignment with primitive types.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value The value to be assigned.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref SetString(const Ch*, Allocator&) (for copying) or
+ \ref StringRef() (to explicitly mark the pointer as constant) instead.
+ All other pointer types would implicitly convert to \c bool,
+ use \ref SetBool() instead.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
+ operator=(T value) {
+ GenericValue v(value);
+ return *this = v;
+ }
+
+ //! Deep-copy assignment from Value
+ /*! Assigns a \b copy of the Value to the current Value object
+ \tparam SourceAllocator Allocator type of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator to use for copying
+ */
+ template <typename SourceAllocator>
+ GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
+ RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
+ this->~GenericValue();
+ new (this) GenericValue(rhs, allocator);
+ return *this;
+ }
+
+ //! Exchange the contents of this value with those of other.
+ /*!
+ \param other Another value.
+ \note Constant complexity.
+ */
+ GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
+ GenericValue temp;
+ temp.RawAssign(*this);
+ RawAssign(other);
+ other.RawAssign(temp);
+ return *this;
+ }
+
+ //! free-standing swap function helper
+ /*!
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
+ \code
+ void swap(MyClass& a, MyClass& b) {
+ using std::swap;
+ swap(a.value, b.value);
+ // ...
+ }
+ \endcode
+ \see Swap()
+ */
+ friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+
+ //! Prepare Value for move semantics
+ /*! \return *this */
+ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
+ //@}
+
+ //!@name Equal-to and not-equal-to operators
+ //@{
+ //! Equal-to operator
+ /*!
+ \note If an object contains duplicated named member, comparing equality with any object is always \c false.
+ \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
+ */
+ template <typename SourceAllocator>
+ bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ typedef GenericValue<Encoding, SourceAllocator> RhsType;
+ if (GetType() != rhs.GetType())
+ return false;
+
+ switch (GetType()) {
+ case kObjectType: // Warning: O(n^2) inner-loop
+ if (data_.o.size != rhs.data_.o.size)
+ return false;
+ for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
+ typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
+ if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
+ return false;
+ }
+ return true;
+
+ case kArrayType:
+ if (data_.a.size != rhs.data_.a.size)
+ return false;
+ for (SizeType i = 0; i < data_.a.size; i++)
+ if ((*this)[i] != rhs[i])
+ return false;
+ return true;
+
+ case kStringType:
+ return StringEqual(rhs);
+
+ case kNumberType:
+ if (IsDouble() || rhs.IsDouble()) {
+ double a = GetDouble(); // May convert from integer to double.
+ double b = rhs.GetDouble(); // Ditto
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
+ else
+ return data_.n.u64 == rhs.data_.n.u64;
+
+ default:
+ return true;
+ }
+ }
+
+ //! Equal-to operator with const C-string pointer
+ bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Equal-to operator with string object
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
+#endif
+
+ //! Equal-to operator with primitive types
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
+
+ //! Not-equal-to operator
+ /*! \return !(*this == rhs)
+ */
+ template <typename SourceAllocator>
+ bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with const C-string pointer
+ bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with arbitrary types
+ /*! \return !(*this == rhs)
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
+
+ //! Equal-to operator with arbitrary types (symmetric version)
+ /*! \return (rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
+
+ //! Not-Equal-to operator with arbitrary types (symmetric version)
+ /*! \return !(rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
+ //@}
+
+ //!@name Type
+ //@{
+
+ Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); }
+ bool IsNull() const { return data_.f.flags == kNullFlag; }
+ bool IsFalse() const { return data_.f.flags == kFalseFlag; }
+ bool IsTrue() const { return data_.f.flags == kTrueFlag; }
+ bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
+ bool IsObject() const { return data_.f.flags == kObjectFlag; }
+ bool IsArray() const { return data_.f.flags == kArrayFlag; }
+ bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
+ bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
+ bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
+ bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
+ bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
+ bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
+ bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
+
+ // Checks whether a number can be losslessly converted to a double.
+ bool IsLosslessDouble() const {
+ if (!IsNumber()) return false;
+ if (IsUint64()) {
+ uint64_t u = GetUint64();
+ volatile double d = static_cast<double>(u);
+ return (d >= 0.0)
+ && (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
+ && (u == static_cast<uint64_t>(d));
+ }
+ if (IsInt64()) {
+ int64_t i = GetInt64();
+ volatile double d = static_cast<double>(i);
+ return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
+ && (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
+ && (i == static_cast<int64_t>(d));
+ }
+ return true; // double, int, uint are always lossless
+ }
+
+ // Checks whether a number is a float (possible lossy).
+ bool IsFloat() const {
+ if ((data_.f.flags & kDoubleFlag) == 0)
+ return false;
+ double d = GetDouble();
+ return d >= -3.4028234e38 && d <= 3.4028234e38;
+ }
+ // Checks whether a number can be losslessly converted to a float.
+ bool IsLosslessFloat() const {
+ if (!IsNumber()) return false;
+ double a = GetDouble();
+ if (a < static_cast<double>(-std::numeric_limits<float>::max())
+ || a > static_cast<double>(std::numeric_limits<float>::max()))
+ return false;
+ double b = static_cast<double>(static_cast<float>(a));
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
+
+ //@}
+
+ //!@name Null
+ //@{
+
+ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+ //@}
+
+ //!@name Bool
+ //@{
+
+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
+ //!< Set boolean value
+ /*! \post IsBool() == true */
+ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+ //@}
+
+ //!@name Object
+ //@{
+
+ //! Set this value as an empty object.
+ /*! \post IsObject() == true */
+ GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+ //! Get the number of members in the object.
+ SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
+
+ //! Check whether the object is empty.
+ bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
+ \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
+ Since 0.2, if the name is not correct, it will assert.
+ If user is unsure whether a member exists, user should use HasMember() first.
+ A better approach is to use FindMember().
+ \note Linear time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
+ GenericValue n(StringRef(name));
+ return (*this)[n];
+ }
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam SourceAllocator Allocator of the \c name value
+
+ \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
+ And it can also handle strings with embedded null characters.
+
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator member = FindMember(name);
+ if (member != MemberEnd())
+ return member->value;
+ else {
+ RAPIDJSON_ASSERT(false); // see above note
+
+ // This will generate -Wexit-time-destructors in clang
+ // static GenericValue NullValue;
+ // return NullValue;
+
+ // Use static buffer and placement-new to prevent destruction
+ static char buffer[sizeof(GenericValue)];
+ return *new (buffer) GenericValue();
+ }
+ }
+ template <typename SourceAllocator>
+ const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Get a value from an object associated with name (string object).
+ GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
+ const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
+#endif
+
+ //! Const member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
+ //! Const \em past-the-end member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
+ //! Member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
+ //! \em Past-the-end member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
+
+ //! Check whether a member exists in the object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Check whether a member exists in the object with string object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
+#endif
+
+ //! Check whether a member exists in the object with GenericValue name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
+
+ //! Find member by name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ MemberIterator FindMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return FindMember(n);
+ }
+
+ ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+ //! Find member by name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+ MemberIterator member = MemberBegin();
+ for ( ; member != MemberEnd(); ++member)
+ if (name.StringEqual(member->name))
+ break;
+ return member;
+ }
+ template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Find member by string object name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+ */
+ MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
+ ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
+#endif
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c name and \c value will be transferred to this object on success.
+ \pre IsObject() && name.IsString()
+ \post name.IsNull() && value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+
+ ObjectData& o = data_.o;
+ if (o.size >= o.capacity) {
+ if (o.capacity == 0) {
+ o.capacity = kDefaultObjectCapacity;
+ SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))));
+ }
+ else {
+ SizeType oldCapacity = o.capacity;
+ o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
+ SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
+ }
+ }
+ Member* members = GetMembersPointer();
+ members[o.size].name.RawAssign(name);
+ members[o.size].value.RawAssign(value);
+ o.size++;
+ return *this;
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Add a string object as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
+ GenericValue v(value, allocator);
+ return AddMember(name, v, allocator);
+ }
+#endif
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A string value as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(GenericValue& name, T value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this object on success.
+ \pre IsObject()
+ \post value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A constant string reference as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(StringRefType name, T value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Remove all members in the object.
+ /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void RemoveAllMembers() {
+ RAPIDJSON_ASSERT(IsObject());
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ data_.o.size = 0;
+ }
+
+ //! Remove a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Linear time complexity.
+ */
+ bool RemoveMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return RemoveMember(n);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
+#endif
+
+ template <typename SourceAllocator>
+ bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ RemoveMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Remove a member in object by iterator.
+ /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
+ \return the new iterator after removal.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Constant time complexity.
+ */
+ MemberIterator RemoveMember(MemberIterator m) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(GetMembersPointer() != 0);
+ RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
+
+ MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
+ if (data_.o.size > 1 && m != last)
+ *m = *last; // Move the last one to this place
+ else
+ m->~Member(); // Only one left, just destroy
+ --data_.o.size;
+ return m;
+ }
+
+ //! Remove a member from an object by iterator.
+ /*! \param pos iterator to the member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
+ \return Iterator following the removed element.
+ If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
+ \note This function preserves the relative order of the remaining object
+ members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator pos) {
+ return EraseMember(pos, pos +1);
+ }
+
+ //! Remove members in the range [first, last) from an object.
+ /*! \param first iterator to the first member to remove
+ \param last iterator following the last member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
+ \return Iterator following the last removed element.
+ \note This function preserves the relative order of the remaining object
+ members.
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(GetMembersPointer() != 0);
+ RAPIDJSON_ASSERT(first >= MemberBegin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= MemberEnd());
+
+ MemberIterator pos = MemberBegin() + (first - MemberBegin());
+ for (MemberIterator itr = pos; itr != last; ++itr)
+ itr->~Member();
+ std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
+ data_.o.size -= static_cast<SizeType>(last - first);
+ return pos;
+ }
+
+ //! Erase a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note Linear time complexity.
+ */
+ bool EraseMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return EraseMember(n);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
+#endif
+
+ template <typename SourceAllocator>
+ bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ EraseMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
+ ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Set this value as an empty array.
+ /*! \post IsArray == true */
+ GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+ //! Get the number of elements in array.
+ SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+ //! Get the capacity of array.
+ SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+ //! Check whether the array is empty.
+ bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+ //! Remove all elements in the array.
+ /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void Clear() {
+ RAPIDJSON_ASSERT(IsArray());
+ GenericValue* e = GetElementsPointer();
+ for (GenericValue* v = e; v != e + data_.a.size; ++v)
+ v->~GenericValue();
+ data_.a.size = 0;
+ }
+
+ //! Get an element from array by index.
+ /*! \pre IsArray() == true
+ \param index Zero-based index of element.
+ \see operator[](T*)
+ */
+ GenericValue& operator[](SizeType index) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(index < data_.a.size);
+ return GetElementsPointer()[index];
+ }
+ const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+ //! Element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
+ //! \em Past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
+ //! Constant element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+ //! Constant \em past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+ //! Request the array to have enough capacity to store elements.
+ /*! \param newCapacity The capacity that the array at least need to have.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note Linear time complexity.
+ */
+ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (newCapacity > data_.a.capacity) {
+ SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
+ data_.a.capacity = newCapacity;
+ }
+ return *this;
+ }
+
+ //! Append a GenericValue at the end of the array.
+ /*! \param value Value to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \post value.IsNull() == true
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this array on success.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ */
+ GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (data_.a.size >= data_.a.capacity)
+ Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
+ GetElementsPointer()[data_.a.size++].RawAssign(value);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
+ return PushBack(value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+ //! Append a constant string reference at the end of the array.
+ /*! \param value Constant string reference to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ \see GenericStringRef
+ */
+ GenericValue& PushBack(StringRefType value, Allocator& allocator) {
+ return (*this).template PushBack<StringRefType>(value, allocator);
+ }
+
+ //! Append a primitive value at the end of the array.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value Value of primitive type T to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref PushBack(GenericValue&, Allocator&) or \ref
+ PushBack(StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ PushBack(T value, Allocator& allocator) {
+ GenericValue v(value);
+ return PushBack(v, allocator);
+ }
+
+ //! Remove the last element in the array.
+ /*!
+ \note Constant time complexity.
+ */
+ GenericValue& PopBack() {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(!Empty());
+ GetElementsPointer()[--data_.a.size].~GenericValue();
+ return *this;
+ }
+
+ //! Remove an element of array by iterator.
+ /*!
+ \param pos iterator to the element to remove
+ \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
+ \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator pos) {
+ return Erase(pos, pos + 1);
+ }
+
+ //! Remove elements in the range [first, last) of the array.
+ /*!
+ \param first iterator to the first element to remove
+ \param last iterator following the last element to remove
+ \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
+ \return Iterator following the last removed element.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(data_.a.size > 0);
+ RAPIDJSON_ASSERT(GetElementsPointer() != 0);
+ RAPIDJSON_ASSERT(first >= Begin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= End());
+ ValueIterator pos = Begin() + (first - Begin());
+ for (ValueIterator itr = pos; itr != last; ++itr)
+ itr->~GenericValue();
+ std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
+ data_.a.size -= static_cast<SizeType>(last - first);
+ return pos;
+ }
+
+ Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
+ ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
+
+ //@}
+
+ //!@name Number
+ //@{
+
+ int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
+ unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
+ int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
+
+ //! Get the value as double type.
+ /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
+ */
+ double GetDouble() const {
+ RAPIDJSON_ASSERT(IsNumber());
+ if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
+ if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
+ if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
+ if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
+ RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
+ }
+
+ //! Get the value as float type.
+ /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
+ */
+ float GetFloat() const {
+ return static_cast<float>(GetDouble());
+ }
+
+ GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
+ GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
+ GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
+ GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
+ GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
+ GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
+
+ //@}
+
+ //!@name String
+ //@{
+
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
+
+ //! Get the length of string.
+ /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+ */
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
+
+ //! Set this value as a string without copying source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string pointer.
+ \param length The length of source string, excluding the trailing null terminator.
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == length
+ \see SetString(StringRefType)
+ */
+ GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
+
+ //! Set this value as a string without copying source string.
+ /*! \param s source string reference
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == s.length
+ */
+ GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string.
+ \param length The length of source string, excluding the trailing null terminator.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
+#endif
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Templated version for checking whether this value is type T.
+ /*!
+ \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
+ */
+ template <typename T>
+ bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
+
+ template <typename T>
+ T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
+
+ template <typename T>
+ T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
+
+ template<typename T>
+ ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
+
+ template<typename T>
+ ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
+
+ //@}
+
+ //! Generate events of this value to a Handler.
+ /*! This function adopts the GoF visitor pattern.
+ Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+ It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+ \tparam Handler type of handler.
+ \param handler An object implementing concept Handler.
+ */
+ template <typename Handler>
+ bool Accept(Handler& handler) const {
+ switch(GetType()) {
+ case kNullType: return handler.Null();
+ case kFalseType: return handler.Bool(false);
+ case kTrueType: return handler.Bool(true);
+
+ case kObjectType:
+ if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
+ return false;
+ for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
+ RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
+ if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
+ return false;
+ if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
+ return false;
+ }
+ return handler.EndObject(data_.o.size);
+
+ case kArrayType:
+ if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
+ return false;
+ for (const GenericValue* v = Begin(); v != End(); ++v)
+ if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
+ return false;
+ return handler.EndArray(data_.a.size);
+
+ case kStringType:
+ return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
+
+ default:
+ RAPIDJSON_ASSERT(GetType() == kNumberType);
+ if (IsDouble()) return handler.Double(data_.n.d);
+ else if (IsInt()) return handler.Int(data_.n.i.i);
+ else if (IsUint()) return handler.Uint(data_.n.u.u);
+ else if (IsInt64()) return handler.Int64(data_.n.i64);
+ else return handler.Uint64(data_.n.u64);
+ }
+ }
+
+private:
+ template <typename, typename> friend class GenericValue;
+ template <typename, typename, typename> friend class GenericDocument;
+
+ enum {
+ kBoolFlag = 0x0008,
+ kNumberFlag = 0x0010,
+ kIntFlag = 0x0020,
+ kUintFlag = 0x0040,
+ kInt64Flag = 0x0080,
+ kUint64Flag = 0x0100,
+ kDoubleFlag = 0x0200,
+ kStringFlag = 0x0400,
+ kCopyFlag = 0x0800,
+ kInlineStrFlag = 0x1000,
+
+ // Initial flags of different types.
+ kNullFlag = kNullType,
+ kTrueFlag = kTrueType | kBoolFlag,
+ kFalseFlag = kFalseType | kBoolFlag,
+ kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+ kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+ kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+ kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+ kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+ kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
+ kConstStringFlag = kStringType | kStringFlag,
+ kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+ kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
+ kObjectFlag = kObjectType,
+ kArrayFlag = kArrayType,
+
+ kTypeMask = 0x07
+ };
+
+ static const SizeType kDefaultArrayCapacity = 16;
+ static const SizeType kDefaultObjectCapacity = 16;
+
+ struct Flag {
+#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
+ char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer
+#elif RAPIDJSON_64BIT
+ char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
+#else
+ char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
+#endif
+ uint16_t flags;
+ };
+
+ struct String {
+ SizeType length;
+ SizeType hashcode; //!< reserved
+ const Ch* str;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
+ // (excluding the terminating zero) and store a value to determine the length of the contained
+ // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
+ // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
+ // the string terminator as well. For getting the string length back from that value just use
+ // "MaxSize - str[LenPos]".
+ // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
+ // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
+ struct ShortString {
+ enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+ Ch str[MaxChars];
+
+ inline static bool Usable(SizeType len) { return (MaxSize >= len); }
+ inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
+ inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); }
+ }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // By using proper binary layout, retrieval of different integer types do not need conversions.
+ union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+ struct I {
+ int i;
+ char padding[4];
+ }i;
+ struct U {
+ unsigned u;
+ char padding2[4];
+ }u;
+#else
+ struct I {
+ char padding[4];
+ int i;
+ }i;
+ struct U {
+ char padding2[4];
+ unsigned u;
+ }u;
+#endif
+ int64_t i64;
+ uint64_t u64;
+ double d;
+ }; // 8 bytes
+
+ struct ObjectData {
+ SizeType size;
+ SizeType capacity;
+ Member* members;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ struct ArrayData {
+ SizeType size;
+ SizeType capacity;
+ GenericValue* elements;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ union Data {
+ String s;
+ ShortString ss;
+ Number n;
+ ObjectData o;
+ ArrayData a;
+ Flag f;
+ }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+ RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
+ RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
+ RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
+ RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
+ RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
+ RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
+
+ // Initialize this value as array with initial data, without calling destructor.
+ void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
+ data_.f.flags = kArrayFlag;
+ if (count) {
+ GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
+ SetElementsPointer(e);
+ std::memcpy(e, values, count * sizeof(GenericValue));
+ }
+ else
+ SetElementsPointer(0);
+ data_.a.size = data_.a.capacity = count;
+ }
+
+ //! Initialize this value as object with initial data, without calling destructor.
+ void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
+ data_.f.flags = kObjectFlag;
+ if (count) {
+ Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
+ SetMembersPointer(m);
+ std::memcpy(m, members, count * sizeof(Member));
+ }
+ else
+ SetMembersPointer(0);
+ data_.o.size = data_.o.capacity = count;
+ }
+
+ //! Initialize this value as constant string, without calling destructor.
+ void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
+ data_.f.flags = kConstStringFlag;
+ SetStringPointer(s);
+ data_.s.length = s.length;
+ }
+
+ //! Initialize this value as copy string with initial data, without calling destructor.
+ void SetStringRaw(StringRefType s, Allocator& allocator) {
+ Ch* str = 0;
+ if (ShortString::Usable(s.length)) {
+ data_.f.flags = kShortStringFlag;
+ data_.ss.SetLength(s.length);
+ str = data_.ss.str;
+ } else {
+ data_.f.flags = kCopyStringFlag;
+ data_.s.length = s.length;
+ str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
+ SetStringPointer(str);
+ }
+ std::memcpy(str, s, s.length * sizeof(Ch));
+ str[s.length] = '\0';
+ }
+
+ //! Assignment without calling destructor
+ void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ data_ = rhs.data_;
+ // data_.f.flags = rhs.data_.f.flags;
+ rhs.data_.f.flags = kNullFlag;
+ }
+
+ template <typename SourceAllocator>
+ bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ RAPIDJSON_ASSERT(IsString());
+ RAPIDJSON_ASSERT(rhs.IsString());
+
+ const SizeType len1 = GetStringLength();
+ const SizeType len2 = rhs.GetStringLength();
+ if(len1 != len2) { return false; }
+
+ const Ch* const str1 = GetString();
+ const Ch* const str2 = rhs.GetString();
+ if(str1 == str2) { return true; } // fast path for constant string
+
+ return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
+ }
+
+ Data data_;
+};
+
+//! GenericValue with UTF8 encoding
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument
+
+//! A document for parsing JSON text as DOM.
+/*!
+ \note implements Handler concept
+ \tparam Encoding Encoding for both parsing and string storage.
+ \tparam Allocator Allocator for allocating memory for the DOM
+ \tparam StackAllocator Allocator for allocating memory for stack during parsing.
+ \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+
+ //! Constructor
+ /*! Creates an empty document of specified type.
+ \param type Mandatory type of object to create.
+ \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+ //! Constructor
+ /*! Creates an empty document which type is Null.
+ \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(std::move(rhs.stack_)),
+ parseResult_(rhs.parseResult_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+ }
+#endif
+
+ ~GenericDocument() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ {
+ // The cast to ValueType is necessary here, because otherwise it would
+ // attempt to call GenericValue's templated assignment operator.
+ ValueType::operator=(std::forward<ValueType>(rhs));
+
+ // Calling the destructor here would prematurely call stack_'s destructor
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = std::move(rhs.stack_);
+ parseResult_ = rhs.parseResult_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+
+ return *this;
+ }
+#endif
+
+ //! Exchange the contents of this document with those of another.
+ /*!
+ \param rhs Another document.
+ \note Constant complexity.
+ \see GenericValue::Swap
+ */
+ GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
+ ValueType::Swap(rhs);
+ stack_.Swap(rhs.stack_);
+ internal::Swap(allocator_, rhs.allocator_);
+ internal::Swap(ownAllocator_, rhs.ownAllocator_);
+ internal::Swap(parseResult_, rhs.parseResult_);
+ return *this;
+ }
+
+ //! free-standing swap function helper
+ /*!
+ Helper function to enable support for common swap implementation pattern based on \c std::swap:
+ \code
+ void swap(MyClass& a, MyClass& b) {
+ using std::swap;
+ swap(a.doc, b.doc);
+ // ...
+ }
+ \endcode
+ \see Swap()
+ */
+ friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
+
+ //! Populate this document by a generator which produces SAX events.
+ /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
+ \param g Generator functor which sends SAX events to the parameter.
+ \return The document itself for fluent API.
+ */
+ template <typename Generator>
+ GenericDocument& Populate(Generator& g) {
+ ClearStackOnExit scope(*this);
+ if (g(*this)) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
+ }
+ return *this;
+ }
+
+ //!@name Parse from stream
+ //!@{
+
+ //! Parse JSON text from an input stream (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam SourceEncoding Encoding of input stream
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
+ stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
+ ClearStackOnExit scope(*this);
+ parseResult_ = reader.template Parse<parseFlags>(is, *this);
+ if (parseResult_) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
+ }
+ return *this;
+ }
+
+ //! Parse JSON text from an input stream
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<parseFlags, Encoding, InputStream>(is);
+ }
+
+ //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
+ }
+ //!@}
+
+ //!@name Parse in-place from mutable string
+ //!@{
+
+ //! Parse JSON text from a mutable string
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& ParseInsitu(Ch* str) {
+ GenericInsituStringStream<Encoding> s(str);
+ return ParseStream<parseFlags | kParseInsituFlag>(s);
+ }
+
+ //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
+ /*! \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ GenericDocument& ParseInsitu(Ch* str) {
+ return ParseInsitu<kParseDefaultFlags>(str);
+ }
+ //!@}
+
+ //!@name Parse from read-only string
+ //!@{
+
+ //! Parse JSON text from a read-only string (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \tparam SourceEncoding Transcoding from input Encoding
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ GenericStringStream<SourceEncoding> s(str);
+ return ParseStream<parseFlags, SourceEncoding>(s);
+ }
+
+ //! Parse JSON text from a read-only string
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<parseFlags, Encoding>(str);
+ }
+
+ //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
+ /*! \param str Read-only zero-terminated string to be parsed.
+ */
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
+ EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
+ ParseStream<parseFlags, SourceEncoding>(is);
+ return *this;
+ }
+
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str, size_t length) {
+ return Parse<parseFlags, Encoding>(str, length);
+ }
+
+ GenericDocument& Parse(const Ch* str, size_t length) {
+ return Parse<kParseDefaultFlags>(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
+ // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
+ return Parse<parseFlags, SourceEncoding>(str.c_str());
+ }
+
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const std::basic_string<Ch>& str) {
+ return Parse<parseFlags, Encoding>(str.c_str());
+ }
+
+ GenericDocument& Parse(const std::basic_string<Ch>& str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+#endif // RAPIDJSON_HAS_STDSTRING
+
+ //!@}
+
+ //!@name Handling parse errors
+ //!@{
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseError() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+ //! Implicit conversion to get the last parse result
+#ifndef __clang // -Wdocumentation
+ /*! \return \ref ParseResult of the last parse operation
+
+ \code
+ Document doc;
+ ParseResult ok = doc.Parse(json);
+ if (!ok)
+ printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
+ \endcode
+ */
+#endif
+ operator ParseResult() const { return parseResult_; }
+ //!@}
+
+ //! Get the allocator of this document.
+ Allocator& GetAllocator() {
+ RAPIDJSON_ASSERT(allocator_);
+ return *allocator_;
+ }
+
+ //! Get the capacity of stack in bytes.
+ size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
+ ~ClearStackOnExit() { d_.ClearStack(); }
+ private:
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ GenericDocument& d_;
+ };
+
+ // callers of the following private Handler functions
+ // template <typename,typename,typename> friend class GenericReader; // for parsing
+ template <typename, typename> friend class GenericValue; // for deep copying
+
+public:
+ // Implementation of Handler
+ bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
+ bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
+ bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ return true;
+ }
+
+ bool String(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ return true;
+ }
+
+ bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
+
+ bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount) {
+ typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+ stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
+ return true;
+ }
+
+ bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
+
+ bool EndArray(SizeType elementCount) {
+ ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+ stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+ return true;
+ }
+
+private:
+ //! Prohibit copying
+ GenericDocument(const GenericDocument&);
+ //! Prohibit assignment
+ GenericDocument& operator=(const GenericDocument&);
+
+ void ClearStack() {
+ if (Allocator::kNeedFree)
+ while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+ (stack_.template Pop<ValueType>(1))->~ValueType();
+ else
+ stack_.Clear();
+ stack_.ShrinkToFit();
+ }
+
+ void Destroy() {
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ static const size_t kDefaultStackCapacity = 1024;
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ internal::Stack<StackAllocator> stack_;
+ ParseResult parseResult_;
+};
+
+//! GenericDocument with UTF8 encoding
+typedef GenericDocument<UTF8<> > Document;
+
+// defined here due to the dependency on GenericDocument
+template <typename Encoding, typename Allocator>
+template <typename SourceAllocator>
+inline
+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
+{
+ switch (rhs.GetType()) {
+ case kObjectType:
+ case kArrayType: { // perform deep copy via SAX Handler
+ GenericDocument<Encoding,Allocator> d(&allocator);
+ rhs.Accept(d);
+ RawAssign(*d.stack_.template Pop<GenericValue>(1));
+ }
+ break;
+ case kStringType:
+ if (rhs.data_.f.flags == kConstStringFlag) {
+ data_.f.flags = rhs.data_.f.flags;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ } else {
+ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+ }
+ break;
+ default:
+ data_.f.flags = rhs.data_.f.flags;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ break;
+ }
+}
+
+//! Helper class for accessing Value of array type.
+/*!
+ Instance of this helper class is obtained by \c GenericValue::GetArray().
+ In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
+*/
+template <bool Const, typename ValueT>
+class GenericArray {
+public:
+ typedef GenericArray<true, ValueT> ConstArray;
+ typedef GenericArray<false, ValueT> Array;
+ typedef ValueT PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef ValueType* ValueIterator; // This may be const or non-const iterator
+ typedef const ValueT* ConstValueIterator;
+ typedef typename ValueType::AllocatorType AllocatorType;
+ typedef typename ValueType::StringRefType StringRefType;
+
+ template <typename, typename>
+ friend class GenericValue;
+
+ GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
+ GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
+ ~GenericArray() {}
+
+ SizeType Size() const { return value_.Size(); }
+ SizeType Capacity() const { return value_.Capacity(); }
+ bool Empty() const { return value_.Empty(); }
+ void Clear() const { value_.Clear(); }
+ ValueType& operator[](SizeType index) const { return value_[index]; }
+ ValueIterator Begin() const { return value_.Begin(); }
+ ValueIterator End() const { return value_.End(); }
+ GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
+ GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
+ GenericArray PopBack() const { value_.PopBack(); return *this; }
+ ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
+
+#if RAPIDJSON_HAS_CXX11_RANGE_FOR
+ ValueIterator begin() const { return value_.Begin(); }
+ ValueIterator end() const { return value_.End(); }
+#endif
+
+private:
+ GenericArray();
+ GenericArray(ValueType& value) : value_(value) {}
+ ValueType& value_;
+};
+
+//! Helper class for accessing Value of object type.
+/*!
+ Instance of this helper class is obtained by \c GenericValue::GetObject().
+ In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
+*/
+template <bool Const, typename ValueT>
+class GenericObject {
+public:
+ typedef GenericObject<true, ValueT> ConstObject;
+ typedef GenericObject<false, ValueT> Object;
+ typedef ValueT PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator
+ typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
+ typedef typename ValueType::AllocatorType AllocatorType;
+ typedef typename ValueType::StringRefType StringRefType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename ValueType::Ch Ch;
+
+ template <typename, typename>
+ friend class GenericValue;
+
+ GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
+ GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
+ ~GenericObject() {}
+
+ SizeType MemberCount() const { return value_.MemberCount(); }
+ bool ObjectEmpty() const { return value_.ObjectEmpty(); }
+ template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
+ template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
+#if RAPIDJSON_HAS_STDSTRING
+ ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
+#endif
+ MemberIterator MemberBegin() const { return value_.MemberBegin(); }
+ MemberIterator MemberEnd() const { return value_.MemberEnd(); }
+ bool HasMember(const Ch* name) const { return value_.HasMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
+#endif
+ template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
+ MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
+ template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
+#endif
+ GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#if RAPIDJSON_HAS_STDSTRING
+ GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#endif
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
+ void RemoveAllMembers() { return value_.RemoveAllMembers(); }
+ bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
+#endif
+ template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
+ MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
+ MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
+ bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
+#if RAPIDJSON_HAS_STDSTRING
+ bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
+#endif
+ template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
+
+#if RAPIDJSON_HAS_CXX11_RANGE_FOR
+ MemberIterator begin() const { return value_.MemberBegin(); }
+ MemberIterator end() const { return value_.MemberEnd(); }
+#endif
+
+private:
+ GenericObject();
+ GenericObject(ValueType& value) : value_(value) {}
+ ValueType& value_;
+};
+
+RAPIDJSON_NAMESPACE_END
+RAPIDJSON_DIAG_POP
+
+#endif // RAPIDJSON_DOCUMENT_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/encodedstream.h b/ext/librethinkdbxx/src/rapidjson/encodedstream.h
new file mode 100644
index 00000000..14506838
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/encodedstream.h
@@ -0,0 +1,299 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
+#define RAPIDJSON_ENCODEDSTREAM_H_
+
+#include "stream.h"
+#include "memorystream.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Input byte stream wrapper with a statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
+*/
+template <typename Encoding, typename InputByteStream>
+class EncodedInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedInputStream(InputByteStream& is) : is_(is) {
+ current_ = Encoding::TakeBOM(is_);
+ }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
+ size_t Tell() const { return is_.Tell(); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+
+ InputByteStream& is_;
+ Ch current_;
+};
+
+//! Specialized for UTF8 MemoryStream.
+template <>
+class EncodedInputStream<UTF8<>, MemoryStream> {
+public:
+ typedef UTF8<>::Ch Ch;
+
+ EncodedInputStream(MemoryStream& is) : is_(is) {
+ if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
+ if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
+ if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
+ }
+ Ch Peek() const { return is_.Peek(); }
+ Ch Take() { return is_.Take(); }
+ size_t Tell() const { return is_.Tell(); }
+
+ // Not implemented
+ void Put(Ch) {}
+ void Flush() {}
+ Ch* PutBegin() { return 0; }
+ size_t PutEnd(Ch*) { return 0; }
+
+ MemoryStream& is_;
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+};
+
+//! Output byte stream wrapper with statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
+*/
+template <typename Encoding, typename OutputByteStream>
+class EncodedOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
+ if (putBOM)
+ Encoding::PutBOM(os_);
+ }
+
+ void Put(Ch c) { Encoding::Put(os_, c); }
+ void Flush() { os_.Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
+ Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ EncodedOutputStream(const EncodedOutputStream&);
+ EncodedOutputStream& operator=(const EncodedOutputStream&);
+
+ OutputByteStream& os_;
+};
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for reading.
+ \tparam InputByteStream type of input byte stream to be wrapped.
+*/
+template <typename CharType, typename InputByteStream>
+class AutoUTFInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param is input stream to be wrapped.
+ \param type UTF encoding type if it is not detected from the stream.
+ */
+ AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+ DetectType();
+ static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
+ takeFunc_ = f[type_];
+ current_ = takeFunc_(*is_);
+ }
+
+ UTFType GetType() const { return type_; }
+ bool HasBOM() const { return hasBOM_; }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
+ size_t Tell() const { return is_->Tell(); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ AutoUTFInputStream(const AutoUTFInputStream&);
+ AutoUTFInputStream& operator=(const AutoUTFInputStream&);
+
+ // Detect encoding type with BOM or RFC 4627
+ void DetectType() {
+ // BOM (Byte Order Mark):
+ // 00 00 FE FF UTF-32BE
+ // FF FE 00 00 UTF-32LE
+ // FE FF UTF-16BE
+ // FF FE UTF-16LE
+ // EF BB BF UTF-8
+
+ const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
+ if (!c)
+ return;
+
+ unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
+ hasBOM_ = false;
+ if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
+
+ // RFC 4627: Section 3
+ // "Since the first two characters of a JSON text will always be ASCII
+ // characters [RFC0020], it is possible to determine whether an octet
+ // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
+ // at the pattern of nulls in the first four octets."
+ // 00 00 00 xx UTF-32BE
+ // 00 xx 00 xx UTF-16BE
+ // xx 00 00 00 UTF-32LE
+ // xx 00 xx 00 UTF-16LE
+ // xx xx xx xx UTF-8
+
+ if (!hasBOM_) {
+ unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
+ switch (pattern) {
+ case 0x08: type_ = kUTF32BE; break;
+ case 0x0A: type_ = kUTF16BE; break;
+ case 0x01: type_ = kUTF32LE; break;
+ case 0x05: type_ = kUTF16LE; break;
+ case 0x0F: type_ = kUTF8; break;
+ default: break; // Use type defined by user.
+ }
+ }
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+ }
+
+ typedef Ch (*TakeFunc)(InputByteStream& is);
+ InputByteStream* is_;
+ UTFType type_;
+ Ch current_;
+ TakeFunc takeFunc_;
+ bool hasBOM_;
+};
+
+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for writing.
+ \tparam OutputByteStream type of output byte stream to be wrapped.
+*/
+template <typename CharType, typename OutputByteStream>
+class AutoUTFOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param os output stream to be wrapped.
+ \param type UTF encoding type.
+ \param putBOM Whether to write BOM at the beginning of the stream.
+ */
+ AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+
+ static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
+ putFunc_ = f[type_];
+
+ if (putBOM)
+ PutBOM();
+ }
+
+ UTFType GetType() const { return type_; }
+
+ void Put(Ch c) { putFunc_(*os_, c); }
+ void Flush() { os_->Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
+ Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ AutoUTFOutputStream(const AutoUTFOutputStream&);
+ AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
+
+ void PutBOM() {
+ typedef void (*PutBOMFunc)(OutputByteStream&);
+ static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
+ f[type_](*os_);
+ }
+
+ typedef void (*PutFunc)(OutputByteStream&, Ch);
+
+ OutputByteStream* os_;
+ UTFType type_;
+ PutFunc putFunc_;
+};
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/encodings.h b/ext/librethinkdbxx/src/rapidjson/encodings.h
new file mode 100644
index 00000000..baa7c2b1
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/encodings.h
@@ -0,0 +1,716 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODINGS_H_
+#define RAPIDJSON_ENCODINGS_H_
+
+#include "rapidjson.h"
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(overflow)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+ \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+ typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
+
+ enum { supportUnicode = 1 }; // or 0 if not supporting unicode
+
+ //! \brief Encode a Unicode codepoint to an output stream.
+ //! \param os Output stream.
+ //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint);
+
+ //! \brief Decode a Unicode codepoint from an input stream.
+ //! \param is Input stream.
+ //! \param codepoint Output of the unicode codepoint.
+ //! \return true if a valid codepoint can be decoded from the stream.
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint);
+
+ //! \brief Validate one Unicode codepoint from an encoded stream.
+ //! \param is Input stream to obtain codepoint.
+ //! \param os Output for copying one codepoint.
+ //! \return true if it is valid.
+ //! \note This function just validating and copying the codepoint without actually decode it.
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os);
+
+ // The following functions are deal with byte streams.
+
+ //! Take a character from input byte stream, skip BOM if exist.
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is);
+
+ //! Take a character from input byte stream.
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is);
+
+ //! Put BOM to output byte stream.
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os);
+
+ //! Put a character to output byte stream.
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+ http://tools.ietf.org/html/rfc3629
+ \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct UTF8 {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ }
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ typename InputStream::Ch c = is.Take();
+ if (!(c & 0x80)) {
+ *codepoint = static_cast<unsigned char>(c);
+ return true;
+ }
+
+ unsigned char type = GetRange(static_cast<unsigned char>(c));
+ if (type >= 32) {
+ *codepoint = 0;
+ } else {
+ *codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
+ }
+ bool result = true;
+ switch (type) {
+ case 2: TAIL(); return result;
+ case 3: TAIL(); TAIL(); return result;
+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+ case 6: TAIL(); TAIL(); TAIL(); return result;
+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+#define COPY() os.Put(c = is.Take())
+#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ Ch c;
+ COPY();
+ if (!(c & 0x80))
+ return true;
+
+ bool result = true;
+ switch (GetRange(static_cast<unsigned char>(c))) {
+ case 2: TAIL(); return result;
+ case 3: TAIL(); TAIL(); return result;
+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
+ case 6: TAIL(); TAIL(); TAIL(); return result;
+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ static unsigned char GetRange(unsigned char c) {
+ // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+ // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
+ static const unsigned char type[] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+ };
+ return type[c];
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ typename InputByteStream::Ch c = Take(is);
+ if (static_cast<unsigned char>(c) != 0xEFu) return c;
+ c = is.Take();
+ if (static_cast<unsigned char>(c) != 0xBBu) return c;
+ c = is.Take();
+ if (static_cast<unsigned char>(c) != 0xBFu) return c;
+ c = is.Take();
+ return c;
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return static_cast<Ch>(is.Take());
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+ http://tools.ietf.org/html/rfc2781
+ \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF16LE and UTF16BE, which handle endianness.
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ os.Put(static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ os.Put((v & 0x3FF) | 0xDC00);
+ }
+ }
+
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ PutUnsafe(os, (v & 0x3FF) | 0xDC00);
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ typename InputStream::Ch c = is.Take();
+ if (c < 0xD800 || c > 0xDFFF) {
+ *codepoint = static_cast<unsigned>(c);
+ return true;
+ }
+ else if (c <= 0xDBFF) {
+ *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
+ c = is.Take();
+ *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
+ *codepoint += 0x10000;
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ typename InputStream::Ch c;
+ os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
+ if (c < 0xD800 || c > 0xDFFF)
+ return true;
+ else if (c <= 0xDBFF) {
+ os.Put(c = is.Take());
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+};
+
+//! UTF-16 little endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16LE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<uint8_t>(is.Take());
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
+ }
+};
+
+//! UTF-16 big endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16BE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<uint8_t>(is.Take());
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-32
+ \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF32LE and UTF32BE, which handle endianness.
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(codepoint);
+ }
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ PutUnsafe(os, codepoint);
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c = is.Take();
+ *codepoint = c;
+ return c <= 0x10FFFF;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c;
+ os.Put(c = is.Take());
+ return c <= 0x10FFFF;
+ }
+};
+
+//! UTF-32 little endian enocoding.
+template<typename CharType = unsigned>
+struct UTF32LE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<uint8_t>(is.Take());
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
+ }
+};
+
+//! UTF-32 big endian encoding.
+template<typename CharType = unsigned>
+struct UTF32BE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
+ c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
+ return static_cast<CharType>(c);
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
+ os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ASCII
+
+//! ASCII encoding.
+/*! http://en.wikipedia.org/wiki/ASCII
+ \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct ASCII {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 0 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ }
+
+ template<typename OutputStream>
+ static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ uint8_t c = static_cast<uint8_t>(is.Take());
+ *codepoint = c;
+ return c <= 0X7F;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ uint8_t c = static_cast<uint8_t>(is.Take());
+ os.Put(static_cast<typename OutputStream::Ch>(c));
+ return c <= 0x7F;
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ uint8_t c = static_cast<uint8_t>(Take(is));
+ return static_cast<Ch>(c);
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return static_cast<Ch>(is.Take());
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ (void)os;
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoUTF
+
+//! Runtime-specified UTF encoding type of a stream.
+enum UTFType {
+ kUTF8 = 0, //!< UTF-8.
+ kUTF16LE = 1, //!< UTF-16 little endian.
+ kUTF16BE = 2, //!< UTF-16 big endian.
+ kUTF32LE = 3, //!< UTF-32 little endian.
+ kUTF32BE = 4 //!< UTF-32 big endian.
+};
+
+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
+*/
+template<typename CharType>
+struct AutoUTF {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+ template<typename OutputStream>
+ RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
+ template<typename OutputStream>
+ RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
+ template <typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+ typedef bool (*DecodeFunc)(InputStream&, unsigned*);
+ static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
+ return (*f[is.GetType()])(is, codepoint);
+ }
+
+ template <typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
+ static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
+ return (*f[is.GetType()])(is, os);
+ }
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Transcoder
+
+//! Encoding conversion.
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder {
+ //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::Encode(os, codepoint);
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::EncodeUnsafe(os, codepoint);
+ return true;
+ }
+
+ //! Validate one Unicode codepoint from an encoded stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Transcode(is, os); // Since source/target encoding is different, must transcode.
+ }
+};
+
+// Forward declaration.
+template<typename Stream>
+inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
+
+//! Specialization of Transcoder with same source and target encoding.
+template<typename Encoding>
+struct Transcoder<Encoding, Encoding> {
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
+ PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Encoding::Validate(is, os); // source/target encoding are the same
+ }
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/error/en.h b/ext/librethinkdbxx/src/rapidjson/error/en.h
new file mode 100644
index 00000000..2db838bf
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/error/en.h
@@ -0,0 +1,74 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ERROR_EN_H_
+#define RAPIDJSON_ERROR_EN_H_
+
+#include "error.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(covered-switch-default)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Maps error code of parsing into error message.
+/*!
+ \ingroup RAPIDJSON_ERRORS
+ \param parseErrorCode Error code obtained in parsing.
+ \return the error message.
+ \note User can make a copy of this function for localization.
+ Using switch-case is safer for future modification of error codes.
+*/
+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
+ switch (parseErrorCode) {
+ case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
+
+ case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
+ case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
+
+ case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
+
+ case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
+ case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
+ case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
+
+ case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
+
+ case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
+ case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
+ case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
+ case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
+ case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
+
+ case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
+ case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
+ case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
+
+ case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
+ case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
+
+ default: return RAPIDJSON_ERROR_STRING("Unknown error.");
+ }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ERROR_EN_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/error/error.h b/ext/librethinkdbxx/src/rapidjson/error/error.h
new file mode 100644
index 00000000..95cb31a7
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/error/error.h
@@ -0,0 +1,155 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ERROR_ERROR_H_
+#define RAPIDJSON_ERROR_ERROR_H_
+
+#include "../rapidjson.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+/*! \file error.h */
+
+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_CHARTYPE
+
+//! Character type of error messages.
+/*! \ingroup RAPIDJSON_ERRORS
+ The default character type is \c char.
+ On Windows, user can define this macro as \c TCHAR for supporting both
+ unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_CHARTYPE
+#define RAPIDJSON_ERROR_CHARTYPE char
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ERROR_STRING
+
+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
+/*! \ingroup RAPIDJSON_ERRORS
+ By default this conversion macro does nothing.
+ On Windows, user can define this macro as \c _T(x) for supporting both
+ unicode/non-unicode settings.
+*/
+#ifndef RAPIDJSON_ERROR_STRING
+#define RAPIDJSON_ERROR_STRING(x) x
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseErrorCode
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+ \see GenericReader::Parse, GenericReader::GetParseErrorCode
+*/
+enum ParseErrorCode {
+ kParseErrorNone = 0, //!< No error.
+
+ kParseErrorDocumentEmpty, //!< The document is empty.
+ kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
+
+ kParseErrorValueInvalid, //!< Invalid value.
+
+ kParseErrorObjectMissName, //!< Missing a name for object member.
+ kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
+ kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
+
+ kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
+
+ kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
+ kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
+ kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
+ kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
+ kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
+
+ kParseErrorNumberTooBig, //!< Number too big to be stored in double.
+ kParseErrorNumberMissFraction, //!< Miss fraction part in number.
+ kParseErrorNumberMissExponent, //!< Miss exponent in number.
+
+ kParseErrorTermination, //!< Parsing was terminated.
+ kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
+};
+
+//! Result of parsing (wraps ParseErrorCode)
+/*!
+ \ingroup RAPIDJSON_ERRORS
+ \code
+ Document doc;
+ ParseResult ok = doc.Parse("[42]");
+ if (!ok) {
+ fprintf(stderr, "JSON parse error: %s (%u)",
+ GetParseError_En(ok.Code()), ok.Offset());
+ exit(EXIT_FAILURE);
+ }
+ \endcode
+ \see GenericReader::Parse, GenericDocument::Parse
+*/
+struct ParseResult {
+public:
+ //! Default constructor, no error.
+ ParseResult() : code_(kParseErrorNone), offset_(0) {}
+ //! Constructor to set an error.
+ ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
+
+ //! Get the error code.
+ ParseErrorCode Code() const { return code_; }
+ //! Get the error offset, if \ref IsError(), 0 otherwise.
+ size_t Offset() const { return offset_; }
+
+ //! Conversion to \c bool, returns \c true, iff !\ref IsError().
+ operator bool() const { return !IsError(); }
+ //! Whether the result is an error.
+ bool IsError() const { return code_ != kParseErrorNone; }
+
+ bool operator==(const ParseResult& that) const { return code_ == that.code_; }
+ bool operator==(ParseErrorCode code) const { return code_ == code; }
+ friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
+
+ //! Reset error code.
+ void Clear() { Set(kParseErrorNone); }
+ //! Update error code and offset.
+ void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
+
+private:
+ ParseErrorCode code_;
+ size_t offset_;
+};
+
+//! Function pointer type of GetParseError().
+/*! \ingroup RAPIDJSON_ERRORS
+
+ This is the prototype for \c GetParseError_X(), where \c X is a locale.
+ User can dynamically change locale in runtime, e.g.:
+\code
+ GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
+ const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
+\endcode
+*/
+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ERROR_ERROR_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/filereadstream.h b/ext/librethinkdbxx/src/rapidjson/filereadstream.h
new file mode 100644
index 00000000..b56ea13b
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/filereadstream.h
@@ -0,0 +1,99 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEREADSTREAM_H_
+#define RAPIDJSON_FILEREADSTREAM_H_
+
+#include "stream.h"
+#include <cstdio>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(missing-noreturn)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! File byte stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileReadStream {
+public:
+ typedef char Ch; //!< Character type (byte).
+
+ //! Constructor.
+ /*!
+ \param fp File pointer opened for read.
+ \param buffer user-supplied buffer.
+ \param bufferSize size of buffer in bytes. Must >=4 bytes.
+ */
+ FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ RAPIDJSON_ASSERT(bufferSize >= 4);
+ Read();
+ }
+
+ Ch Peek() const { return *current_; }
+ Ch Take() { Ch c = *current_; Read(); return c; }
+ size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
+
+ // Not implemented
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ return (current_ + 4 <= bufferLast_) ? current_ : 0;
+ }
+
+private:
+ void Read() {
+ if (current_ < bufferLast_)
+ ++current_;
+ else if (!eof_) {
+ count_ += readCount_;
+ readCount_ = fread(buffer_, 1, bufferSize_, fp_);
+ bufferLast_ = buffer_ + readCount_ - 1;
+ current_ = buffer_;
+
+ if (readCount_ < bufferSize_) {
+ buffer_[readCount_] = '\0';
+ ++bufferLast_;
+ eof_ = true;
+ }
+ }
+ }
+
+ std::FILE* fp_;
+ Ch *buffer_;
+ size_t bufferSize_;
+ Ch *bufferLast_;
+ Ch *current_;
+ size_t readCount_;
+ size_t count_; //!< Number of characters read
+ bool eof_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/filewritestream.h b/ext/librethinkdbxx/src/rapidjson/filewritestream.h
new file mode 100644
index 00000000..6378dd60
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/filewritestream.h
@@ -0,0 +1,104 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
+#define RAPIDJSON_FILEWRITESTREAM_H_
+
+#include "stream.h"
+#include <cstdio>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(unreachable-code)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of C file stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileWriteStream {
+public:
+ typedef char Ch; //!< Character type. Only support char.
+
+ FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ }
+
+ void Put(char c) {
+ if (current_ >= bufferEnd_)
+ Flush();
+
+ *current_++ = c;
+ }
+
+ void PutN(char c, size_t n) {
+ size_t avail = static_cast<size_t>(bufferEnd_ - current_);
+ while (n > avail) {
+ std::memset(current_, c, avail);
+ current_ += avail;
+ Flush();
+ n -= avail;
+ avail = static_cast<size_t>(bufferEnd_ - current_);
+ }
+
+ if (n > 0) {
+ std::memset(current_, c, n);
+ current_ += n;
+ }
+ }
+
+ void Flush() {
+ if (current_ != buffer_) {
+ size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
+ if (result < static_cast<size_t>(current_ - buffer_)) {
+ // failure deliberately ignored at this time
+ // added to avoid warn_unused_result build errors
+ }
+ current_ = buffer_;
+ }
+ }
+
+ // Not implemented
+ char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+ char Take() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ FileWriteStream(const FileWriteStream&);
+ FileWriteStream& operator=(const FileWriteStream&);
+
+ std::FILE* fp_;
+ char *buffer_;
+ char *bufferEnd_;
+ char *current_;
+};
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(FileWriteStream& stream, char c, size_t n) {
+ stream.PutN(c, n);
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/fwd.h b/ext/librethinkdbxx/src/rapidjson/fwd.h
new file mode 100644
index 00000000..e8104e84
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/fwd.h
@@ -0,0 +1,151 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FWD_H_
+#define RAPIDJSON_FWD_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// encodings.h
+
+template<typename CharType> struct UTF8;
+template<typename CharType> struct UTF16;
+template<typename CharType> struct UTF16BE;
+template<typename CharType> struct UTF16LE;
+template<typename CharType> struct UTF32;
+template<typename CharType> struct UTF32BE;
+template<typename CharType> struct UTF32LE;
+template<typename CharType> struct ASCII;
+template<typename CharType> struct AutoUTF;
+
+template<typename SourceEncoding, typename TargetEncoding>
+struct Transcoder;
+
+// allocators.h
+
+class CrtAllocator;
+
+template <typename BaseAllocator>
+class MemoryPoolAllocator;
+
+// stream.h
+
+template <typename Encoding>
+struct GenericStringStream;
+
+typedef GenericStringStream<UTF8<char> > StringStream;
+
+template <typename Encoding>
+struct GenericInsituStringStream;
+
+typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
+
+// stringbuffer.h
+
+template <typename Encoding, typename Allocator>
+class GenericStringBuffer;
+
+typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
+
+// filereadstream.h
+
+class FileReadStream;
+
+// filewritestream.h
+
+class FileWriteStream;
+
+// memorybuffer.h
+
+template <typename Allocator>
+struct GenericMemoryBuffer;
+
+typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
+
+// memorystream.h
+
+struct MemoryStream;
+
+// reader.h
+
+template<typename Encoding, typename Derived>
+struct BaseReaderHandler;
+
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
+class GenericReader;
+
+typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
+
+// writer.h
+
+template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
+class Writer;
+
+// prettywriter.h
+
+template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
+class PrettyWriter;
+
+// document.h
+
+template <typename Encoding, typename Allocator>
+struct GenericMember;
+
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator;
+
+template<typename CharType>
+struct GenericStringRef;
+
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
+
+template <typename Encoding, typename Allocator, typename StackAllocator>
+class GenericDocument;
+
+typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
+
+// pointer.h
+
+template <typename ValueType, typename Allocator>
+class GenericPointer;
+
+typedef GenericPointer<Value, CrtAllocator> Pointer;
+
+// schema.h
+
+template <typename SchemaDocumentType>
+class IGenericRemoteSchemaDocumentProvider;
+
+template <typename ValueT, typename Allocator>
+class GenericSchemaDocument;
+
+typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
+typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
+
+template <
+ typename SchemaDocumentType,
+ typename OutputHandler,
+ typename StateAllocator>
+class GenericSchemaValidator;
+
+typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSONFWD_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/biginteger.h b/ext/librethinkdbxx/src/rapidjson/internal/biginteger.h
new file mode 100644
index 00000000..9d3e88c9
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/biginteger.h
@@ -0,0 +1,290 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_BIGINTEGER_H_
+#define RAPIDJSON_BIGINTEGER_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h> // for _umul128
+#pragma intrinsic(_umul128)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class BigInteger {
+public:
+ typedef uint64_t Type;
+
+ BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+ }
+
+ explicit BigInteger(uint64_t u) : count_(1) {
+ digits_[0] = u;
+ }
+
+ BigInteger(const char* decimals, size_t length) : count_(1) {
+ RAPIDJSON_ASSERT(length > 0);
+ digits_[0] = 0;
+ size_t i = 0;
+ const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
+ while (length >= kMaxDigitPerIteration) {
+ AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
+ length -= kMaxDigitPerIteration;
+ i += kMaxDigitPerIteration;
+ }
+
+ if (length > 0)
+ AppendDecimal64(decimals + i, decimals + i + length);
+ }
+
+ BigInteger& operator=(const BigInteger &rhs)
+ {
+ if (this != &rhs) {
+ count_ = rhs.count_;
+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
+ }
+ return *this;
+ }
+
+ BigInteger& operator=(uint64_t u) {
+ digits_[0] = u;
+ count_ = 1;
+ return *this;
+ }
+
+ BigInteger& operator+=(uint64_t u) {
+ Type backup = digits_[0];
+ digits_[0] += u;
+ for (size_t i = 0; i < count_ - 1; i++) {
+ if (digits_[i] >= backup)
+ return *this; // no carry
+ backup = digits_[i + 1];
+ digits_[i + 1] += 1;
+ }
+
+ // Last carry
+ if (digits_[count_ - 1] < backup)
+ PushBack(1);
+
+ return *this;
+ }
+
+ BigInteger& operator*=(uint64_t u) {
+ if (u == 0) return *this = 0;
+ if (u == 1) return *this;
+ if (*this == 1) return *this = u;
+
+ uint64_t k = 0;
+ for (size_t i = 0; i < count_; i++) {
+ uint64_t hi;
+ digits_[i] = MulAdd64(digits_[i], u, k, &hi);
+ k = hi;
+ }
+
+ if (k > 0)
+ PushBack(k);
+
+ return *this;
+ }
+
+ BigInteger& operator*=(uint32_t u) {
+ if (u == 0) return *this = 0;
+ if (u == 1) return *this;
+ if (*this == 1) return *this = u;
+
+ uint64_t k = 0;
+ for (size_t i = 0; i < count_; i++) {
+ const uint64_t c = digits_[i] >> 32;
+ const uint64_t d = digits_[i] & 0xFFFFFFFF;
+ const uint64_t uc = u * c;
+ const uint64_t ud = u * d;
+ const uint64_t p0 = ud + k;
+ const uint64_t p1 = uc + (p0 >> 32);
+ digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
+ k = p1 >> 32;
+ }
+
+ if (k > 0)
+ PushBack(k);
+
+ return *this;
+ }
+
+ BigInteger& operator<<=(size_t shift) {
+ if (IsZero() || shift == 0) return *this;
+
+ size_t offset = shift / kTypeBit;
+ size_t interShift = shift % kTypeBit;
+ RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
+
+ if (interShift == 0) {
+ std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
+ count_ += offset;
+ }
+ else {
+ digits_[count_] = 0;
+ for (size_t i = count_; i > 0; i--)
+ digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
+ digits_[offset] = digits_[0] << interShift;
+ count_ += offset;
+ if (digits_[count_])
+ count_++;
+ }
+
+ std::memset(digits_, 0, offset * sizeof(Type));
+
+ return *this;
+ }
+
+ bool operator==(const BigInteger& rhs) const {
+ return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
+ }
+
+ bool operator==(const Type rhs) const {
+ return count_ == 1 && digits_[0] == rhs;
+ }
+
+ BigInteger& MultiplyPow5(unsigned exp) {
+ static const uint32_t kPow5[12] = {
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+ if (exp == 0) return *this;
+ for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
+ for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
+ if (exp > 0) *this *= kPow5[exp - 1];
+ return *this;
+ }
+
+ // Compute absolute difference of this and rhs.
+ // Assume this != rhs
+ bool Difference(const BigInteger& rhs, BigInteger* out) const {
+ int cmp = Compare(rhs);
+ RAPIDJSON_ASSERT(cmp != 0);
+ const BigInteger *a, *b; // Makes a > b
+ bool ret;
+ if (cmp < 0) { a = &rhs; b = this; ret = true; }
+ else { a = this; b = &rhs; ret = false; }
+
+ Type borrow = 0;
+ for (size_t i = 0; i < a->count_; i++) {
+ Type d = a->digits_[i] - borrow;
+ if (i < b->count_)
+ d -= b->digits_[i];
+ borrow = (d > a->digits_[i]) ? 1 : 0;
+ out->digits_[i] = d;
+ if (d != 0)
+ out->count_ = i + 1;
+ }
+
+ return ret;
+ }
+
+ int Compare(const BigInteger& rhs) const {
+ if (count_ != rhs.count_)
+ return count_ < rhs.count_ ? -1 : 1;
+
+ for (size_t i = count_; i-- > 0;)
+ if (digits_[i] != rhs.digits_[i])
+ return digits_[i] < rhs.digits_[i] ? -1 : 1;
+
+ return 0;
+ }
+
+ size_t GetCount() const { return count_; }
+ Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
+ bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
+
+private:
+ void AppendDecimal64(const char* begin, const char* end) {
+ uint64_t u = ParseUint64(begin, end);
+ if (IsZero())
+ *this = u;
+ else {
+ unsigned exp = static_cast<unsigned>(end - begin);
+ (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
+ }
+ }
+
+ void PushBack(Type digit) {
+ RAPIDJSON_ASSERT(count_ < kCapacity);
+ digits_[count_++] = digit;
+ }
+
+ static uint64_t ParseUint64(const char* begin, const char* end) {
+ uint64_t r = 0;
+ for (const char* p = begin; p != end; ++p) {
+ RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
+ r = r * 10u + static_cast<unsigned>(*p - '0');
+ }
+ return r;
+ }
+
+ // Assume a * b + k < 2^128
+ static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ uint64_t low = _umul128(a, b, outHigh) + k;
+ if (low < k)
+ (*outHigh)++;
+ return low;
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+ __extension__ typedef unsigned __int128 uint128;
+ uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
+ p += k;
+ *outHigh = static_cast<uint64_t>(p >> 64);
+ return static_cast<uint64_t>(p);
+#else
+ const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
+ uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
+ x1 += (x0 >> 32); // can't give carry
+ x1 += x2;
+ if (x1 < x2)
+ x3 += (static_cast<uint64_t>(1) << 32);
+ uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
+ uint64_t hi = x3 + (x1 >> 32);
+
+ lo += k;
+ if (lo < k)
+ hi++;
+ *outHigh = hi;
+ return lo;
+#endif
+ }
+
+ static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
+ static const size_t kCapacity = kBitCount / sizeof(Type);
+ static const size_t kTypeBit = sizeof(Type) * 8;
+
+ Type digits_[kCapacity];
+ size_t count_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_BIGINTEGER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/diyfp.h b/ext/librethinkdbxx/src/rapidjson/internal/diyfp.h
new file mode 100644
index 00000000..c9fefdc6
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/diyfp.h
@@ -0,0 +1,258 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DIYFP_H_
+#define RAPIDJSON_DIYFP_H_
+
+#include "../rapidjson.h"
+
+#if defined(_MSC_VER) && defined(_M_AMD64)
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse64)
+#pragma intrinsic(_umul128)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+struct DiyFp {
+ DiyFp() : f(), e() {}
+
+ DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
+
+ explicit DiyFp(double d) {
+ union {
+ double d;
+ uint64_t u64;
+ } u = { d };
+
+ int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
+ uint64_t significand = (u.u64 & kDpSignificandMask);
+ if (biased_e != 0) {
+ f = significand + kDpHiddenBit;
+ e = biased_e - kDpExponentBias;
+ }
+ else {
+ f = significand;
+ e = kDpMinExponent + 1;
+ }
+ }
+
+ DiyFp operator-(const DiyFp& rhs) const {
+ return DiyFp(f - rhs.f, e);
+ }
+
+ DiyFp operator*(const DiyFp& rhs) const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ uint64_t h;
+ uint64_t l = _umul128(f, rhs.f, &h);
+ if (l & (uint64_t(1) << 63)) // rounding
+ h++;
+ return DiyFp(h, e + rhs.e + 64);
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+ __extension__ typedef unsigned __int128 uint128;
+ uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
+ uint64_t h = static_cast<uint64_t>(p >> 64);
+ uint64_t l = static_cast<uint64_t>(p);
+ if (l & (uint64_t(1) << 63)) // rounding
+ h++;
+ return DiyFp(h, e + rhs.e + 64);
+#else
+ const uint64_t M32 = 0xFFFFFFFF;
+ const uint64_t a = f >> 32;
+ const uint64_t b = f & M32;
+ const uint64_t c = rhs.f >> 32;
+ const uint64_t d = rhs.f & M32;
+ const uint64_t ac = a * c;
+ const uint64_t bc = b * c;
+ const uint64_t ad = a * d;
+ const uint64_t bd = b * d;
+ uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
+ tmp += 1U << 31; /// mult_round
+ return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
+#endif
+ }
+
+ DiyFp Normalize() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+ unsigned long index;
+ _BitScanReverse64(&index, f);
+ return DiyFp(f << (63 - index), e - (63 - index));
+#elif defined(__GNUC__) && __GNUC__ >= 4
+ int s = __builtin_clzll(f);
+ return DiyFp(f << s, e - s);
+#else
+ DiyFp res = *this;
+ while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ return res;
+#endif
+ }
+
+ DiyFp NormalizeBoundary() const {
+ DiyFp res = *this;
+ while (!(res.f & (kDpHiddenBit << 1))) {
+ res.f <<= 1;
+ res.e--;
+ }
+ res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+ res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+ return res;
+ }
+
+ void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+ DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+ DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+ mi.f <<= mi.e - pl.e;
+ mi.e = pl.e;
+ *plus = pl;
+ *minus = mi;
+ }
+
+ double ToDouble() const {
+ union {
+ double d;
+ uint64_t u64;
+ }u;
+ const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
+ static_cast<uint64_t>(e + kDpExponentBias);
+ u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
+ return u.d;
+ }
+
+ static const int kDiySignificandSize = 64;
+ static const int kDpSignificandSize = 52;
+ static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
+ static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
+ static const int kDpMinExponent = -kDpExponentBias;
+ static const int kDpDenormalExponent = -kDpExponentBias + 1;
+ static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+ static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+ static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+ uint64_t f;
+ int e;
+};
+
+inline DiyFp GetCachedPowerByIndex(size_t index) {
+ // 10^-348, 10^-340, ..., 10^340
+ static const uint64_t kCachedPowers_F[] = {
+ RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
+ RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
+ RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
+ RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
+ RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
+ RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
+ RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
+ RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
+ RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
+ RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
+ RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
+ RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
+ RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
+ RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
+ RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
+ RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
+ RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
+ RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
+ RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
+ RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
+ RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
+ RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
+ RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
+ RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
+ RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
+ RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
+ RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
+ RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
+ RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
+ RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
+ RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
+ RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
+ RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
+ RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
+ RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
+ RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
+ RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
+ RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
+ RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
+ RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
+ RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
+ RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
+ RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
+ RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
+ };
+ static const int16_t kCachedPowers_E[] = {
+ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
+ -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
+ -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
+ -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
+ -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
+ 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
+ 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
+ 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
+ 907, 933, 960, 986, 1013, 1039, 1066
+ };
+ return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
+}
+
+inline DiyFp GetCachedPower(int e, int* K) {
+
+ //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+ double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
+ int k = static_cast<int>(dk);
+ if (dk - k > 0.0)
+ k++;
+
+ unsigned index = static_cast<unsigned>((k >> 3) + 1);
+ *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
+
+ return GetCachedPowerByIndex(index);
+}
+
+inline DiyFp GetCachedPower10(int exp, int *outExp) {
+ unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
+ *outExp = -348 + static_cast<int>(index) * 8;
+ return GetCachedPowerByIndex(index);
+ }
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DIYFP_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/dtoa.h b/ext/librethinkdbxx/src/rapidjson/internal/dtoa.h
new file mode 100644
index 00000000..8d6350e6
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/dtoa.h
@@ -0,0 +1,245 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
+// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
+// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
+
+#ifndef RAPIDJSON_DTOA_
+#define RAPIDJSON_DTOA_
+
+#include "itoa.h" // GetDigitsLut()
+#include "diyfp.h"
+#include "ieee754.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
+#endif
+
+inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+ while (rest < wp_w && delta - rest >= ten_kappa &&
+ (rest + ten_kappa < wp_w || /// closer
+ wp_w - rest > rest + ten_kappa - wp_w)) {
+ buffer[len - 1]--;
+ rest += ten_kappa;
+ }
+}
+
+inline unsigned CountDecimalDigit32(uint32_t n) {
+ // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+ if (n < 10) return 1;
+ if (n < 100) return 2;
+ if (n < 1000) return 3;
+ if (n < 10000) return 4;
+ if (n < 100000) return 5;
+ if (n < 1000000) return 6;
+ if (n < 10000000) return 7;
+ if (n < 100000000) return 8;
+ // Will not reach 10 digits in DigitGen()
+ //if (n < 1000000000) return 9;
+ //return 10;
+ return 9;
+}
+
+inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+ static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+ const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+ const DiyFp wp_w = Mp - W;
+ uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+ uint64_t p2 = Mp.f & (one.f - 1);
+ unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
+ *len = 0;
+
+ while (kappa > 0) {
+ uint32_t d = 0;
+ switch (kappa) {
+ case 9: d = p1 / 100000000; p1 %= 100000000; break;
+ case 8: d = p1 / 10000000; p1 %= 10000000; break;
+ case 7: d = p1 / 1000000; p1 %= 1000000; break;
+ case 6: d = p1 / 100000; p1 %= 100000; break;
+ case 5: d = p1 / 10000; p1 %= 10000; break;
+ case 4: d = p1 / 1000; p1 %= 1000; break;
+ case 3: d = p1 / 100; p1 %= 100; break;
+ case 2: d = p1 / 10; p1 %= 10; break;
+ case 1: d = p1; p1 = 0; break;
+ default:;
+ }
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
+ kappa--;
+ uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+ if (tmp <= delta) {
+ *K += kappa;
+ GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+ return;
+ }
+ }
+
+ // kappa = 0
+ for (;;) {
+ p2 *= 10;
+ delta *= 10;
+ char d = static_cast<char>(p2 >> -one.e);
+ if (d || *len)
+ buffer[(*len)++] = static_cast<char>('0' + d);
+ p2 &= one.f - 1;
+ kappa--;
+ if (p2 < delta) {
+ *K += kappa;
+ int index = -static_cast<int>(kappa);
+ GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
+ return;
+ }
+ }
+}
+
+inline void Grisu2(double value, char* buffer, int* length, int* K) {
+ const DiyFp v(value);
+ DiyFp w_m, w_p;
+ v.NormalizedBoundaries(&w_m, &w_p);
+
+ const DiyFp c_mk = GetCachedPower(w_p.e, K);
+ const DiyFp W = v.Normalize() * c_mk;
+ DiyFp Wp = w_p * c_mk;
+ DiyFp Wm = w_m * c_mk;
+ Wm.f++;
+ Wp.f--;
+ DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+
+inline char* WriteExponent(int K, char* buffer) {
+ if (K < 0) {
+ *buffer++ = '-';
+ K = -K;
+ }
+
+ if (K >= 100) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
+ K %= 100;
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else if (K >= 10) {
+ const char* d = GetDigitsLut() + K * 2;
+ *buffer++ = d[0];
+ *buffer++ = d[1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(K));
+
+ return buffer;
+}
+
+inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
+ const int kk = length + k; // 10^(kk-1) <= v < 10^kk
+
+ if (0 <= k && kk <= 21) {
+ // 1234e7 -> 12340000000
+ for (int i = length; i < kk; i++)
+ buffer[i] = '0';
+ buffer[kk] = '.';
+ buffer[kk + 1] = '0';
+ return &buffer[kk + 2];
+ }
+ else if (0 < kk && kk <= 21) {
+ // 1234e-2 -> 12.34
+ std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
+ buffer[kk] = '.';
+ if (0 > k + maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[kk + 2]; // Reserve one zero
+ }
+ else
+ return &buffer[length + 1];
+ }
+ else if (-6 < kk && kk <= 0) {
+ // 1234e-6 -> 0.001234
+ const int offset = 2 - kk;
+ std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
+ buffer[0] = '0';
+ buffer[1] = '.';
+ for (int i = 2; i < offset; i++)
+ buffer[i] = '0';
+ if (length - kk > maxDecimalPlaces) {
+ // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
+ // Remove extra trailing zeros (at least one) after truncation.
+ for (int i = maxDecimalPlaces + 1; i > 2; i--)
+ if (buffer[i] != '0')
+ return &buffer[i + 1];
+ return &buffer[3]; // Reserve one zero
+ }
+ else
+ return &buffer[length + offset];
+ }
+ else if (kk < -maxDecimalPlaces) {
+ // Truncate to zero
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ else if (length == 1) {
+ // 1e30
+ buffer[1] = 'e';
+ return WriteExponent(kk - 1, &buffer[2]);
+ }
+ else {
+ // 1234e30 -> 1.234e33
+ std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
+ buffer[1] = '.';
+ buffer[length + 1] = 'e';
+ return WriteExponent(kk - 1, &buffer[0 + length + 2]);
+ }
+}
+
+inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
+ RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
+ Double d(value);
+ if (d.IsZero()) {
+ if (d.Sign())
+ *buffer++ = '-'; // -0.0, Issue #289
+ buffer[0] = '0';
+ buffer[1] = '.';
+ buffer[2] = '0';
+ return &buffer[3];
+ }
+ else {
+ if (value < 0) {
+ *buffer++ = '-';
+ value = -value;
+ }
+ int length, K;
+ Grisu2(value, buffer, &length, &K);
+ return Prettify(buffer, length, K, maxDecimalPlaces);
+ }
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_DTOA_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/ieee754.h b/ext/librethinkdbxx/src/rapidjson/internal/ieee754.h
new file mode 100644
index 00000000..82bb0b99
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/ieee754.h
@@ -0,0 +1,78 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_IEEE754_
+#define RAPIDJSON_IEEE754_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+class Double {
+public:
+ Double() {}
+ Double(double d) : d_(d) {}
+ Double(uint64_t u) : u_(u) {}
+
+ double Value() const { return d_; }
+ uint64_t Uint64Value() const { return u_; }
+
+ double NextPositiveDouble() const {
+ RAPIDJSON_ASSERT(!Sign());
+ return Double(u_ + 1).Value();
+ }
+
+ bool Sign() const { return (u_ & kSignMask) != 0; }
+ uint64_t Significand() const { return u_ & kSignificandMask; }
+ int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
+
+ bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
+ bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
+ bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
+ bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
+ bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
+
+ uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
+ int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
+ uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
+
+ static unsigned EffectiveSignificandSize(int order) {
+ if (order >= -1021)
+ return 53;
+ else if (order <= -1074)
+ return 0;
+ else
+ return static_cast<unsigned>(order) + 1074;
+ }
+
+private:
+ static const int kSignificandSize = 52;
+ static const int kExponentBias = 0x3FF;
+ static const int kDenormalExponent = 1 - kExponentBias;
+ static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
+ static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
+ static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+ static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
+
+ union {
+ double d_;
+ uint64_t u_;
+ };
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_IEEE754_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/itoa.h b/ext/librethinkdbxx/src/rapidjson/internal/itoa.h
new file mode 100644
index 00000000..01a4e7e7
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/itoa.h
@@ -0,0 +1,304 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ITOA_
+#define RAPIDJSON_ITOA_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline const char* GetDigitsLut() {
+ static const char cDigitsLut[200] = {
+ '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+ '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+ '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+ '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+ '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+ '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+ '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+ '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+ '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+ '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+ };
+ return cDigitsLut;
+}
+
+inline char* u32toa(uint32_t value, char* buffer) {
+ const char* cDigitsLut = GetDigitsLut();
+
+ if (value < 10000) {
+ const uint32_t d1 = (value / 100) << 1;
+ const uint32_t d2 = (value % 100) << 1;
+
+ if (value >= 1000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 100)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 10)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ }
+ else if (value < 100000000) {
+ // value = bbbbcccc
+ const uint32_t b = value / 10000;
+ const uint32_t c = value % 10000;
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ if (value >= 10000000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 1000000)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 100000)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ else {
+ // value = aabbbbcccc in decimal
+
+ const uint32_t a = value / 100000000; // 1 to 42
+ value %= 100000000;
+
+ if (a >= 10) {
+ const unsigned i = a << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+
+ const uint32_t b = value / 10000; // 0 to 9999
+ const uint32_t c = value % 10000; // 0 to 9999
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ *buffer++ = cDigitsLut[d1];
+ *buffer++ = cDigitsLut[d1 + 1];
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ return buffer;
+}
+
+inline char* i32toa(int32_t value, char* buffer) {
+ uint32_t u = static_cast<uint32_t>(value);
+ if (value < 0) {
+ *buffer++ = '-';
+ u = ~u + 1;
+ }
+
+ return u32toa(u, buffer);
+}
+
+inline char* u64toa(uint64_t value, char* buffer) {
+ const char* cDigitsLut = GetDigitsLut();
+ const uint64_t kTen8 = 100000000;
+ const uint64_t kTen9 = kTen8 * 10;
+ const uint64_t kTen10 = kTen8 * 100;
+ const uint64_t kTen11 = kTen8 * 1000;
+ const uint64_t kTen12 = kTen8 * 10000;
+ const uint64_t kTen13 = kTen8 * 100000;
+ const uint64_t kTen14 = kTen8 * 1000000;
+ const uint64_t kTen15 = kTen8 * 10000000;
+ const uint64_t kTen16 = kTen8 * kTen8;
+
+ if (value < kTen8) {
+ uint32_t v = static_cast<uint32_t>(value);
+ if (v < 10000) {
+ const uint32_t d1 = (v / 100) << 1;
+ const uint32_t d2 = (v % 100) << 1;
+
+ if (v >= 1000)
+ *buffer++ = cDigitsLut[d1];
+ if (v >= 100)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (v >= 10)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ }
+ else {
+ // value = bbbbcccc
+ const uint32_t b = v / 10000;
+ const uint32_t c = v % 10000;
+
+ const uint32_t d1 = (b / 100) << 1;
+ const uint32_t d2 = (b % 100) << 1;
+
+ const uint32_t d3 = (c / 100) << 1;
+ const uint32_t d4 = (c % 100) << 1;
+
+ if (value >= 10000000)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= 1000000)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= 100000)
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ }
+ }
+ else if (value < kTen16) {
+ const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+ const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+
+ const uint32_t b0 = v0 / 10000;
+ const uint32_t c0 = v0 % 10000;
+
+ const uint32_t d1 = (b0 / 100) << 1;
+ const uint32_t d2 = (b0 % 100) << 1;
+
+ const uint32_t d3 = (c0 / 100) << 1;
+ const uint32_t d4 = (c0 % 100) << 1;
+
+ const uint32_t b1 = v1 / 10000;
+ const uint32_t c1 = v1 % 10000;
+
+ const uint32_t d5 = (b1 / 100) << 1;
+ const uint32_t d6 = (b1 % 100) << 1;
+
+ const uint32_t d7 = (c1 / 100) << 1;
+ const uint32_t d8 = (c1 % 100) << 1;
+
+ if (value >= kTen15)
+ *buffer++ = cDigitsLut[d1];
+ if (value >= kTen14)
+ *buffer++ = cDigitsLut[d1 + 1];
+ if (value >= kTen13)
+ *buffer++ = cDigitsLut[d2];
+ if (value >= kTen12)
+ *buffer++ = cDigitsLut[d2 + 1];
+ if (value >= kTen11)
+ *buffer++ = cDigitsLut[d3];
+ if (value >= kTen10)
+ *buffer++ = cDigitsLut[d3 + 1];
+ if (value >= kTen9)
+ *buffer++ = cDigitsLut[d4];
+ if (value >= kTen8)
+ *buffer++ = cDigitsLut[d4 + 1];
+
+ *buffer++ = cDigitsLut[d5];
+ *buffer++ = cDigitsLut[d5 + 1];
+ *buffer++ = cDigitsLut[d6];
+ *buffer++ = cDigitsLut[d6 + 1];
+ *buffer++ = cDigitsLut[d7];
+ *buffer++ = cDigitsLut[d7 + 1];
+ *buffer++ = cDigitsLut[d8];
+ *buffer++ = cDigitsLut[d8 + 1];
+ }
+ else {
+ const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
+ value %= kTen16;
+
+ if (a < 10)
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a));
+ else if (a < 100) {
+ const uint32_t i = a << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else if (a < 1000) {
+ *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
+
+ const uint32_t i = (a % 100) << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ }
+ else {
+ const uint32_t i = (a / 100) << 1;
+ const uint32_t j = (a % 100) << 1;
+ *buffer++ = cDigitsLut[i];
+ *buffer++ = cDigitsLut[i + 1];
+ *buffer++ = cDigitsLut[j];
+ *buffer++ = cDigitsLut[j + 1];
+ }
+
+ const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
+ const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
+
+ const uint32_t b0 = v0 / 10000;
+ const uint32_t c0 = v0 % 10000;
+
+ const uint32_t d1 = (b0 / 100) << 1;
+ const uint32_t d2 = (b0 % 100) << 1;
+
+ const uint32_t d3 = (c0 / 100) << 1;
+ const uint32_t d4 = (c0 % 100) << 1;
+
+ const uint32_t b1 = v1 / 10000;
+ const uint32_t c1 = v1 % 10000;
+
+ const uint32_t d5 = (b1 / 100) << 1;
+ const uint32_t d6 = (b1 % 100) << 1;
+
+ const uint32_t d7 = (c1 / 100) << 1;
+ const uint32_t d8 = (c1 % 100) << 1;
+
+ *buffer++ = cDigitsLut[d1];
+ *buffer++ = cDigitsLut[d1 + 1];
+ *buffer++ = cDigitsLut[d2];
+ *buffer++ = cDigitsLut[d2 + 1];
+ *buffer++ = cDigitsLut[d3];
+ *buffer++ = cDigitsLut[d3 + 1];
+ *buffer++ = cDigitsLut[d4];
+ *buffer++ = cDigitsLut[d4 + 1];
+ *buffer++ = cDigitsLut[d5];
+ *buffer++ = cDigitsLut[d5 + 1];
+ *buffer++ = cDigitsLut[d6];
+ *buffer++ = cDigitsLut[d6 + 1];
+ *buffer++ = cDigitsLut[d7];
+ *buffer++ = cDigitsLut[d7 + 1];
+ *buffer++ = cDigitsLut[d8];
+ *buffer++ = cDigitsLut[d8 + 1];
+ }
+
+ return buffer;
+}
+
+inline char* i64toa(int64_t value, char* buffer) {
+ uint64_t u = static_cast<uint64_t>(value);
+ if (value < 0) {
+ *buffer++ = '-';
+ u = ~u + 1;
+ }
+
+ return u64toa(u, buffer);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ITOA_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/meta.h b/ext/librethinkdbxx/src/rapidjson/internal/meta.h
new file mode 100644
index 00000000..5a9aaa42
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/meta.h
@@ -0,0 +1,181 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_META_H_
+#define RAPIDJSON_INTERNAL_META_H_
+
+#include "../rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+#if defined(_MSC_VER)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(6334)
+#endif
+
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+#include <type_traits>
+#endif
+
+//@cond RAPIDJSON_INTERNAL
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
+template <typename T> struct Void { typedef void Type; };
+
+///////////////////////////////////////////////////////////////////////////////
+// BoolType, TrueType, FalseType
+//
+template <bool Cond> struct BoolType {
+ static const bool Value = Cond;
+ typedef BoolType Type;
+};
+typedef BoolType<true> TrueType;
+typedef BoolType<false> FalseType;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
+//
+
+template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
+template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
+template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
+template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
+
+template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
+template <> struct AndExprCond<true, true> : TrueType {};
+template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
+template <> struct OrExprCond<false, false> : FalseType {};
+
+template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
+template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
+template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
+template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AddConst, MaybeAddConst, RemoveConst
+template <typename T> struct AddConst { typedef const T Type; };
+template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
+template <typename T> struct RemoveConst { typedef T Type; };
+template <typename T> struct RemoveConst<const T> { typedef T Type; };
+
+
+///////////////////////////////////////////////////////////////////////////////
+// IsSame, IsConst, IsMoreConst, IsPointer
+//
+template <typename T, typename U> struct IsSame : FalseType {};
+template <typename T> struct IsSame<T, T> : TrueType {};
+
+template <typename T> struct IsConst : FalseType {};
+template <typename T> struct IsConst<const T> : TrueType {};
+
+template <typename CT, typename T>
+struct IsMoreConst
+ : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
+ BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
+
+template <typename T> struct IsPointer : FalseType {};
+template <typename T> struct IsPointer<T*> : TrueType {};
+
+///////////////////////////////////////////////////////////////////////////////
+// IsBaseOf
+//
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+template <typename B, typename D> struct IsBaseOf
+ : BoolType< ::std::is_base_of<B,D>::value> {};
+
+#else // simplified version adopted from Boost
+
+template<typename B, typename D> struct IsBaseOfImpl {
+ RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
+ RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
+
+ typedef char (&Yes)[1];
+ typedef char (&No) [2];
+
+ template <typename T>
+ static Yes Check(const D*, T);
+ static No Check(const B*, int);
+
+ struct Host {
+ operator const B*() const;
+ operator const D*();
+ };
+
+ enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
+};
+
+template <typename B, typename D> struct IsBaseOf
+ : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
+
+#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+
+//////////////////////////////////////////////////////////////////////////
+// EnableIf / DisableIf
+//
+template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
+template <typename T> struct EnableIfCond<false, T> { /* empty */ };
+
+template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
+template <typename T> struct DisableIfCond<true, T> { /* empty */ };
+
+template <typename Condition, typename T = void>
+struct EnableIf : EnableIfCond<Condition::Value, T> {};
+
+template <typename Condition, typename T = void>
+struct DisableIf : DisableIfCond<Condition::Value, T> {};
+
+// SFINAE helpers
+struct SfinaeTag {};
+template <typename T> struct RemoveSfinaeTag;
+template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
+
+#define RAPIDJSON_REMOVEFPTR_(type) \
+ typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
+ < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
+
+#define RAPIDJSON_ENABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_DISABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+//@endcond
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_META_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/pow10.h b/ext/librethinkdbxx/src/rapidjson/internal/pow10.h
new file mode 100644
index 00000000..02f475d7
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/pow10.h
@@ -0,0 +1,55 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+#include "../rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+ \param n non-negative exponent. Must <= 308.
+ \return 10.0^n
+*/
+inline double Pow10(int n) {
+ static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
+ 1e+0,
+ 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
+ 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+ 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+ 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+ 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+ 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+ 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+ 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+ 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+ 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+ 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+ 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+ 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+ 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+ 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
+ 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
+ };
+ RAPIDJSON_ASSERT(n >= 0 && n <= 308);
+ return e[n];
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POW10_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/regex.h b/ext/librethinkdbxx/src/rapidjson/internal/regex.h
new file mode 100644
index 00000000..422a5240
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/regex.h
@@ -0,0 +1,701 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_REGEX_H_
+#define RAPIDJSON_INTERNAL_REGEX_H_
+
+#include "../allocators.h"
+#include "../stream.h"
+#include "stack.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+RAPIDJSON_DIAG_OFF(implicit-fallthrough)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+#ifndef RAPIDJSON_REGEX_VERBOSE
+#define RAPIDJSON_REGEX_VERBOSE 0
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericRegex
+
+static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
+static const SizeType kRegexInvalidRange = ~SizeType(0);
+
+//! Regular expression engine with subset of ECMAscript grammar.
+/*!
+ Supported regular expression syntax:
+ - \c ab Concatenation
+ - \c a|b Alternation
+ - \c a? Zero or one
+ - \c a* Zero or more
+ - \c a+ One or more
+ - \c a{3} Exactly 3 times
+ - \c a{3,} At least 3 times
+ - \c a{3,5} 3 to 5 times
+ - \c (ab) Grouping
+ - \c ^a At the beginning
+ - \c a$ At the end
+ - \c . Any character
+ - \c [abc] Character classes
+ - \c [a-c] Character class range
+ - \c [a-z0-9_] Character class combination
+ - \c [^abc] Negated character classes
+ - \c [^a-c] Negated character class range
+ - \c [\b] Backspace (U+0008)
+ - \c \\| \\\\ ... Escape characters
+ - \c \\f Form feed (U+000C)
+ - \c \\n Line feed (U+000A)
+ - \c \\r Carriage return (U+000D)
+ - \c \\t Tab (U+0009)
+ - \c \\v Vertical tab (U+000B)
+
+ \note This is a Thompson NFA engine, implemented with reference to
+ Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
+ https://swtch.com/~rsc/regexp/regexp1.html
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericRegex {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ GenericRegex(const Ch* source, Allocator* allocator = 0) :
+ states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
+ stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
+ {
+ GenericStringStream<Encoding> ss(source);
+ DecodedStream<GenericStringStream<Encoding> > ds(ss);
+ Parse(ds);
+ }
+
+ ~GenericRegex() {
+ Allocator::Free(stateSet_);
+ }
+
+ bool IsValid() const {
+ return root_ != kRegexInvalidState;
+ }
+
+ template <typename InputStream>
+ bool Match(InputStream& is) const {
+ return SearchWithAnchoring(is, true, true);
+ }
+
+ bool Match(const Ch* s) const {
+ GenericStringStream<Encoding> is(s);
+ return Match(is);
+ }
+
+ template <typename InputStream>
+ bool Search(InputStream& is) const {
+ return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
+ }
+
+ bool Search(const Ch* s) const {
+ GenericStringStream<Encoding> is(s);
+ return Search(is);
+ }
+
+private:
+ enum Operator {
+ kZeroOrOne,
+ kZeroOrMore,
+ kOneOrMore,
+ kConcatenation,
+ kAlternation,
+ kLeftParenthesis
+ };
+
+ static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.'
+ static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
+ static const unsigned kRangeNegationFlag = 0x80000000;
+
+ struct Range {
+ unsigned start; //
+ unsigned end;
+ SizeType next;
+ };
+
+ struct State {
+ SizeType out; //!< Equals to kInvalid for matching state
+ SizeType out1; //!< Equals to non-kInvalid for split
+ SizeType rangeStart;
+ unsigned codepoint;
+ };
+
+ struct Frag {
+ Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
+ SizeType start;
+ SizeType out; //!< link-list of all output states
+ SizeType minIndex;
+ };
+
+ template <typename SourceStream>
+ class DecodedStream {
+ public:
+ DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
+ unsigned Peek() { return codepoint_; }
+ unsigned Take() {
+ unsigned c = codepoint_;
+ if (c) // No further decoding when '\0'
+ Decode();
+ return c;
+ }
+
+ private:
+ void Decode() {
+ if (!Encoding::Decode(ss_, &codepoint_))
+ codepoint_ = 0;
+ }
+
+ SourceStream& ss_;
+ unsigned codepoint_;
+ };
+
+ State& GetState(SizeType index) {
+ RAPIDJSON_ASSERT(index < stateCount_);
+ return states_.template Bottom<State>()[index];
+ }
+
+ const State& GetState(SizeType index) const {
+ RAPIDJSON_ASSERT(index < stateCount_);
+ return states_.template Bottom<State>()[index];
+ }
+
+ Range& GetRange(SizeType index) {
+ RAPIDJSON_ASSERT(index < rangeCount_);
+ return ranges_.template Bottom<Range>()[index];
+ }
+
+ const Range& GetRange(SizeType index) const {
+ RAPIDJSON_ASSERT(index < rangeCount_);
+ return ranges_.template Bottom<Range>()[index];
+ }
+
+ template <typename InputStream>
+ void Parse(DecodedStream<InputStream>& ds) {
+ Allocator allocator;
+ Stack<Allocator> operandStack(&allocator, 256); // Frag
+ Stack<Allocator> operatorStack(&allocator, 256); // Operator
+ Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
+
+ *atomCountStack.template Push<unsigned>() = 0;
+
+ unsigned codepoint;
+ while (ds.Peek() != 0) {
+ switch (codepoint = ds.Take()) {
+ case '^':
+ anchorBegin_ = true;
+ break;
+
+ case '$':
+ anchorEnd_ = true;
+ break;
+
+ case '|':
+ while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+ *operatorStack.template Push<Operator>() = kAlternation;
+ *atomCountStack.template Top<unsigned>() = 0;
+ break;
+
+ case '(':
+ *operatorStack.template Push<Operator>() = kLeftParenthesis;
+ *atomCountStack.template Push<unsigned>() = 0;
+ break;
+
+ case ')':
+ while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+ if (operatorStack.Empty())
+ return;
+ operatorStack.template Pop<Operator>(1);
+ atomCountStack.template Pop<unsigned>(1);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '?':
+ if (!Eval(operandStack, kZeroOrOne))
+ return;
+ break;
+
+ case '*':
+ if (!Eval(operandStack, kZeroOrMore))
+ return;
+ break;
+
+ case '+':
+ if (!Eval(operandStack, kOneOrMore))
+ return;
+ break;
+
+ case '{':
+ {
+ unsigned n, m;
+ if (!ParseUnsigned(ds, &n))
+ return;
+
+ if (ds.Peek() == ',') {
+ ds.Take();
+ if (ds.Peek() == '}')
+ m = kInfinityQuantifier;
+ else if (!ParseUnsigned(ds, &m) || m < n)
+ return;
+ }
+ else
+ m = n;
+
+ if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
+ return;
+ ds.Take();
+ }
+ break;
+
+ case '.':
+ PushOperand(operandStack, kAnyCharacterClass);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '[':
+ {
+ SizeType range;
+ if (!ParseRange(ds, &range))
+ return;
+ SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
+ GetState(s).rangeStart = range;
+ *operandStack.template Push<Frag>() = Frag(s, s, s);
+ }
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ break;
+
+ case '\\': // Escape character
+ if (!CharacterEscape(ds, &codepoint))
+ return; // Unsupported escape character
+ // fall through to default
+
+ default: // Pattern character
+ PushOperand(operandStack, codepoint);
+ ImplicitConcatenation(atomCountStack, operatorStack);
+ }
+ }
+
+ while (!operatorStack.Empty())
+ if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
+ return;
+
+ // Link the operand to matching state.
+ if (operandStack.GetSize() == sizeof(Frag)) {
+ Frag* e = operandStack.template Pop<Frag>(1);
+ Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
+ root_ = e->start;
+
+#if RAPIDJSON_REGEX_VERBOSE
+ printf("root: %d\n", root_);
+ for (SizeType i = 0; i < stateCount_ ; i++) {
+ State& s = GetState(i);
+ printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
+ }
+ printf("\n");
+#endif
+ }
+
+ // Preallocate buffer for SearchWithAnchoring()
+ RAPIDJSON_ASSERT(stateSet_ == 0);
+ if (stateCount_ > 0) {
+ stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
+ state0_.template Reserve<SizeType>(stateCount_);
+ state1_.template Reserve<SizeType>(stateCount_);
+ }
+ }
+
+ SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
+ State* s = states_.template Push<State>();
+ s->out = out;
+ s->out1 = out1;
+ s->codepoint = codepoint;
+ s->rangeStart = kRegexInvalidRange;
+ return stateCount_++;
+ }
+
+ void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
+ SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
+ *operandStack.template Push<Frag>() = Frag(s, s, s);
+ }
+
+ void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
+ if (*atomCountStack.template Top<unsigned>())
+ *operatorStack.template Push<Operator>() = kConcatenation;
+ (*atomCountStack.template Top<unsigned>())++;
+ }
+
+ SizeType Append(SizeType l1, SizeType l2) {
+ SizeType old = l1;
+ while (GetState(l1).out != kRegexInvalidState)
+ l1 = GetState(l1).out;
+ GetState(l1).out = l2;
+ return old;
+ }
+
+ void Patch(SizeType l, SizeType s) {
+ for (SizeType next; l != kRegexInvalidState; l = next) {
+ next = GetState(l).out;
+ GetState(l).out = s;
+ }
+ }
+
+ bool Eval(Stack<Allocator>& operandStack, Operator op) {
+ switch (op) {
+ case kConcatenation:
+ RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
+ {
+ Frag e2 = *operandStack.template Pop<Frag>(1);
+ Frag e1 = *operandStack.template Pop<Frag>(1);
+ Patch(e1.out, e2.start);
+ *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
+ }
+ return true;
+
+ case kAlternation:
+ if (operandStack.GetSize() >= sizeof(Frag) * 2) {
+ Frag e2 = *operandStack.template Pop<Frag>(1);
+ Frag e1 = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(e1.start, e2.start, 0);
+ *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
+ return true;
+ }
+ return false;
+
+ case kZeroOrOne:
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
+ return true;
+ }
+ return false;
+
+ case kZeroOrMore:
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ Patch(e.out, s);
+ *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
+ return true;
+ }
+ return false;
+
+ default:
+ RAPIDJSON_ASSERT(op == kOneOrMore);
+ if (operandStack.GetSize() >= sizeof(Frag)) {
+ Frag e = *operandStack.template Pop<Frag>(1);
+ SizeType s = NewState(kRegexInvalidState, e.start, 0);
+ Patch(e.out, s);
+ *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
+ RAPIDJSON_ASSERT(n <= m);
+ RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
+
+ if (n == 0) {
+ if (m == 0) // a{0} not support
+ return false;
+ else if (m == kInfinityQuantifier)
+ Eval(operandStack, kZeroOrMore); // a{0,} -> a*
+ else {
+ Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
+ for (unsigned i = 0; i < m - 1; i++)
+ CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
+ for (unsigned i = 0; i < m - 1; i++)
+ Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
+ }
+ return true;
+ }
+
+ for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
+ CloneTopOperand(operandStack);
+
+ if (m == kInfinityQuantifier)
+ Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
+ else if (m > n) {
+ CloneTopOperand(operandStack); // a{3,5} -> a a a a
+ Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
+ for (unsigned i = n; i < m - 1; i++)
+ CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
+ for (unsigned i = n; i < m; i++)
+ Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
+ }
+
+ for (unsigned i = 0; i < n - 1; i++)
+ Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
+
+ return true;
+ }
+
+ static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
+
+ void CloneTopOperand(Stack<Allocator>& operandStack) {
+ const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
+ SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
+ State* s = states_.template Push<State>(count);
+ memcpy(s, &GetState(src.minIndex), count * sizeof(State));
+ for (SizeType j = 0; j < count; j++) {
+ if (s[j].out != kRegexInvalidState)
+ s[j].out += count;
+ if (s[j].out1 != kRegexInvalidState)
+ s[j].out1 += count;
+ }
+ *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
+ stateCount_ += count;
+ }
+
+ template <typename InputStream>
+ bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
+ unsigned r = 0;
+ if (ds.Peek() < '0' || ds.Peek() > '9')
+ return false;
+ while (ds.Peek() >= '0' && ds.Peek() <= '9') {
+ if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
+ return false; // overflow
+ r = r * 10 + (ds.Take() - '0');
+ }
+ *u = r;
+ return true;
+ }
+
+ template <typename InputStream>
+ bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
+ bool isBegin = true;
+ bool negate = false;
+ int step = 0;
+ SizeType start = kRegexInvalidRange;
+ SizeType current = kRegexInvalidRange;
+ unsigned codepoint;
+ while ((codepoint = ds.Take()) != 0) {
+ if (isBegin) {
+ isBegin = false;
+ if (codepoint == '^') {
+ negate = true;
+ continue;
+ }
+ }
+
+ switch (codepoint) {
+ case ']':
+ if (start == kRegexInvalidRange)
+ return false; // Error: nothing inside []
+ if (step == 2) { // Add trailing '-'
+ SizeType r = NewRange('-');
+ RAPIDJSON_ASSERT(current != kRegexInvalidRange);
+ GetRange(current).next = r;
+ }
+ if (negate)
+ GetRange(start).start |= kRangeNegationFlag;
+ *range = start;
+ return true;
+
+ case '\\':
+ if (ds.Peek() == 'b') {
+ ds.Take();
+ codepoint = 0x0008; // Escape backspace character
+ }
+ else if (!CharacterEscape(ds, &codepoint))
+ return false;
+ // fall through to default
+
+ default:
+ switch (step) {
+ case 1:
+ if (codepoint == '-') {
+ step++;
+ break;
+ }
+ // fall through to step 0 for other characters
+
+ case 0:
+ {
+ SizeType r = NewRange(codepoint);
+ if (current != kRegexInvalidRange)
+ GetRange(current).next = r;
+ if (start == kRegexInvalidRange)
+ start = r;
+ current = r;
+ }
+ step = 1;
+ break;
+
+ default:
+ RAPIDJSON_ASSERT(step == 2);
+ GetRange(current).end = codepoint;
+ step = 0;
+ }
+ }
+ }
+ return false;
+ }
+
+ SizeType NewRange(unsigned codepoint) {
+ Range* r = ranges_.template Push<Range>();
+ r->start = r->end = codepoint;
+ r->next = kRegexInvalidRange;
+ return rangeCount_++;
+ }
+
+ template <typename InputStream>
+ bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
+ unsigned codepoint;
+ switch (codepoint = ds.Take()) {
+ case '^':
+ case '$':
+ case '|':
+ case '(':
+ case ')':
+ case '?':
+ case '*':
+ case '+':
+ case '.':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case '\\':
+ *escapedCodepoint = codepoint; return true;
+ case 'f': *escapedCodepoint = 0x000C; return true;
+ case 'n': *escapedCodepoint = 0x000A; return true;
+ case 'r': *escapedCodepoint = 0x000D; return true;
+ case 't': *escapedCodepoint = 0x0009; return true;
+ case 'v': *escapedCodepoint = 0x000B; return true;
+ default:
+ return false; // Unsupported escape character
+ }
+ }
+
+ template <typename InputStream>
+ bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
+ RAPIDJSON_ASSERT(IsValid());
+ DecodedStream<InputStream> ds(is);
+
+ state0_.Clear();
+ Stack<Allocator> *current = &state0_, *next = &state1_;
+ const size_t stateSetSize = GetStateSetSize();
+ std::memset(stateSet_, 0, stateSetSize);
+
+ bool matched = AddState(*current, root_);
+ unsigned codepoint;
+ while (!current->Empty() && (codepoint = ds.Take()) != 0) {
+ std::memset(stateSet_, 0, stateSetSize);
+ next->Clear();
+ matched = false;
+ for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
+ const State& sr = GetState(*s);
+ if (sr.codepoint == codepoint ||
+ sr.codepoint == kAnyCharacterClass ||
+ (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
+ {
+ matched = AddState(*next, sr.out) || matched;
+ if (!anchorEnd && matched)
+ return true;
+ }
+ if (!anchorBegin)
+ AddState(*next, root_);
+ }
+ internal::Swap(current, next);
+ }
+
+ return matched;
+ }
+
+ size_t GetStateSetSize() const {
+ return (stateCount_ + 31) / 32 * 4;
+ }
+
+ // Return whether the added states is a match state
+ bool AddState(Stack<Allocator>& l, SizeType index) const {
+ RAPIDJSON_ASSERT(index != kRegexInvalidState);
+
+ const State& s = GetState(index);
+ if (s.out1 != kRegexInvalidState) { // Split
+ bool matched = AddState(l, s.out);
+ return AddState(l, s.out1) || matched;
+ }
+ else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
+ stateSet_[index >> 5] |= (1 << (index & 31));
+ *l.template PushUnsafe<SizeType>() = index;
+ }
+ return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
+ }
+
+ bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
+ bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
+ while (rangeIndex != kRegexInvalidRange) {
+ const Range& r = GetRange(rangeIndex);
+ if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
+ return yes;
+ rangeIndex = r.next;
+ }
+ return !yes;
+ }
+
+ Stack<Allocator> states_;
+ Stack<Allocator> ranges_;
+ SizeType root_;
+ SizeType stateCount_;
+ SizeType rangeCount_;
+
+ static const unsigned kInfinityQuantifier = ~0u;
+
+ // For SearchWithAnchoring()
+ uint32_t* stateSet_; // allocated by states_.GetAllocator()
+ mutable Stack<Allocator> state0_;
+ mutable Stack<Allocator> state1_;
+ bool anchorBegin_;
+ bool anchorEnd_;
+};
+
+typedef GenericRegex<UTF8<> > Regex;
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_REGEX_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/stack.h b/ext/librethinkdbxx/src/rapidjson/internal/stack.h
new file mode 100644
index 00000000..022c9aab
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/stack.h
@@ -0,0 +1,230 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+#include "../allocators.h"
+#include "swap.h"
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+ // Optimization note: Do not allocate memory for stack_ in constructor.
+ // Do it lazily when first Push() -> Expand() -> Resize().
+ Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack(Stack&& rhs)
+ : allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(rhs.stack_),
+ stackTop_(rhs.stackTop_),
+ stackEnd_(rhs.stackEnd_),
+ initialCapacity_(rhs.initialCapacity_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+#endif
+
+ ~Stack() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack& operator=(Stack&& rhs) {
+ if (&rhs != this)
+ {
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = rhs.stack_;
+ stackTop_ = rhs.stackTop_;
+ stackEnd_ = rhs.stackEnd_;
+ initialCapacity_ = rhs.initialCapacity_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+ return *this;
+ }
+#endif
+
+ void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
+ internal::Swap(allocator_, rhs.allocator_);
+ internal::Swap(ownAllocator_, rhs.ownAllocator_);
+ internal::Swap(stack_, rhs.stack_);
+ internal::Swap(stackTop_, rhs.stackTop_);
+ internal::Swap(stackEnd_, rhs.stackEnd_);
+ internal::Swap(initialCapacity_, rhs.initialCapacity_);
+ }
+
+ void Clear() { stackTop_ = stack_; }
+
+ void ShrinkToFit() {
+ if (Empty()) {
+ // If the stack is empty, completely deallocate the memory.
+ Allocator::Free(stack_);
+ stack_ = 0;
+ stackTop_ = 0;
+ stackEnd_ = 0;
+ }
+ else
+ Resize(GetSize());
+ }
+
+ // Optimization note: try to minimize the size of this function for force inline.
+ // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
+ template<typename T>
+ RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
+ // Expand the stack if needed
+ if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
+ Expand<T>(count);
+ }
+
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+ Reserve<T>(count);
+ return PushUnsafe<T>(count);
+ }
+
+ template<typename T>
+ RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
+ RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
+ T* ret = reinterpret_cast<T*>(stackTop_);
+ stackTop_ += sizeof(T) * count;
+ return ret;
+ }
+
+ template<typename T>
+ T* Pop(size_t count) {
+ RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+ stackTop_ -= count * sizeof(T);
+ return reinterpret_cast<T*>(stackTop_);
+ }
+
+ template<typename T>
+ T* Top() {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ const T* Top() const {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ T* End() { return reinterpret_cast<T*>(stackTop_); }
+
+ template<typename T>
+ const T* End() const { return reinterpret_cast<T*>(stackTop_); }
+
+ template<typename T>
+ T* Bottom() { return reinterpret_cast<T*>(stack_); }
+
+ template<typename T>
+ const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
+
+ bool HasAllocator() const {
+ return allocator_ != 0;
+ }
+
+ Allocator& GetAllocator() {
+ RAPIDJSON_ASSERT(allocator_);
+ return *allocator_;
+ }
+
+ bool Empty() const { return stackTop_ == stack_; }
+ size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
+ size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
+
+private:
+ template<typename T>
+ void Expand(size_t count) {
+ // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
+ size_t newCapacity;
+ if (stack_ == 0) {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ newCapacity = initialCapacity_;
+ } else {
+ newCapacity = GetCapacity();
+ newCapacity += (newCapacity + 1) / 2;
+ }
+ size_t newSize = GetSize() + sizeof(T) * count;
+ if (newCapacity < newSize)
+ newCapacity = newSize;
+
+ Resize(newCapacity);
+ }
+
+ void Resize(size_t newCapacity) {
+ const size_t size = GetSize(); // Backup the current size
+ stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
+ stackTop_ = stack_ + size;
+ stackEnd_ = stack_ + newCapacity;
+ }
+
+ void Destroy() {
+ Allocator::Free(stack_);
+ RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
+ }
+
+ // Prohibit copy constructor & assignment operator.
+ Stack(const Stack&);
+ Stack& operator=(const Stack&);
+
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ char *stack_;
+ char *stackTop_;
+ char *stackEnd_;
+ size_t initialCapacity_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_STACK_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/strfunc.h b/ext/librethinkdbxx/src/rapidjson/internal/strfunc.h
new file mode 100644
index 00000000..2edfae52
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/strfunc.h
@@ -0,0 +1,55 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+#include "../stream.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+ \param s Null-terminated input string.
+ \return Number of characters in the string.
+ \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+ const Ch* p = s;
+ while (*p) ++p;
+ return SizeType(p - s);
+}
+
+//! Returns number of code points in a encoded string.
+template<typename Encoding>
+bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
+ GenericStringStream<Encoding> is(s);
+ const typename Encoding::Ch* end = s + length;
+ SizeType count = 0;
+ while (is.src_ < end) {
+ unsigned codepoint;
+ if (!Encoding::Decode(is, &codepoint))
+ return false;
+ count++;
+ }
+ *outCount = count;
+ return true;
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/strtod.h b/ext/librethinkdbxx/src/rapidjson/internal/strtod.h
new file mode 100644
index 00000000..289c413b
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/strtod.h
@@ -0,0 +1,269 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRTOD_
+#define RAPIDJSON_STRTOD_
+
+#include "ieee754.h"
+#include "biginteger.h"
+#include "diyfp.h"
+#include "pow10.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+inline double FastPath(double significand, int exp) {
+ if (exp < -308)
+ return 0.0;
+ else if (exp >= 0)
+ return significand * internal::Pow10(exp);
+ else
+ return significand / internal::Pow10(-exp);
+}
+
+inline double StrtodNormalPrecision(double d, int p) {
+ if (p < -308) {
+ // Prevent expSum < -308, making Pow10(p) = 0
+ d = FastPath(d, -308);
+ d = FastPath(d, p + 308);
+ }
+ else
+ d = FastPath(d, p);
+ return d;
+}
+
+template <typename T>
+inline T Min3(T a, T b, T c) {
+ T m = a;
+ if (m > b) m = b;
+ if (m > c) m = c;
+ return m;
+}
+
+inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
+ const Double db(b);
+ const uint64_t bInt = db.IntegerSignificand();
+ const int bExp = db.IntegerExponent();
+ const int hExp = bExp - 1;
+
+ int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
+
+ // Adjust for decimal exponent
+ if (dExp >= 0) {
+ dS_Exp2 += dExp;
+ dS_Exp5 += dExp;
+ }
+ else {
+ bS_Exp2 -= dExp;
+ bS_Exp5 -= dExp;
+ hS_Exp2 -= dExp;
+ hS_Exp5 -= dExp;
+ }
+
+ // Adjust for binary exponent
+ if (bExp >= 0)
+ bS_Exp2 += bExp;
+ else {
+ dS_Exp2 -= bExp;
+ hS_Exp2 -= bExp;
+ }
+
+ // Adjust for half ulp exponent
+ if (hExp >= 0)
+ hS_Exp2 += hExp;
+ else {
+ dS_Exp2 -= hExp;
+ bS_Exp2 -= hExp;
+ }
+
+ // Remove common power of two factor from all three scaled values
+ int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
+ dS_Exp2 -= common_Exp2;
+ bS_Exp2 -= common_Exp2;
+ hS_Exp2 -= common_Exp2;
+
+ BigInteger dS = d;
+ dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
+
+ BigInteger bS(bInt);
+ bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
+
+ BigInteger hS(1);
+ hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
+
+ BigInteger delta(0);
+ dS.Difference(bS, &delta);
+
+ return delta.Compare(hS);
+}
+
+inline bool StrtodFast(double d, int p, double* result) {
+ // Use fast path for string-to-double conversion if possible
+ // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
+ if (p > 22 && p < 22 + 16) {
+ // Fast Path Cases In Disguise
+ d *= internal::Pow10(p - 22);
+ p = 22;
+ }
+
+ if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
+ *result = FastPath(d, p);
+ return true;
+ }
+ else
+ return false;
+}
+
+// Compute an approximation and see if it is within 1/2 ULP
+inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
+ uint64_t significand = 0;
+ size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
+ for (; i < length; i++) {
+ if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
+ (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
+ break;
+ significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
+ }
+
+ if (i < length && decimals[i] >= '5') // Rounding
+ significand++;
+
+ size_t remaining = length - i;
+ const unsigned kUlpShift = 3;
+ const unsigned kUlp = 1 << kUlpShift;
+ int64_t error = (remaining == 0) ? 0 : kUlp / 2;
+
+ DiyFp v(significand, 0);
+ v = v.Normalize();
+ error <<= -v.e;
+
+ const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
+
+ int actualExp;
+ DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
+ if (actualExp != dExp) {
+ static const DiyFp kPow10[] = {
+ DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
+ DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
+ DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
+ DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
+ DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
+ DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
+ DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
+ };
+ int adjustment = dExp - actualExp - 1;
+ RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
+ v = v * kPow10[adjustment];
+ if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
+ error += kUlp / 2;
+ }
+
+ v = v * cachedPower;
+
+ error += kUlp + (error == 0 ? 0 : 1);
+
+ const int oldExp = v.e;
+ v = v.Normalize();
+ error <<= oldExp - v.e;
+
+ const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
+ unsigned precisionSize = 64 - effectiveSignificandSize;
+ if (precisionSize + kUlpShift >= 64) {
+ unsigned scaleExp = (precisionSize + kUlpShift) - 63;
+ v.f >>= scaleExp;
+ v.e += scaleExp;
+ error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
+ precisionSize -= scaleExp;
+ }
+
+ DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
+ const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
+ const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
+ if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
+ rounded.f++;
+ if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
+ rounded.f >>= 1;
+ rounded.e++;
+ }
+ }
+
+ *result = rounded.ToDouble();
+
+ return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
+}
+
+inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+ const BigInteger dInt(decimals, length);
+ const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
+ Double a(approx);
+ int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
+ if (cmp < 0)
+ return a.Value(); // within half ULP
+ else if (cmp == 0) {
+ // Round towards even
+ if (a.Significand() & 1)
+ return a.NextPositiveDouble();
+ else
+ return a.Value();
+ }
+ else // adjustment
+ return a.NextPositiveDouble();
+}
+
+inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
+ RAPIDJSON_ASSERT(d >= 0.0);
+ RAPIDJSON_ASSERT(length >= 1);
+
+ double result;
+ if (StrtodFast(d, p, &result))
+ return result;
+
+ // Trim leading zeros
+ while (*decimals == '0' && length > 1) {
+ length--;
+ decimals++;
+ decimalPosition--;
+ }
+
+ // Trim trailing zeros
+ while (decimals[length - 1] == '0' && length > 1) {
+ length--;
+ decimalPosition--;
+ exp++;
+ }
+
+ // Trim right-most digits
+ const int kMaxDecimalDigit = 780;
+ if (static_cast<int>(length) > kMaxDecimalDigit) {
+ int delta = (static_cast<int>(length) - kMaxDecimalDigit);
+ exp += delta;
+ decimalPosition -= static_cast<unsigned>(delta);
+ length = kMaxDecimalDigit;
+ }
+
+ // If too small, underflow to zero
+ if (int(length) + exp < -324)
+ return 0.0;
+
+ if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
+ return result;
+
+ // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
+ return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRTOD_
diff --git a/ext/librethinkdbxx/src/rapidjson/internal/swap.h b/ext/librethinkdbxx/src/rapidjson/internal/swap.h
new file mode 100644
index 00000000..666e49f9
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/internal/swap.h
@@ -0,0 +1,46 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_SWAP_H_
+#define RAPIDJSON_INTERNAL_SWAP_H_
+
+#include "../rapidjson.h"
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom swap() to avoid dependency on C++ <algorithm> header
+/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
+ \note This has the same semantics as std::swap().
+*/
+template <typename T>
+inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_SWAP_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/istreamwrapper.h b/ext/librethinkdbxx/src/rapidjson/istreamwrapper.h
new file mode 100644
index 00000000..f5fe2897
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/istreamwrapper.h
@@ -0,0 +1,115 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
+#define RAPIDJSON_ISTREAMWRAPPER_H_
+
+#include "stream.h"
+#include <iosfwd>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
+/*!
+ The classes can be wrapped including but not limited to:
+
+ - \c std::istringstream
+ - \c std::stringstream
+ - \c std::wistringstream
+ - \c std::wstringstream
+ - \c std::ifstream
+ - \c std::fstream
+ - \c std::wifstream
+ - \c std::wfstream
+
+ \tparam StreamType Class derived from \c std::basic_istream.
+*/
+
+template <typename StreamType>
+class BasicIStreamWrapper {
+public:
+ typedef typename StreamType::char_type Ch;
+ BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
+
+ Ch Peek() const {
+ typename StreamType::int_type c = stream_.peek();
+ return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
+ }
+
+ Ch Take() {
+ typename StreamType::int_type c = stream_.get();
+ if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
+ count_++;
+ return static_cast<Ch>(c);
+ }
+ else
+ return '\0';
+ }
+
+ // tellg() may return -1 when failed. So we count by ourself.
+ size_t Tell() const { return count_; }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
+ int i;
+ bool hasError = false;
+ for (i = 0; i < 4; ++i) {
+ typename StreamType::int_type c = stream_.get();
+ if (c == StreamType::traits_type::eof()) {
+ hasError = true;
+ stream_.clear();
+ break;
+ }
+ peekBuffer_[i] = static_cast<Ch>(c);
+ }
+ for (--i; i >= 0; --i)
+ stream_.putback(peekBuffer_[i]);
+ return !hasError ? peekBuffer_ : 0;
+ }
+
+private:
+ BasicIStreamWrapper(const BasicIStreamWrapper&);
+ BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
+
+ StreamType& stream_;
+ size_t count_; //!< Number of characters read. Note:
+ mutable Ch peekBuffer_[4];
+};
+
+typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
+typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
+
+#if defined(__clang__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ISTREAMWRAPPER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/memorybuffer.h b/ext/librethinkdbxx/src/rapidjson/memorybuffer.h
new file mode 100644
index 00000000..39bee1de
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/memorybuffer.h
@@ -0,0 +1,70 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_MEMORYBUFFER_H_
+#define RAPIDJSON_MEMORYBUFFER_H_
+
+#include "stream.h"
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output byte stream.
+/*!
+ This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
+
+ It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
+
+ Differences between MemoryBuffer and StringBuffer:
+ 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer.
+ 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
+
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Allocator = CrtAllocator>
+struct GenericMemoryBuffer {
+ typedef char Ch; // byte
+
+ GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() { stack_.ShrinkToFit(); }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetBuffer() const {
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+};
+
+typedef GenericMemoryBuffer<> MemoryBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
+ std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/memorystream.h b/ext/librethinkdbxx/src/rapidjson/memorystream.h
new file mode 100644
index 00000000..1d71d8a4
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/memorystream.h
@@ -0,0 +1,71 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_MEMORYSTREAM_H_
+#define RAPIDJSON_MEMORYSTREAM_H_
+
+#include "stream.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(missing-noreturn)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory input byte stream.
+/*!
+ This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
+
+ It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
+
+ Differences between MemoryStream and StringStream:
+ 1. StringStream has encoding but MemoryStream is a byte stream.
+ 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
+ 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
+ \note implements Stream concept
+*/
+struct MemoryStream {
+ typedef char Ch; // byte
+
+ MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
+
+ Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
+ Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ // For encoding detection only.
+ const Ch* Peek4() const {
+ return Tell() + 4 <= size_ ? src_ : 0;
+ }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* begin_; //!< Original head of the string.
+ const Ch* end_; //!< End of stream.
+ size_t size_; //!< Size of the stream.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_MEMORYBUFFER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/msinttypes/inttypes.h b/ext/librethinkdbxx/src/rapidjson/msinttypes/inttypes.h
new file mode 100644
index 00000000..18111286
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/msinttypes/inttypes.h
@@ -0,0 +1,316 @@
+// ISO C9x compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2013 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the product nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// The above software in this distribution may have been modified by
+// THL A29 Limited ("Tencent Modifications").
+// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// miloyip: VC supports inttypes.h since VC2013
+#if _MSC_VER >= 1800
+#include <inttypes.h>
+#else
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+ intmax_t quot;
+ intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8 "d"
+#define PRIi8 "i"
+#define PRIdLEAST8 "d"
+#define PRIiLEAST8 "i"
+#define PRIdFAST8 "d"
+#define PRIiFAST8 "i"
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIdLEAST16 "hd"
+#define PRIiLEAST16 "hi"
+#define PRIdFAST16 "hd"
+#define PRIiFAST16 "hi"
+
+#define PRId32 "I32d"
+#define PRIi32 "I32i"
+#define PRIdLEAST32 "I32d"
+#define PRIiLEAST32 "I32i"
+#define PRIdFAST32 "I32d"
+#define PRIiFAST32 "I32i"
+
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIdLEAST64 "I64d"
+#define PRIiLEAST64 "I64i"
+#define PRIdFAST64 "I64d"
+#define PRIiFAST64 "I64i"
+
+#define PRIdMAX "I64d"
+#define PRIiMAX "I64i"
+
+#define PRIdPTR "Id"
+#define PRIiPTR "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8 "o"
+#define PRIu8 "u"
+#define PRIx8 "x"
+#define PRIX8 "X"
+#define PRIoLEAST8 "o"
+#define PRIuLEAST8 "u"
+#define PRIxLEAST8 "x"
+#define PRIXLEAST8 "X"
+#define PRIoFAST8 "o"
+#define PRIuFAST8 "u"
+#define PRIxFAST8 "x"
+#define PRIXFAST8 "X"
+
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+#define PRIoLEAST16 "ho"
+#define PRIuLEAST16 "hu"
+#define PRIxLEAST16 "hx"
+#define PRIXLEAST16 "hX"
+#define PRIoFAST16 "ho"
+#define PRIuFAST16 "hu"
+#define PRIxFAST16 "hx"
+#define PRIXFAST16 "hX"
+
+#define PRIo32 "I32o"
+#define PRIu32 "I32u"
+#define PRIx32 "I32x"
+#define PRIX32 "I32X"
+#define PRIoLEAST32 "I32o"
+#define PRIuLEAST32 "I32u"
+#define PRIxLEAST32 "I32x"
+#define PRIXLEAST32 "I32X"
+#define PRIoFAST32 "I32o"
+#define PRIuFAST32 "I32u"
+#define PRIxFAST32 "I32x"
+#define PRIXFAST32 "I32X"
+
+#define PRIo64 "I64o"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#define PRIX64 "I64X"
+#define PRIoLEAST64 "I64o"
+#define PRIuLEAST64 "I64u"
+#define PRIxLEAST64 "I64x"
+#define PRIXLEAST64 "I64X"
+#define PRIoFAST64 "I64o"
+#define PRIuFAST64 "I64u"
+#define PRIxFAST64 "I64x"
+#define PRIXFAST64 "I64X"
+
+#define PRIoMAX "I64o"
+#define PRIuMAX "I64u"
+#define PRIxMAX "I64x"
+#define PRIXMAX "I64X"
+
+#define PRIoPTR "Io"
+#define PRIuPTR "Iu"
+#define PRIxPTR "Ix"
+#define PRIXPTR "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8 "d"
+#define SCNi8 "i"
+#define SCNdLEAST8 "d"
+#define SCNiLEAST8 "i"
+#define SCNdFAST8 "d"
+#define SCNiFAST8 "i"
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNdLEAST16 "hd"
+#define SCNiLEAST16 "hi"
+#define SCNdFAST16 "hd"
+#define SCNiFAST16 "hi"
+
+#define SCNd32 "ld"
+#define SCNi32 "li"
+#define SCNdLEAST32 "ld"
+#define SCNiLEAST32 "li"
+#define SCNdFAST32 "ld"
+#define SCNiFAST32 "li"
+
+#define SCNd64 "I64d"
+#define SCNi64 "I64i"
+#define SCNdLEAST64 "I64d"
+#define SCNiLEAST64 "I64i"
+#define SCNdFAST64 "I64d"
+#define SCNiFAST64 "I64i"
+
+#define SCNdMAX "I64d"
+#define SCNiMAX "I64i"
+
+#ifdef _WIN64 // [
+# define SCNdPTR "I64d"
+# define SCNiPTR "I64i"
+#else // _WIN64 ][
+# define SCNdPTR "ld"
+# define SCNiPTR "li"
+#endif // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8 "o"
+#define SCNu8 "u"
+#define SCNx8 "x"
+#define SCNX8 "X"
+#define SCNoLEAST8 "o"
+#define SCNuLEAST8 "u"
+#define SCNxLEAST8 "x"
+#define SCNXLEAST8 "X"
+#define SCNoFAST8 "o"
+#define SCNuFAST8 "u"
+#define SCNxFAST8 "x"
+#define SCNXFAST8 "X"
+
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+#define SCNX16 "hX"
+#define SCNoLEAST16 "ho"
+#define SCNuLEAST16 "hu"
+#define SCNxLEAST16 "hx"
+#define SCNXLEAST16 "hX"
+#define SCNoFAST16 "ho"
+#define SCNuFAST16 "hu"
+#define SCNxFAST16 "hx"
+#define SCNXFAST16 "hX"
+
+#define SCNo32 "lo"
+#define SCNu32 "lu"
+#define SCNx32 "lx"
+#define SCNX32 "lX"
+#define SCNoLEAST32 "lo"
+#define SCNuLEAST32 "lu"
+#define SCNxLEAST32 "lx"
+#define SCNXLEAST32 "lX"
+#define SCNoFAST32 "lo"
+#define SCNuFAST32 "lu"
+#define SCNxFAST32 "lx"
+#define SCNXFAST32 "lX"
+
+#define SCNo64 "I64o"
+#define SCNu64 "I64u"
+#define SCNx64 "I64x"
+#define SCNX64 "I64X"
+#define SCNoLEAST64 "I64o"
+#define SCNuLEAST64 "I64u"
+#define SCNxLEAST64 "I64x"
+#define SCNXLEAST64 "I64X"
+#define SCNoFAST64 "I64o"
+#define SCNuFAST64 "I64u"
+#define SCNxFAST64 "I64x"
+#define SCNXFAST64 "I64X"
+
+#define SCNoMAX "I64o"
+#define SCNuMAX "I64u"
+#define SCNxMAX "I64x"
+#define SCNXMAX "I64X"
+
+#ifdef _WIN64 // [
+# define SCNoPTR "I64o"
+# define SCNuPTR "I64u"
+# define SCNxPTR "I64x"
+# define SCNXPTR "I64X"
+#else // _WIN64 ][
+# define SCNoPTR "lo"
+# define SCNuPTR "lu"
+# define SCNxPTR "lx"
+# define SCNXPTR "lX"
+#endif // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ // did division wrong; must fix up
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#endif // _MSC_VER >= 1800
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/ext/librethinkdbxx/src/rapidjson/msinttypes/stdint.h b/ext/librethinkdbxx/src/rapidjson/msinttypes/stdint.h
new file mode 100644
index 00000000..3d4477b9
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/msinttypes/stdint.h
@@ -0,0 +1,300 @@
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006-2013 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the product nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// The above software in this distribution may have been modified by
+// THL A29 Limited ("Tencent Modifications").
+// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
+#if _MSC_VER >= 1600 // [
+#include <stdint.h>
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+#undef INT8_C
+#undef INT16_C
+#undef INT32_C
+#undef INT64_C
+#undef UINT8_C
+#undef UINT16_C
+#undef UINT32_C
+#undef UINT64_C
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C // [
+# define INTMAX_C INT64_C
+#endif // INTMAX_C ]
+#ifndef UINTMAX_C // [
+# define UINTMAX_C UINT64_C
+#endif // UINTMAX_C ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#else // ] _MSC_VER >= 1700 [
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler would give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#if defined(__cplusplus) && !defined(_M_ARM)
+extern "C" {
+#endif
+# include <wchar.h>
+#if defined(__cplusplus) && !defined(_M_ARM)
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+# define _W64 __w64
+# else
+# define _W64
+# endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+#else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+#endif
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef signed __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef _W64 signed int intptr_t;
+ typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
+// Check out Issue 9 for the details.
+#ifndef INTMAX_C // [
+# define INTMAX_C INT64_C
+#endif // INTMAX_C ]
+#ifndef UINTMAX_C // [
+# define UINTMAX_C UINT64_C
+#endif // UINTMAX_C ]
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+#endif // _MSC_VER >= 1600 ]
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/ext/librethinkdbxx/src/rapidjson/ostreamwrapper.h b/ext/librethinkdbxx/src/rapidjson/ostreamwrapper.h
new file mode 100644
index 00000000..6f4667c0
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/ostreamwrapper.h
@@ -0,0 +1,81 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
+#define RAPIDJSON_OSTREAMWRAPPER_H_
+
+#include "stream.h"
+#include <iosfwd>
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
+/*!
+ The classes can be wrapped including but not limited to:
+
+ - \c std::ostringstream
+ - \c std::stringstream
+ - \c std::wpstringstream
+ - \c std::wstringstream
+ - \c std::ifstream
+ - \c std::fstream
+ - \c std::wofstream
+ - \c std::wfstream
+
+ \tparam StreamType Class derived from \c std::basic_ostream.
+*/
+
+template <typename StreamType>
+class BasicOStreamWrapper {
+public:
+ typedef typename StreamType::char_type Ch;
+ BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
+
+ void Put(Ch c) {
+ stream_.put(c);
+ }
+
+ void Flush() {
+ stream_.flush();
+ }
+
+ // Not implemented
+ char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
+ char Take() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
+ char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
+
+private:
+ BasicOStreamWrapper(const BasicOStreamWrapper&);
+ BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
+
+ StreamType& stream_;
+};
+
+typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
+typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_OSTREAMWRAPPER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/pointer.h b/ext/librethinkdbxx/src/rapidjson/pointer.h
new file mode 100644
index 00000000..0206ac1c
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/pointer.h
@@ -0,0 +1,1358 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POINTER_H_
+#define RAPIDJSON_POINTER_H_
+
+#include "document.h"
+#include "internal/itoa.h"
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(switch-enum)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
+
+//! Error code of parsing.
+/*! \ingroup RAPIDJSON_ERRORS
+ \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
+*/
+enum PointerParseErrorCode {
+ kPointerParseErrorNone = 0, //!< The parse is successful
+
+ kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
+ kPointerParseErrorInvalidEscape, //!< Invalid escape
+ kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
+ kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericPointer
+
+//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
+/*!
+ This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
+ (https://tools.ietf.org/html/rfc6901).
+
+ A JSON pointer is for identifying a specific value in a JSON document
+ (GenericDocument). It can simplify coding of DOM tree manipulation, because it
+ can access multiple-level depth of DOM tree with single API call.
+
+ After it parses a string representation (e.g. "/foo/0" or URI fragment
+ representation (e.g. "#/foo/0") into its internal representation (tokens),
+ it can be used to resolve a specific value in multiple documents, or sub-tree
+ of documents.
+
+ Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
+ Apart from assignment, a Pointer cannot be modified after construction.
+
+ Although Pointer is very convenient, please aware that constructing Pointer
+ involves parsing and dynamic memory allocation. A special constructor with user-
+ supplied tokens eliminates these.
+
+ GenericPointer depends on GenericDocument and GenericValue.
+
+ \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
+ \tparam Allocator The allocator type for allocating memory for internal representation.
+
+ \note GenericPointer uses same encoding of ValueType.
+ However, Allocator of GenericPointer is independent of Allocator of Value.
+*/
+template <typename ValueType, typename Allocator = CrtAllocator>
+class GenericPointer {
+public:
+ typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
+ typedef typename ValueType::Ch Ch; //!< Character type from Value
+
+ //! A token is the basic units of internal representation.
+ /*!
+ A JSON pointer string representation "/foo/123" is parsed to two tokens:
+ "foo" and 123. 123 will be represented in both numeric form and string form.
+ They are resolved according to the actual value type (object or array).
+
+ For token that are not numbers, or the numeric value is out of bound
+ (greater than limits of SizeType), they are only treated as string form
+ (i.e. the token's index will be equal to kPointerInvalidIndex).
+
+ This struct is public so that user can create a Pointer without parsing and
+ allocation, using a special constructor.
+ */
+ struct Token {
+ const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
+ SizeType length; //!< Length of the name.
+ SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
+ };
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor.
+ GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+
+ //! Constructor that parses a string or URI fragment representation.
+ /*!
+ \param source A null-terminated, string or URI fragment representation of JSON pointer.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ */
+ explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source, internal::StrLen(source));
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor that parses a string or URI fragment representation.
+ /*!
+ \param source A string or URI fragment representation of JSON pointer.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source.c_str(), source.size());
+ }
+#endif
+
+ //! Constructor that parses a string or URI fragment representation, with length of the source string.
+ /*!
+ \param source A string or URI fragment representation of JSON pointer.
+ \param length Length of source.
+ \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
+ \note Slightly faster than the overload without length.
+ */
+ GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ Parse(source, length);
+ }
+
+ //! Constructor with user-supplied tokens.
+ /*!
+ This constructor let user supplies const array of tokens.
+ This prevents the parsing process and eliminates allocation.
+ This is preferred for memory constrained environments.
+
+ \param tokens An constant array of tokens representing the JSON pointer.
+ \param tokenCount Number of tokens.
+
+ \b Example
+ \code
+ #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
+ #define INDEX(i) { #i, sizeof(#i) - 1, i }
+
+ static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
+ static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
+ // Equivalent to static const Pointer p("/foo/123");
+
+ #undef NAME
+ #undef INDEX
+ \endcode
+ */
+ GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
+
+ //! Copy constructor.
+ GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
+ *this = rhs;
+ }
+
+ //! Destructor.
+ ~GenericPointer() {
+ if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
+ Allocator::Free(tokens_);
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ //! Assignment operator.
+ GenericPointer& operator=(const GenericPointer& rhs) {
+ if (this != &rhs) {
+ // Do not delete ownAllcator
+ if (nameBuffer_)
+ Allocator::Free(tokens_);
+
+ tokenCount_ = rhs.tokenCount_;
+ parseErrorOffset_ = rhs.parseErrorOffset_;
+ parseErrorCode_ = rhs.parseErrorCode_;
+
+ if (rhs.nameBuffer_)
+ CopyFromRaw(rhs); // Normally parsed tokens.
+ else {
+ tokens_ = rhs.tokens_; // User supplied const tokens.
+ nameBuffer_ = 0;
+ }
+ }
+ return *this;
+ }
+
+ //@}
+
+ //!@name Append token
+ //@{
+
+ //! Append a token and return a new Pointer
+ /*!
+ \param token Token to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
+ GenericPointer r;
+ r.allocator_ = allocator;
+ Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
+ std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
+ r.tokens_[tokenCount_].name = p;
+ r.tokens_[tokenCount_].length = token.length;
+ r.tokens_[tokenCount_].index = token.index;
+ return r;
+ }
+
+ //! Append a name token with length, and return a new Pointer
+ /*!
+ \param name Name to be appended.
+ \param length Length of name.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
+ Token token = { name, length, kPointerInvalidIndex };
+ return Append(token, allocator);
+ }
+
+ //! Append a name token without length, and return a new Pointer
+ /*!
+ \param name Name (const Ch*) to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
+ Append(T* name, Allocator* allocator = 0) const {
+ return Append(name, StrLen(name), allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Append a name token, and return a new Pointer
+ /*!
+ \param name Name to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
+ return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
+ }
+#endif
+
+ //! Append a index token, and return a new Pointer
+ /*!
+ \param index Index to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
+ char buffer[21];
+ char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
+ SizeType length = static_cast<SizeType>(end - buffer);
+ buffer[length] = '\0';
+
+ if (sizeof(Ch) == 1) {
+ Token token = { reinterpret_cast<Ch*>(buffer), length, index };
+ return Append(token, allocator);
+ }
+ else {
+ Ch name[21];
+ for (size_t i = 0; i <= length; i++)
+ name[i] = buffer[i];
+ Token token = { name, length, index };
+ return Append(token, allocator);
+ }
+ }
+
+ //! Append a token by value, and return a new Pointer
+ /*!
+ \param token token to be appended.
+ \param allocator Allocator for the newly return Pointer.
+ \return A new Pointer with appended token.
+ */
+ GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
+ if (token.IsString())
+ return Append(token.GetString(), token.GetStringLength(), allocator);
+ else {
+ RAPIDJSON_ASSERT(token.IsUint64());
+ RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
+ return Append(static_cast<SizeType>(token.GetUint64()), allocator);
+ }
+ }
+
+ //!@name Handling Parse Error
+ //@{
+
+ //! Check whether this is a valid pointer.
+ bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
+
+ //! Get the parsing error offset in code unit.
+ size_t GetParseErrorOffset() const { return parseErrorOffset_; }
+
+ //! Get the parsing error code.
+ PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
+
+ //@}
+
+ //! Get the allocator of this pointer.
+ Allocator& GetAllocator() { return *allocator_; }
+
+ //!@name Tokens
+ //@{
+
+ //! Get the token array (const version only).
+ const Token* GetTokens() const { return tokens_; }
+
+ //! Get the number of tokens.
+ size_t GetTokenCount() const { return tokenCount_; }
+
+ //@}
+
+ //!@name Equality/inequality operators
+ //@{
+
+ //! Equality operator.
+ /*!
+ \note When any pointers are invalid, always returns false.
+ */
+ bool operator==(const GenericPointer& rhs) const {
+ if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
+ return false;
+
+ for (size_t i = 0; i < tokenCount_; i++) {
+ if (tokens_[i].index != rhs.tokens_[i].index ||
+ tokens_[i].length != rhs.tokens_[i].length ||
+ (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //! Inequality operator.
+ /*!
+ \note When any pointers are invalid, always returns true.
+ */
+ bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
+
+ //@}
+
+ //!@name Stringify
+ //@{
+
+ //! Stringify the pointer into string representation.
+ /*!
+ \tparam OutputStream Type of output stream.
+ \param os The output stream.
+ */
+ template<typename OutputStream>
+ bool Stringify(OutputStream& os) const {
+ return Stringify<false, OutputStream>(os);
+ }
+
+ //! Stringify the pointer into URI fragment representation.
+ /*!
+ \tparam OutputStream Type of output stream.
+ \param os The output stream.
+ */
+ template<typename OutputStream>
+ bool StringifyUriFragment(OutputStream& os) const {
+ return Stringify<true, OutputStream>(os);
+ }
+
+ //@}
+
+ //!@name Create value
+ //@{
+
+ //! Create a value in a subtree.
+ /*!
+ If the value is not exist, it creates all parent values and a JSON Null value.
+ So it always succeed and return the newly created or existing value.
+
+ Remind that it may change types of parents according to tokens, so it
+ potentially removes previously stored values. For example, if a document
+ was an array, and "/foo" is used to create a value, then the document
+ will be changed to an object, and all existing array elements are lost.
+
+ \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
+ \return The resolved newly created (a JSON Null value), or already exists value.
+ */
+ ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
+ RAPIDJSON_ASSERT(IsValid());
+ ValueType* v = &root;
+ bool exist = true;
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
+ v->PushBack(ValueType().Move(), allocator);
+ v = &((*v)[v->Size() - 1]);
+ exist = false;
+ }
+ else {
+ if (t->index == kPointerInvalidIndex) { // must be object name
+ if (!v->IsObject())
+ v->SetObject(); // Change to Object
+ }
+ else { // object name or array index
+ if (!v->IsArray() && !v->IsObject())
+ v->SetArray(); // Change to Array
+ }
+
+ if (v->IsArray()) {
+ if (t->index >= v->Size()) {
+ v->Reserve(t->index + 1, allocator);
+ while (t->index >= v->Size())
+ v->PushBack(ValueType().Move(), allocator);
+ exist = false;
+ }
+ v = &((*v)[t->index]);
+ }
+ else {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd()) {
+ v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
+ v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
+ exist = false;
+ }
+ else
+ v = &m->value;
+ }
+ }
+ }
+
+ if (alreadyExist)
+ *alreadyExist = exist;
+
+ return *v;
+ }
+
+ //! Creates a value in a document.
+ /*!
+ \param document A document to be resolved.
+ \param alreadyExist If non-null, it stores whether the resolved value is already exist.
+ \return The resolved newly created, or already exists value.
+ */
+ template <typename stackAllocator>
+ ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
+ return Create(document, document.GetAllocator(), alreadyExist);
+ }
+
+ //@}
+
+ //!@name Query value
+ //@{
+
+ //! Query a value in a subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
+ \return Pointer to the value if it can be resolved. Otherwise null.
+
+ \note
+ There are only 3 situations when a value cannot be resolved:
+ 1. A value in the path is not an array nor object.
+ 2. An object value does not contain the token.
+ 3. A token is out of range of an array value.
+
+ Use unresolvedTokenIndex to retrieve the token index.
+ */
+ ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
+ RAPIDJSON_ASSERT(IsValid());
+ ValueType* v = &root;
+ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ switch (v->GetType()) {
+ case kObjectType:
+ {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd())
+ break;
+ v = &m->value;
+ }
+ continue;
+ case kArrayType:
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
+ break;
+ v = &((*v)[t->index]);
+ continue;
+ default:
+ break;
+ }
+
+ // Error: unresolved token
+ if (unresolvedTokenIndex)
+ *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
+ return 0;
+ }
+ return v;
+ }
+
+ //! Query a const value in a const subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Pointer to the value if it can be resolved. Otherwise null.
+ */
+ const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
+ return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
+ }
+
+ //@}
+
+ //!@name Query a value with default
+ //@{
+
+ //! Query a value in a subtree with default value.
+ /*!
+ Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
+ So that this function always succeed.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param defaultValue Default value to be cloned if the value was not exists.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
+ }
+
+ //! Query a value in a subtree with default null-terminated string.
+ ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Query a value in a subtree with default std::basic_string.
+ ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
+ bool alreadyExist;
+ Value& v = Create(root, allocator, &alreadyExist);
+ return alreadyExist ? v : v.SetString(defaultValue, allocator);
+ }
+#endif
+
+ //! Query a value in a subtree with default primitive value.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
+ return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
+ }
+
+ //! Query a value in a document with default value.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+ //! Query a value in a document with default null-terminated string.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Query a value in a document with default std::basic_string.
+ template <typename stackAllocator>
+ ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+#endif
+
+ //! Query a value in a document with default primitive value.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T, typename stackAllocator>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
+ return GetWithDefault(document, defaultValue, document.GetAllocator());
+ }
+
+ //@}
+
+ //!@name Set a value
+ //@{
+
+ //! Set a value in a subtree, with move semantics.
+ /*!
+ It creates all parents if they are not exist or types are different to the tokens.
+ So this function always succeeds but potentially remove existing values.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param value Value to be set.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = value;
+ }
+
+ //! Set a value in a subtree, with copy semantics.
+ ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator).CopyFrom(value, allocator);
+ }
+
+ //! Set a null-terminated string in a subtree.
+ ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value, allocator).Move();
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set a std::basic_string in a subtree.
+ ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value, allocator).Move();
+ }
+#endif
+
+ //! Set a primitive value in a subtree.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator) = ValueType(value).Move();
+ }
+
+ //! Set a value in a document, with move semantics.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
+ return Create(document) = value;
+ }
+
+ //! Set a value in a document, with copy semantics.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
+ return Create(document).CopyFrom(value, document.GetAllocator());
+ }
+
+ //! Set a null-terminated string in a document.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Sets a std::basic_string in a document.
+ template <typename stackAllocator>
+ ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
+ return Create(document) = ValueType(value, document.GetAllocator()).Move();
+ }
+#endif
+
+ //! Set a primitive value in a document.
+ /*!
+ \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
+ */
+ template <typename T, typename stackAllocator>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
+ Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
+ return Create(document) = value;
+ }
+
+ //@}
+
+ //!@name Swap a value
+ //@{
+
+ //! Swap a value with a value in a subtree.
+ /*!
+ It creates all parents if they are not exist or types are different to the tokens.
+ So this function always succeeds but potentially remove existing values.
+
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \param value Value to be swapped.
+ \param allocator Allocator for creating the values if the specified value or its parents are not exist.
+ \see Create()
+ */
+ ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
+ return Create(root, allocator).Swap(value);
+ }
+
+ //! Swap a value with a value in a document.
+ template <typename stackAllocator>
+ ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
+ return Create(document).Swap(value);
+ }
+
+ //@}
+
+ //! Erase a value in a subtree.
+ /*!
+ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
+ \return Whether the resolved value is found and erased.
+
+ \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
+ */
+ bool Erase(ValueType& root) const {
+ RAPIDJSON_ASSERT(IsValid());
+ if (tokenCount_ == 0) // Cannot erase the root
+ return false;
+
+ ValueType* v = &root;
+ const Token* last = tokens_ + (tokenCount_ - 1);
+ for (const Token *t = tokens_; t != last; ++t) {
+ switch (v->GetType()) {
+ case kObjectType:
+ {
+ typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
+ if (m == v->MemberEnd())
+ return false;
+ v = &m->value;
+ }
+ break;
+ case kArrayType:
+ if (t->index == kPointerInvalidIndex || t->index >= v->Size())
+ return false;
+ v = &((*v)[t->index]);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ switch (v->GetType()) {
+ case kObjectType:
+ return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
+ case kArrayType:
+ if (last->index == kPointerInvalidIndex || last->index >= v->Size())
+ return false;
+ v->Erase(v->Begin() + last->index);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+private:
+ //! Clone the content from rhs to this.
+ /*!
+ \param rhs Source pointer.
+ \param extraToken Extra tokens to be allocated.
+ \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
+ \return Start of non-occupied name buffer, for storing extra names.
+ */
+ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
+ if (!allocator_) // allocator is independently owned.
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
+ for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
+ nameBufferSize += t->length;
+
+ tokenCount_ = rhs.tokenCount_ + extraToken;
+ tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
+ nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
+ if (rhs.tokenCount_ > 0) {
+ std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
+ }
+ if (nameBufferSize > 0) {
+ std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
+ }
+
+ // Adjust pointers to name buffer
+ std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
+ for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
+ t->name += diff;
+
+ return nameBuffer_ + nameBufferSize;
+ }
+
+ //! Check whether a character should be percent-encoded.
+ /*!
+ According to RFC 3986 2.3 Unreserved Characters.
+ \param c The character (code unit) to be tested.
+ */
+ bool NeedPercentEncode(Ch c) const {
+ return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
+ }
+
+ //! Parse a JSON String or its URI fragment representation into tokens.
+#ifndef __clang__ // -Wdocumentation
+ /*!
+ \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
+ \param length Length of the source string.
+ \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
+ */
+#endif
+ void Parse(const Ch* source, size_t length) {
+ RAPIDJSON_ASSERT(source != NULL);
+ RAPIDJSON_ASSERT(nameBuffer_ == 0);
+ RAPIDJSON_ASSERT(tokens_ == 0);
+
+ // Create own allocator if user did not supply.
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ // Count number of '/' as tokenCount
+ tokenCount_ = 0;
+ for (const Ch* s = source; s != source + length; s++)
+ if (*s == '/')
+ tokenCount_++;
+
+ Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
+ Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
+ size_t i = 0;
+
+ // Detect if it is a URI fragment
+ bool uriFragment = false;
+ if (source[i] == '#') {
+ uriFragment = true;
+ i++;
+ }
+
+ if (i != length && source[i] != '/') {
+ parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
+ goto error;
+ }
+
+ while (i < length) {
+ RAPIDJSON_ASSERT(source[i] == '/');
+ i++; // consumes '/'
+
+ token->name = name;
+ bool isNumber = true;
+
+ while (i < length && source[i] != '/') {
+ Ch c = source[i];
+ if (uriFragment) {
+ // Decoding percent-encoding for URI fragment
+ if (c == '%') {
+ PercentDecodeStream is(&source[i], source + length);
+ GenericInsituStringStream<EncodingType> os(name);
+ Ch* begin = os.PutBegin();
+ if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
+ parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
+ goto error;
+ }
+ size_t len = os.PutEnd(begin);
+ i += is.Tell() - 1;
+ if (len == 1)
+ c = *name;
+ else {
+ name += len;
+ isNumber = false;
+ i++;
+ continue;
+ }
+ }
+ else if (NeedPercentEncode(c)) {
+ parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
+ goto error;
+ }
+ }
+
+ i++;
+
+ // Escaping "~0" -> '~', "~1" -> '/'
+ if (c == '~') {
+ if (i < length) {
+ c = source[i];
+ if (c == '0') c = '~';
+ else if (c == '1') c = '/';
+ else {
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
+ goto error;
+ }
+ i++;
+ }
+ else {
+ parseErrorCode_ = kPointerParseErrorInvalidEscape;
+ goto error;
+ }
+ }
+
+ // First check for index: all of characters are digit
+ if (c < '0' || c > '9')
+ isNumber = false;
+
+ *name++ = c;
+ }
+ token->length = static_cast<SizeType>(name - token->name);
+ if (token->length == 0)
+ isNumber = false;
+ *name++ = '\0'; // Null terminator
+
+ // Second check for index: more than one digit cannot have leading zero
+ if (isNumber && token->length > 1 && token->name[0] == '0')
+ isNumber = false;
+
+ // String to SizeType conversion
+ SizeType n = 0;
+ if (isNumber) {
+ for (size_t j = 0; j < token->length; j++) {
+ SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
+ if (m < n) { // overflow detection
+ isNumber = false;
+ break;
+ }
+ n = m;
+ }
+ }
+
+ token->index = isNumber ? n : kPointerInvalidIndex;
+ token++;
+ }
+
+ RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
+ parseErrorCode_ = kPointerParseErrorNone;
+ return;
+
+ error:
+ Allocator::Free(tokens_);
+ nameBuffer_ = 0;
+ tokens_ = 0;
+ tokenCount_ = 0;
+ parseErrorOffset_ = i;
+ return;
+ }
+
+ //! Stringify to string or URI fragment representation.
+ /*!
+ \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
+ \tparam OutputStream type of output stream.
+ \param os The output stream.
+ */
+ template<bool uriFragment, typename OutputStream>
+ bool Stringify(OutputStream& os) const {
+ RAPIDJSON_ASSERT(IsValid());
+
+ if (uriFragment)
+ os.Put('#');
+
+ for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
+ os.Put('/');
+ for (size_t j = 0; j < t->length; j++) {
+ Ch c = t->name[j];
+ if (c == '~') {
+ os.Put('~');
+ os.Put('0');
+ }
+ else if (c == '/') {
+ os.Put('~');
+ os.Put('1');
+ }
+ else if (uriFragment && NeedPercentEncode(c)) {
+ // Transcode to UTF8 sequence
+ GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
+ PercentEncodeStream<OutputStream> target(os);
+ if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
+ return false;
+ j += source.Tell() - 1;
+ }
+ else
+ os.Put(c);
+ }
+ }
+ return true;
+ }
+
+ //! A helper stream for decoding a percent-encoded sequence into code unit.
+ /*!
+ This stream decodes %XY triplet into code unit (0-255).
+ If it encounters invalid characters, it sets output code unit as 0 and
+ mark invalid, and to be checked by IsValid().
+ */
+ class PercentDecodeStream {
+ public:
+ typedef typename ValueType::Ch Ch;
+
+ //! Constructor
+ /*!
+ \param source Start of the stream
+ \param end Past-the-end of the stream.
+ */
+ PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
+
+ Ch Take() {
+ if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
+ valid_ = false;
+ return 0;
+ }
+ src_++;
+ Ch c = 0;
+ for (int j = 0; j < 2; j++) {
+ c = static_cast<Ch>(c << 4);
+ Ch h = *src_;
+ if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
+ else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
+ else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
+ else {
+ valid_ = false;
+ return 0;
+ }
+ src_++;
+ }
+ return c;
+ }
+
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+ bool IsValid() const { return valid_; }
+
+ private:
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+ const Ch* end_; //!< Past-the-end position.
+ bool valid_; //!< Whether the parsing is valid.
+ };
+
+ //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
+ template <typename OutputStream>
+ class PercentEncodeStream {
+ public:
+ PercentEncodeStream(OutputStream& os) : os_(os) {}
+ void Put(char c) { // UTF-8 must be byte
+ unsigned char u = static_cast<unsigned char>(c);
+ static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ os_.Put('%');
+ os_.Put(hexDigits[u >> 4]);
+ os_.Put(hexDigits[u & 15]);
+ }
+ private:
+ OutputStream& os_;
+ };
+
+ Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
+ Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
+ Ch* nameBuffer_; //!< A buffer containing all names in tokens.
+ Token* tokens_; //!< A list of tokens.
+ size_t tokenCount_; //!< Number of tokens in tokens_.
+ size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
+ PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
+};
+
+//! GenericPointer for Value (UTF-8, default allocator).
+typedef GenericPointer<Value> Pointer;
+
+//!@name Helper functions for GenericPointer
+//@{
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
+ return pointer.Create(root, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
+ return pointer.Create(document);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
+ return pointer.Get(root, unresolvedTokenIndex);
+}
+
+template <typename T>
+const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
+ return pointer.Get(root, unresolvedTokenIndex);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
+}
+
+template <typename T, typename CharType, size_t N>
+const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+#endif
+
+template <typename T, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
+ return pointer.GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+#endif
+
+template <typename T, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+#endif
+
+template <typename DocumentType, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
+ return pointer.GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+#endif
+
+template <typename DocumentType, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T>
+typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+#endif
+
+template <typename T, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
+ return pointer.Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+#endif
+
+template <typename T, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
+SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
+}
+
+// No allocator parameter
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
+ return pointer.Set(document, value);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
+ return pointer.Set(document, value);
+}
+#endif
+
+template <typename DocumentType, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
+ return pointer.Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+#endif
+
+template <typename DocumentType, typename CharType, size_t N, typename T2>
+RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
+SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
+ return pointer.Swap(root, value, a);
+}
+
+template <typename T, typename CharType, size_t N>
+typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
+}
+
+template <typename DocumentType>
+typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
+ return pointer.Swap(document, value);
+}
+
+template <typename DocumentType, typename CharType, size_t N>
+typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
+ return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
+ return pointer.Erase(root);
+}
+
+template <typename T, typename CharType, size_t N>
+bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
+ return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
+}
+
+//@}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_POINTER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/prettywriter.h b/ext/librethinkdbxx/src/rapidjson/prettywriter.h
new file mode 100644
index 00000000..75dc474f
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/prettywriter.h
@@ -0,0 +1,249 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Combination of PrettyWriter format flags.
+/*! \see PrettyWriter::SetFormatOptions
+ */
+enum PrettyFormatOptions {
+ kFormatDefault = 0, //!< Default pretty formatting.
+ kFormatSingleLineArray = 1 //!< Format arrays on a single line.
+};
+
+//! Writer with indentation and spacing.
+/*!
+ \tparam OutputStream Type of ouptut os.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
+public:
+ typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+ typedef typename Base::Ch Ch;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param allocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
+
+
+ explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+ //! Set custom indentation.
+ /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
+ \param indentCharCount Number of indent characters for each indentation level.
+ \note The default indentation is 4 spaces.
+ */
+ PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+ RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+ indentChar_ = indentChar;
+ indentCharCount_ = indentCharCount;
+ return *this;
+ }
+
+ //! Set pretty writer formatting options.
+ /*! \param options Formatting options.
+ */
+ PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
+ formatOptions_ = options;
+ return *this;
+ }
+
+ /*! @name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
+ bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
+ bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
+ bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
+ bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
+ bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
+ bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kNumberType);
+ return Base::WriteString(str, length);
+ }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kStringType);
+ return Base::WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ PrettyPrefix(kObjectType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+ return Base::WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndObject();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ bool StartArray() {
+ PrettyPrefix(kArrayType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+ return Base::WriteStartArray();
+ }
+
+ bool EndArray(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndArray();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! Simpler but slower overload.
+ bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+ //@}
+
+ //! Write a raw JSON value.
+ /*!
+ For user to write a stringified JSON as a value.
+
+ \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
+ \param length Length of the json.
+ \param type Type of the root of json.
+ \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
+ */
+ bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
+
+protected:
+ void PrettyPrefix(Type type) {
+ (void)type;
+ if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+ typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+ if (level->inArray) {
+ if (level->valueCount > 0) {
+ Base::os_->Put(','); // add comma if it is not the first element in array
+ if (formatOptions_ & kFormatSingleLineArray)
+ Base::os_->Put(' ');
+ }
+
+ if (!(formatOptions_ & kFormatSingleLineArray)) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ }
+ else { // in object
+ if (level->valueCount > 0) {
+ if (level->valueCount % 2 == 0) {
+ Base::os_->Put(',');
+ Base::os_->Put('\n');
+ }
+ else {
+ Base::os_->Put(':');
+ Base::os_->Put(' ');
+ }
+ }
+ else
+ Base::os_->Put('\n');
+
+ if (level->valueCount % 2 == 0)
+ WriteIndent();
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
+ Base::hasRoot_ = true;
+ }
+ }
+
+ void WriteIndent() {
+ size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
+ PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
+ }
+
+ Ch indentChar_;
+ unsigned indentCharCount_;
+ PrettyFormatOptions formatOptions_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ PrettyWriter(const PrettyWriter&);
+ PrettyWriter& operator=(const PrettyWriter&);
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/rapidjson.h b/ext/librethinkdbxx/src/rapidjson/rapidjson.h
new file mode 100644
index 00000000..d666f202
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/rapidjson.h
@@ -0,0 +1,615 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+/*!\file rapidjson.h
+ \brief common definitions and configuration
+
+ \see RAPIDJSON_CONFIG
+ */
+
+/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
+ \brief Configuration macros for library features
+
+ Some RapidJSON features are configurable to adapt the library to a wide
+ variety of platforms, environments and usage scenarios. Most of the
+ features can be configured in terms of overriden or predefined
+ preprocessor macros at compile-time.
+
+ Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
+
+ \note These macros should be given on the compiler command-line
+ (where applicable) to avoid inconsistent values when compiling
+ different translation units of a single application.
+ */
+
+#include <cstdlib> // malloc(), realloc(), free(), size_t
+#include <cstring> // memset(), memcpy(), memmove(), memcmp()
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_VERSION_STRING
+//
+// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
+//
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+// token stringification
+#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
+#define RAPIDJSON_DO_STRINGIFY(x) #x
+//!@endcond
+
+/*! \def RAPIDJSON_MAJOR_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Major version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_MINOR_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Minor version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_PATCH_VERSION
+ \ingroup RAPIDJSON_CONFIG
+ \brief Patch version of RapidJSON in integer.
+*/
+/*! \def RAPIDJSON_VERSION_STRING
+ \ingroup RAPIDJSON_CONFIG
+ \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
+*/
+#define RAPIDJSON_MAJOR_VERSION 1
+#define RAPIDJSON_MINOR_VERSION 0
+#define RAPIDJSON_PATCH_VERSION 2
+#define RAPIDJSON_VERSION_STRING \
+ RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NAMESPACE_(BEGIN|END)
+/*! \def RAPIDJSON_NAMESPACE
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace
+
+ In order to avoid symbol clashes and/or "One Definition Rule" errors
+ between multiple inclusions of (different versions of) RapidJSON in
+ a single binary, users can customize the name of the main RapidJSON
+ namespace.
+
+ In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
+ to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple
+ levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
+ RAPIDJSON_NAMESPACE_END need to be defined as well:
+
+ \code
+ // in some .cpp file
+ #define RAPIDJSON_NAMESPACE my::rapidjson
+ #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
+ #define RAPIDJSON_NAMESPACE_END } }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson
+ */
+/*! \def RAPIDJSON_NAMESPACE_BEGIN
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (opening expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+/*! \def RAPIDJSON_NAMESPACE_END
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (closing expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+#ifndef RAPIDJSON_NAMESPACE
+#define RAPIDJSON_NAMESPACE rapidjson
+#endif
+#ifndef RAPIDJSON_NAMESPACE_BEGIN
+#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
+#endif
+#ifndef RAPIDJSON_NAMESPACE_END
+#define RAPIDJSON_NAMESPACE_END }
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_HAS_STDSTRING
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
+#else
+#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
+#endif
+/*! \def RAPIDJSON_HAS_STDSTRING
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable RapidJSON support for \c std::string
+
+ By defining this preprocessor symbol to \c 1, several convenience functions for using
+ \ref rapidjson::GenericValue with \c std::string are enabled, especially
+ for construction and comparison.
+
+ \hideinitializer
+*/
+#endif // !defined(RAPIDJSON_HAS_STDSTRING)
+
+#if RAPIDJSON_HAS_STDSTRING
+#include <string>
+#endif // RAPIDJSON_HAS_STDSTRING
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_INT64DEFINE
+
+/*! \def RAPIDJSON_NO_INT64DEFINE
+ \ingroup RAPIDJSON_CONFIG
+ \brief Use external 64-bit integer types.
+
+ RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types
+ to be available at global scope.
+
+ If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
+ prevent RapidJSON from defining its own types.
+*/
+#ifndef RAPIDJSON_NO_INT64DEFINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
+#include "msinttypes/stdint.h"
+#include "msinttypes/inttypes.h"
+#else
+// Other compilers should have this.
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+//!@endcond
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_INT64DEFINE
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_FORCEINLINE
+
+#ifndef RAPIDJSON_FORCEINLINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#if defined(_MSC_VER) && defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
+#else
+#define RAPIDJSON_FORCEINLINE
+#endif
+//!@endcond
+#endif // RAPIDJSON_FORCEINLINE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
+
+//! Endianness of the machine.
+/*!
+ \def RAPIDJSON_ENDIAN
+ \ingroup RAPIDJSON_CONFIG
+
+ GCC 4.6 provided macro for detecting endianness of the target machine. But other
+ compilers may not have this. User can define RAPIDJSON_ENDIAN to either
+ \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
+
+ Default detection implemented with reference to
+ \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
+ \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
+*/
+#ifndef RAPIDJSON_ENDIAN
+// Detect with GCC 4.6's macro
+# ifdef __BYTE_ORDER__
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif // __BYTE_ORDER__
+// Detect with GLIBC's endian.h
+# elif defined(__GLIBC__)
+# include <endian.h>
+# if (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif (__BYTE_ORDER == __BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif // __GLIBC__
+// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
+# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+// Detect with architecture macros
+# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(_MSC_VER) && defined(_M_ARM)
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
+# define RAPIDJSON_ENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_64BIT
+
+//! Whether using 64-bit architecture
+#ifndef RAPIDJSON_64BIT
+#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__)
+#define RAPIDJSON_64BIT 1
+#else
+#define RAPIDJSON_64BIT 0
+#endif
+#endif // RAPIDJSON_64BIT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ALIGN
+
+//! Data alignment of the machine.
+/*! \ingroup RAPIDJSON_CONFIG
+ \param x pointer to align
+
+ Some machines require strict data alignment. Currently the default uses 4 bytes
+ alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
+ User can customize by defining the RAPIDJSON_ALIGN function macro.
+*/
+#ifndef RAPIDJSON_ALIGN
+#if RAPIDJSON_64BIT == 1
+#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
+#else
+#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_UINT64_C2
+
+//! Construct a 64-bit literal by a pair of 32-bit integer.
+/*!
+ 64-bit literal with or without ULL suffix is prone to compiler warnings.
+ UINT64_C() is C macro which cause compilation problems.
+ Use this macro to define 64-bit constants by a pair of 32-bit integer.
+*/
+#ifndef RAPIDJSON_UINT64_C2
+#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+//! Use only lower 48-bit address for some pointers.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+
+ This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
+ The higher 16-bit can be used for storing other data.
+ \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
+*/
+#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
+#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
+#else
+#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
+#endif
+#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
+
+#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
+#if RAPIDJSON_64BIT != 1
+#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
+#endif
+#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
+#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
+#else
+#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
+#define RAPIDJSON_GETPOINTER(type, p) (p)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+/*! \def RAPIDJSON_SIMD
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable SSE2/SSE4.2 optimization.
+
+ RapidJSON supports optimized implementations for some parsing operations
+ based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
+ processors.
+
+ To enable these optimizations, two different symbols can be defined;
+ \code
+ // Enable SSE2 optimization.
+ #define RAPIDJSON_SSE2
+
+ // Enable SSE4.2 optimization.
+ #define RAPIDJSON_SSE42
+ \endcode
+
+ \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+
+ If any of these symbols is defined, RapidJSON defines the macro
+ \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
+*/
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
+ || defined(RAPIDJSON_DOXYGEN_RUNNING)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
+/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-provided \c SizeType definition.
+
+ In order to avoid using 32-bit size types for indexing strings and arrays,
+ define this preprocessor symbol and provide the type rapidjson::SizeType
+ before including RapidJSON:
+ \code
+ #define RAPIDJSON_NO_SIZETYPEDEFINE
+ namespace rapidjson { typedef ::std::size_t SizeType; }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson::SizeType
+*/
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_SIZETYPEDEFINE
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+//! Size type (for string lengths, array sizes, etc.)
+/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
+ instead of using \c size_t. Users may override the SizeType by defining
+ \ref RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+RAPIDJSON_NAMESPACE_END
+#endif
+
+// always import std::size_t to rapidjson namespace
+RAPIDJSON_NAMESPACE_BEGIN
+using std::size_t;
+RAPIDJSON_NAMESPACE_END
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! \ingroup RAPIDJSON_CONFIG
+ By default, rapidjson uses C \c assert() for internal assertions.
+ User can override it by defining RAPIDJSON_ASSERT(x) macro.
+
+ \note Parsing errors are handled and can be customized by the
+ \ref RAPIDJSON_ERRORS APIs.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_STATIC_ASSERT
+
+// Adopt from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+#ifndef __clang__
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#endif
+RAPIDJSON_NAMESPACE_BEGIN
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+template<int x> struct StaticAssertTest {};
+RAPIDJSON_NAMESPACE_END
+
+#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
+#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
+#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
+
+#if defined(__GNUC__)
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+#else
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+#ifndef __clang__
+//!@endcond
+#endif
+
+/*! \def RAPIDJSON_STATIC_ASSERT
+ \brief (Internal) macro to check for conditions at compile-time
+ \param x compile-time condition
+ \hideinitializer
+ */
+#define RAPIDJSON_STATIC_ASSERT(x) \
+ typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
+ sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
+ RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
+
+//! Compiler branching hint for expression with high probability to be true.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+ \param x Boolean expression likely to be true.
+*/
+#ifndef RAPIDJSON_LIKELY
+#if defined(__GNUC__) || defined(__clang__)
+#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
+#else
+#define RAPIDJSON_LIKELY(x) (x)
+#endif
+#endif
+
+//! Compiler branching hint for expression with low probability to be true.
+/*!
+ \ingroup RAPIDJSON_CONFIG
+ \param x Boolean expression unlikely to be true.
+*/
+#ifndef RAPIDJSON_UNLIKELY
+#if defined(__GNUC__) || defined(__clang__)
+#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define RAPIDJSON_UNLIKELY(x) (x)
+#endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+// adopted from Boost
+#define RAPIDJSON_VERSION_CODE(x,y,z) \
+ (((x)*100000) + ((y)*100) + (z))
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
+
+#if defined(__GNUC__)
+#define RAPIDJSON_GNUC \
+ RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
+
+#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
+#define RAPIDJSON_DIAG_OFF(x) \
+ RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
+
+// push/pop support in Clang and GCC>=4.6
+#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
+#else // GCC >= 4.2, < 4.6
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+#endif
+
+#elif defined(_MSC_VER)
+
+// pragma (MSVC specific)
+#define RAPIDJSON_PRAGMA(x) __pragma(x)
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
+
+#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
+#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
+#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
+
+#else
+
+#define RAPIDJSON_DIAG_OFF(x) /* ignored */
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+
+#endif // RAPIDJSON_DIAG_*
+
+///////////////////////////////////////////////////////////////////////////////
+// C++11 features
+
+#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#if defined(__clang__)
+#if __has_feature(cxx_rvalue_references) && \
+ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
+// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#else
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
+#endif
+#endif
+#if RAPIDJSON_HAS_CXX11_NOEXCEPT
+#define RAPIDJSON_NOEXCEPT noexcept
+#else
+#define RAPIDJSON_NOEXCEPT /* noexcept */
+#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
+
+// no automatic detection, yet
+#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
+#endif
+
+#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1700)
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
+#else
+#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
+
+//!@endcond
+
+///////////////////////////////////////////////////////////////////////////////
+// new/delete
+
+#ifndef RAPIDJSON_NEW
+///! customization point for global \c new
+#define RAPIDJSON_NEW(x) new x
+#endif
+#ifndef RAPIDJSON_DELETE
+///! customization point for global \c delete
+#define RAPIDJSON_DELETE(x) delete x
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+/*! \namespace rapidjson
+ \brief main RapidJSON namespace
+ \see RAPIDJSON_NAMESPACE
+*/
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Type of JSON value
+enum Type {
+ kNullType = 0, //!< null
+ kFalseType = 1, //!< false
+ kTrueType = 2, //!< true
+ kObjectType = 3, //!< object
+ kArrayType = 4, //!< array
+ kStringType = 5, //!< string
+ kNumberType = 6 //!< number
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/reader.h b/ext/librethinkdbxx/src/rapidjson/reader.h
new file mode 100644
index 00000000..19f8849b
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/reader.h
@@ -0,0 +1,1879 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+/*! \file reader.h */
+
+#include "allocators.h"
+#include "stream.h"
+#include "encodedstream.h"
+#include "internal/meta.h"
+#include "internal/stack.h"
+#include "internal/strtod.h"
+#include <limits>
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(old-style-cast)
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(switch-enum)
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define RAPIDJSON_NOTHING /* deliberately empty */
+#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
+//!@endcond
+
+/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
+ \ingroup RAPIDJSON_ERRORS
+ \brief Macro to indicate a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ This macros can be used as a customization point for the internal
+ error handling mechanism of RapidJSON.
+
+ A common usage model is to throw an exception instead of requiring the
+ caller to explicitly check the \ref rapidjson::GenericReader::Parse's
+ return value:
+
+ \code
+ #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
+ throw ParseException(parseErrorCode, #parseErrorCode, offset)
+
+ #include <stdexcept> // std::runtime_error
+ #include "rapidjson/error/error.h" // rapidjson::ParseResult
+
+ struct ParseException : std::runtime_error, rapidjson::ParseResult {
+ ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
+ : std::runtime_error(msg), ParseResult(code, offset) {}
+ };
+
+ #include "rapidjson/reader.h"
+ \endcode
+
+ \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
+ */
+#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
+#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
+ SetParseError(parseErrorCode, offset); \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+/*! \def RAPIDJSON_PARSE_ERROR
+ \ingroup RAPIDJSON_ERRORS
+ \brief (Internal) macro to indicate and handle a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
+
+ \see RAPIDJSON_PARSE_ERROR_NORETURN
+ \hideinitializer
+ */
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+#include "error/error.h" // ParseErrorCode, ParseResult
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kParseDefaultFlags definition.
+
+ User can define this as any \c ParseFlag combinations.
+*/
+#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
+#endif
+
+//! Combination of parseFlags
+/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
+ */
+enum ParseFlag {
+ kParseNoFlags = 0, //!< No flags are set.
+ kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
+ kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
+ kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
+ kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
+ kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
+ kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
+ kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
+ kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
+ kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
+ kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+ \brief Concept for receiving events from GenericReader upon parsing.
+ The functions return true if no error occurs. If they return false,
+ the event publisher should terminate the process.
+\code
+concept Handler {
+ typename Ch;
+
+ bool Null();
+ bool Bool(bool b);
+ bool Int(int i);
+ bool Uint(unsigned i);
+ bool Int64(int64_t i);
+ bool Uint64(uint64_t i);
+ bool Double(double d);
+ /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
+ bool RawNumber(const Ch* str, SizeType length, bool copy);
+ bool String(const Ch* str, SizeType length, bool copy);
+ bool StartObject();
+ bool Key(const Ch* str, SizeType length, bool copy);
+ bool EndObject(SizeType memberCount);
+ bool StartArray();
+ bool EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+ \note implements Handler concept
+*/
+template<typename Encoding = UTF8<>, typename Derived = void>
+struct BaseReaderHandler {
+ typedef typename Encoding::Ch Ch;
+
+ typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
+
+ bool Default() { return true; }
+ bool Null() { return static_cast<Override&>(*this).Default(); }
+ bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
+ bool Int(int) { return static_cast<Override&>(*this).Default(); }
+ bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
+ bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
+ bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
+ bool Double(double) { return static_cast<Override&>(*this).Default(); }
+ /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
+ bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+ bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
+ bool StartObject() { return static_cast<Override&>(*this).Default(); }
+ bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
+ bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
+ bool StartArray() { return static_cast<Override&>(*this).Default(); }
+ bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamLocalCopy
+
+namespace internal {
+
+template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
+class StreamLocalCopy;
+
+//! Do copy optimization.
+template<typename Stream>
+class StreamLocalCopy<Stream, 1> {
+public:
+ StreamLocalCopy(Stream& original) : s(original), original_(original) {}
+ ~StreamLocalCopy() { original_ = s; }
+
+ Stream s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+
+ Stream& original_;
+};
+
+//! Keep reference.
+template<typename Stream>
+class StreamLocalCopy<Stream, 0> {
+public:
+ StreamLocalCopy(Stream& original) : s(original) {}
+
+ Stream& s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param is A input stream for skipping white spaces.
+ \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename InputStream>
+void SkipWhitespace(InputStream& is) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ typename InputStream::Ch c;
+ while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
+ s.Take();
+}
+
+inline const char* SkipWhitespace(const char* p, const char* end) {
+ while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ return p;
+}
+
+#ifdef RAPIDJSON_SSE42
+//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+ if (r != 0) { // some of characters is non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ // The middle of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
+
+ for (; p <= end - 16; p += 16) {
+ const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
+ const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+ if (r != 0) { // some of characters is non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+
+ return SkipWhitespace(p, end);
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
+ static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
+ #undef C16
+
+ const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
+ const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
+ const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
+ const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ __m128i x = _mm_cmpeq_epi8(s, w0);
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+ unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
+ if (r != 0) { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
+ // Fast return for single non-whitespace
+ if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
+ static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
+ #undef C16
+
+ const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
+ const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
+ const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
+ const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
+
+ for (; p <= end - 16; p += 16) {
+ const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
+ __m128i x = _mm_cmpeq_epi8(s, w0);
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+ unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
+ if (r != 0) { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ return p + offset;
+#else
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+
+ return SkipWhitespace(p, end);
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& is) {
+ is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& is) {
+ is.src_ = SkipWhitespace_SIMD(is.src_);
+}
+
+template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
+ is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an
+ object implementing Handler concept.
+
+ It needs to allocate a stack for storing a single decoded string during
+ non-destructive parsing.
+
+ For in-situ parsing, the decoded string is directly written to the source
+ text string, no temporary buffer is required.
+
+ A GenericReader object can be reused for parsing multiple JSON text.
+
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam TargetEncoding Encoding of the parse output.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
+class GenericReader {
+public:
+ typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
+
+ //! Constructor.
+ /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+ \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
+ */
+ GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
+
+ //! Parse JSON text.
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ if (parseFlags & kParseIterativeFlag)
+ return IterativeParse<parseFlags>(is, handler);
+
+ parseResult_.Clear();
+
+ ClearStackOnExit scope(*this);
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ else {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (!(parseFlags & kParseStopWhenDoneFlag)) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ }
+ }
+
+ return parseResult_;
+ }
+
+ //! Parse JSON text (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ return Parse<kParseDefaultFlags>(is, handler);
+ }
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+protected:
+ void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericReader(const GenericReader&);
+ GenericReader& operator=(const GenericReader&);
+
+ void ClearStack() { stack_.Clear(); }
+
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
+ ~ClearStackOnExit() { r_.ClearStack(); }
+ private:
+ GenericReader& r_;
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ };
+
+ template<unsigned parseFlags, typename InputStream>
+ void SkipWhitespaceAndComments(InputStream& is) {
+ SkipWhitespace(is);
+
+ if (parseFlags & kParseCommentsFlag) {
+ while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
+ if (Consume(is, '*')) {
+ while (true) {
+ if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+ else if (Consume(is, '*')) {
+ if (Consume(is, '/'))
+ break;
+ }
+ else
+ is.Take();
+ }
+ }
+ else if (RAPIDJSON_LIKELY(Consume(is, '/')))
+ while (is.Peek() != '\0' && is.Take() != '\n');
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+
+ SkipWhitespace(is);
+ }
+ }
+ }
+
+ // Parse object: { string : value, ... }
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseObject(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '{');
+ is.Take(); // Skip '{'
+
+ if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (Consume(is, '}')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType memberCount = 0;;) {
+ if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+
+ ParseString<parseFlags>(is, handler, true);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++memberCount;
+
+ switch (is.Peek()) {
+ case ',':
+ is.Take();
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ break;
+ case '}':
+ is.Take();
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ default:
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
+ }
+
+ if (parseFlags & kParseTrailingCommasFlag) {
+ if (is.Peek() == '}') {
+ if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ is.Take();
+ return;
+ }
+ }
+ }
+ }
+
+ // Parse array: [ value, ... ]
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseArray(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '[');
+ is.Take(); // Skip '['
+
+ if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (Consume(is, ']')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType elementCount = 0;;) {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++elementCount;
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ if (Consume(is, ',')) {
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ }
+ else if (Consume(is, ']')) {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+
+ if (parseFlags & kParseTrailingCommasFlag) {
+ if (is.Peek() == ']') {
+ if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ is.Take();
+ return;
+ }
+ }
+ }
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNull(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'n');
+ is.Take();
+
+ if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Null()))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseTrue(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 't');
+ is.Take();
+
+ if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseFalse(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'f');
+ is.Take();
+
+ if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
+ if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
+ }
+
+ template<typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
+ if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
+ is.Take();
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+ template<typename InputStream>
+ unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; i++) {
+ Ch c = is.Peek();
+ codepoint <<= 4;
+ codepoint += static_cast<unsigned>(c);
+ if (c >= '0' && c <= '9')
+ codepoint -= '0';
+ else if (c >= 'A' && c <= 'F')
+ codepoint -= 'A' - 10;
+ else if (c >= 'a' && c <= 'f')
+ codepoint -= 'a' - 10;
+ else {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
+ }
+ is.Take();
+ }
+ return codepoint;
+ }
+
+ template <typename CharType>
+ class StackStream {
+ public:
+ typedef CharType Ch;
+
+ StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
+ RAPIDJSON_FORCEINLINE void Put(Ch c) {
+ *stack_.template Push<Ch>() = c;
+ ++length_;
+ }
+
+ RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
+ length_ += count;
+ return stack_.template Push<Ch>(count);
+ }
+
+ size_t Length() const { return length_; }
+
+ Ch* Pop() {
+ return stack_.template Pop<Ch>(length_);
+ }
+
+ private:
+ StackStream(const StackStream&);
+ StackStream& operator=(const StackStream&);
+
+ internal::Stack<StackAllocator>& stack_;
+ SizeType length_;
+ };
+
+ // Parse string and generate String event. Different code paths for kParseInsituFlag.
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ RAPIDJSON_ASSERT(s.Peek() == '\"');
+ s.Take(); // Skip '\"'
+
+ bool success = false;
+ if (parseFlags & kParseInsituFlag) {
+ typename InputStream::Ch *head = s.PutBegin();
+ ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ size_t length = s.PutEnd(head) - 1;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
+ success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
+ }
+ else {
+ StackStream<typename TargetEncoding::Ch> stackStream(stack_);
+ ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
+ const typename TargetEncoding::Ch* const str = stackStream.Pop();
+ success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
+ }
+ if (RAPIDJSON_UNLIKELY(!success))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ }
+
+ // Parse string to an output is
+ // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
+ template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ static const char escape[256] = {
+ Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
+ Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
+ 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
+ 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+ };
+#undef Z16
+//!@endcond
+
+ for (;;) {
+ // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
+ if (!(parseFlags & kParseValidateEncodingFlag))
+ ScanCopyUnescapedString(is, os);
+
+ Ch c = is.Peek();
+ if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
+ size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
+ is.Take();
+ Ch e = is.Peek();
+ if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
+ is.Take();
+ os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
+ }
+ else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
+ is.Take();
+ unsigned codepoint = ParseHex4(is, escapeOffset);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
+ // Handle UTF-16 surrogate pair
+ if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
+ unsigned codepoint2 = ParseHex4(is, escapeOffset);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
+ codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+ }
+ TEncoding::Encode(os, codepoint);
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
+ }
+ else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
+ is.Take();
+ os.Put('\0'); // null-terminate the string
+ return;
+ }
+ else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+ if (c == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
+ }
+ else {
+ size_t offset = is.Tell();
+ if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
+ !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
+ !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
+ }
+ }
+ }
+
+ template<typename InputStream, typename OutputStream>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
+ // Do nothing for generic version
+ }
+
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+ // StringStream -> StackStream<char>
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
+ const char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ return;
+ }
+ else
+ os.Put(*p++);
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ SizeType length;
+ #ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+ #else
+ length = static_cast<SizeType>(__builtin_ffs(r) - 1);
+ #endif
+ char* q = reinterpret_cast<char*>(os.Push(length));
+ for (size_t i = 0; i < length; i++)
+ q[i] = p[i];
+
+ p += length;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
+ }
+
+ is.src_ = p;
+ }
+
+ // InsituStringStream -> InsituStringStream
+ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
+ RAPIDJSON_ASSERT(&is == &os);
+ (void)os;
+
+ if (is.src_ == is.dst_) {
+ SkipUnescapedString(is);
+ return;
+ }
+
+ char* p = is.src_;
+ char *q = is.dst_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ while (p != nextAligned)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = p;
+ is.dst_ = q;
+ return;
+ }
+ else
+ *q++ = *p++;
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16, q += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ size_t length;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+#else
+ length = static_cast<size_t>(__builtin_ffs(r) - 1);
+#endif
+ for (const char* pend = p + length; p != pend; )
+ *q++ = *p++;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
+ }
+
+ is.src_ = p;
+ is.dst_ = q;
+ }
+
+ // When read/write pointers are the same for insitu stream, just skip unescaped characters
+ static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
+ RAPIDJSON_ASSERT(is.src_ == is.dst_);
+ char* p = is.src_;
+
+ // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ for (; p != nextAligned; p++)
+ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
+ is.src_ = is.dst_ = p;
+ return;
+ }
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ size_t length;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ length = offset;
+#else
+ length = static_cast<size_t>(__builtin_ffs(r) - 1);
+#endif
+ p += length;
+ break;
+ }
+ }
+
+ is.src_ = is.dst_ = p;
+ }
+#endif
+
+ template<typename InputStream, bool backup, bool pushOnTake>
+ class NumberStream;
+
+ template<typename InputStream>
+ class NumberStream<InputStream, false, false> {
+ public:
+ typedef typename InputStream::Ch Ch;
+
+ NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
+ RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
+ RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
+ RAPIDJSON_FORCEINLINE void Push(char) {}
+
+ size_t Tell() { return is.Tell(); }
+ size_t Length() { return 0; }
+ const char* Pop() { return 0; }
+
+ protected:
+ NumberStream& operator=(const NumberStream&);
+
+ InputStream& is;
+ };
+
+ template<typename InputStream>
+ class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
+ typedef NumberStream<InputStream, false, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch TakePush() {
+ stackStream.Put(static_cast<char>(Base::is.Peek()));
+ return Base::is.Take();
+ }
+
+ RAPIDJSON_FORCEINLINE void Push(char c) {
+ stackStream.Put(c);
+ }
+
+ size_t Length() { return stackStream.Length(); }
+
+ const char* Pop() {
+ stackStream.Put('\0');
+ return stackStream.Pop();
+ }
+
+ private:
+ StackStream<char> stackStream;
+ };
+
+ template<typename InputStream>
+ class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
+ typedef NumberStream<InputStream, true, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
+ };
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNumber(InputStream& is, Handler& handler) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ NumberStream<InputStream,
+ ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
+ ((parseFlags & kParseInsituFlag) == 0) :
+ ((parseFlags & kParseFullPrecisionFlag) != 0),
+ (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
+ (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
+
+ size_t startOffset = s.Tell();
+ double d = 0.0;
+ bool useNanOrInf = false;
+
+ // Parse minus
+ bool minus = Consume(s, '-');
+
+ // Parse int: zero / ( digit1-9 *DIGIT )
+ unsigned i = 0;
+ uint64_t i64 = 0;
+ bool use64bit = false;
+ int significandDigit = 0;
+ if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
+ i = 0;
+ s.TakePush();
+ }
+ else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
+ i = static_cast<unsigned>(s.TakePush() - '0');
+
+ if (minus)
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
+ if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
+ if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+ // Parse NaN or Infinity here
+ else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
+ useNanOrInf = true;
+ if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
+ d = std::numeric_limits<double>::quiet_NaN();
+ }
+ else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
+ d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
+ if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
+ && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+
+ // Parse 64bit int
+ bool useDouble = false;
+ if (use64bit) {
+ if (minus)
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
+ if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
+ d = static_cast<double>(i64);
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
+ if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
+ d = static_cast<double>(i64);
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+
+ // Force double for big integer
+ if (useDouble) {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
+ d = d * 10 + (s.TakePush() - '0');
+ }
+ }
+
+ // Parse frac = decimal-point 1*DIGIT
+ int expFrac = 0;
+ size_t decimalPosition;
+ if (Consume(s, '.')) {
+ decimalPosition = s.Length();
+
+ if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
+
+ if (!useDouble) {
+#if RAPIDJSON_64BIT
+ // Use i64 to store significand in 64-bit architecture
+ if (!use64bit)
+ i64 = i;
+
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
+ break;
+ else {
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ --expFrac;
+ if (i64 != 0)
+ significandDigit++;
+ }
+ }
+
+ d = static_cast<double>(i64);
+#else
+ // Use double to store significand in 32-bit architecture
+ d = static_cast<double>(use64bit ? i64 : i);
+#endif
+ useDouble = true;
+ }
+
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ if (significandDigit < 17) {
+ d = d * 10.0 + (s.TakePush() - '0');
+ --expFrac;
+ if (RAPIDJSON_LIKELY(d > 0.0))
+ significandDigit++;
+ }
+ else
+ s.TakePush();
+ }
+ }
+ else
+ decimalPosition = s.Length(); // decimal position at the end of integer.
+
+ // Parse exp = e [ minus / plus ] 1*DIGIT
+ int exp = 0;
+ if (Consume(s, 'e') || Consume(s, 'E')) {
+ if (!useDouble) {
+ d = static_cast<double>(use64bit ? i64 : i);
+ useDouble = true;
+ }
+
+ bool expMinus = false;
+ if (Consume(s, '+'))
+ ;
+ else if (Consume(s, '-'))
+ expMinus = true;
+
+ if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = static_cast<int>(s.Take() - '0');
+ if (expMinus) {
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = exp * 10 + static_cast<int>(s.Take() - '0');
+ if (exp >= 214748364) { // Issue #313: prevent overflow exponent
+ while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
+ s.Take();
+ }
+ }
+ }
+ else { // positive exp
+ int maxExp = 308 - expFrac;
+ while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
+ exp = exp * 10 + static_cast<int>(s.Take() - '0');
+ if (RAPIDJSON_UNLIKELY(exp > maxExp))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
+ }
+ }
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
+
+ if (expMinus)
+ exp = -exp;
+ }
+
+ // Finish parsing, call event according to the type of number.
+ bool cont = true;
+
+ if (parseFlags & kParseNumbersAsStringsFlag) {
+ if (parseFlags & kParseInsituFlag) {
+ s.Pop(); // Pop stack no matter if it will be used or not.
+ typename InputStream::Ch* head = is.PutBegin();
+ const size_t length = s.Tell() - startOffset;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ // unable to insert the \0 character here, it will erase the comma after this number
+ const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
+ cont = handler.RawNumber(str, SizeType(length), false);
+ }
+ else {
+ SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
+ StringStream srcStream(s.Pop());
+ StackStream<typename TargetEncoding::Ch> dstStream(stack_);
+ while (numCharsToCopy--) {
+ Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
+ }
+ dstStream.Put('\0');
+ const typename TargetEncoding::Ch* str = dstStream.Pop();
+ const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
+ cont = handler.RawNumber(str, SizeType(length), true);
+ }
+ }
+ else {
+ size_t length = s.Length();
+ const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
+
+ if (useDouble) {
+ int p = exp + expFrac;
+ if (parseFlags & kParseFullPrecisionFlag)
+ d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
+ else
+ d = internal::StrtodNormalPrecision(d, p);
+
+ cont = handler.Double(minus ? -d : d);
+ }
+ else if (useNanOrInf) {
+ cont = handler.Double(d);
+ }
+ else {
+ if (use64bit) {
+ if (minus)
+ cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
+ else
+ cont = handler.Uint64(i64);
+ }
+ else {
+ if (minus)
+ cont = handler.Int(static_cast<int32_t>(~i + 1));
+ else
+ cont = handler.Uint(i);
+ }
+ }
+ }
+ if (RAPIDJSON_UNLIKELY(!cont))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
+ }
+
+ // Parse any JSON value
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseValue(InputStream& is, Handler& handler) {
+ switch (is.Peek()) {
+ case 'n': ParseNull <parseFlags>(is, handler); break;
+ case 't': ParseTrue <parseFlags>(is, handler); break;
+ case 'f': ParseFalse <parseFlags>(is, handler); break;
+ case '"': ParseString<parseFlags>(is, handler); break;
+ case '{': ParseObject<parseFlags>(is, handler); break;
+ case '[': ParseArray <parseFlags>(is, handler); break;
+ default :
+ ParseNumber<parseFlags>(is, handler);
+ break;
+
+ }
+ }
+
+ // Iterative Parsing
+
+ // States
+ enum IterativeParsingState {
+ IterativeParsingStartState = 0,
+ IterativeParsingFinishState,
+ IterativeParsingErrorState,
+
+ // Object states
+ IterativeParsingObjectInitialState,
+ IterativeParsingMemberKeyState,
+ IterativeParsingKeyValueDelimiterState,
+ IterativeParsingMemberValueState,
+ IterativeParsingMemberDelimiterState,
+ IterativeParsingObjectFinishState,
+
+ // Array states
+ IterativeParsingArrayInitialState,
+ IterativeParsingElementState,
+ IterativeParsingElementDelimiterState,
+ IterativeParsingArrayFinishState,
+
+ // Single value state
+ IterativeParsingValueState
+ };
+
+ enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
+
+ // Tokens
+ enum Token {
+ LeftBracketToken = 0,
+ RightBracketToken,
+
+ LeftCurlyBracketToken,
+ RightCurlyBracketToken,
+
+ CommaToken,
+ ColonToken,
+
+ StringToken,
+ FalseToken,
+ TrueToken,
+ NullToken,
+ NumberToken,
+
+ kTokenCount
+ };
+
+ RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define N NumberToken
+#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
+ // Maps from ASCII to Token
+ static const unsigned char tokenMap[256] = {
+ N16, // 00~0F
+ N16, // 10~1F
+ N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
+ N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
+ N16, // 40~4F
+ N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
+ N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
+ N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
+ N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
+ };
+#undef N
+#undef N16
+//!@endcond
+
+ if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
+ return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
+ else
+ return NumberToken;
+ }
+
+ RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
+ // current state x one lookahead token -> new state
+ static const char G[cIterativeParsingStateCount][kTokenCount] = {
+ // Start
+ {
+ IterativeParsingArrayInitialState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingValueState, // String
+ IterativeParsingValueState, // False
+ IterativeParsingValueState, // True
+ IterativeParsingValueState, // Null
+ IterativeParsingValueState // Number
+ },
+ // Finish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Error(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ObjectInitial
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberKey
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingKeyValueDelimiterState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // KeyValueDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberValueState, // String
+ IterativeParsingMemberValueState, // False
+ IterativeParsingMemberValueState, // True
+ IterativeParsingMemberValueState, // Null
+ IterativeParsingMemberValueState // Number
+ },
+ // MemberValue
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingMemberDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberDelimiter
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ObjectFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ArrayInitial
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // Element
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingElementDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ElementDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // ArrayFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Single Value (sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ }
+ }; // End of G
+
+ return static_cast<IterativeParsingState>(G[state][token]);
+ }
+
+ // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
+ // May return a new state on state pop.
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
+ (void)token;
+
+ switch (dst) {
+ case IterativeParsingErrorState:
+ return dst;
+
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingArrayInitialState:
+ {
+ // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
+ // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
+ IterativeParsingState n = src;
+ if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
+ n = IterativeParsingElementState;
+ else if (src == IterativeParsingKeyValueDelimiterState)
+ n = IterativeParsingMemberValueState;
+ // Push current state.
+ *stack_.template Push<SizeType>(1) = n;
+ // Initialize and push the member/element count.
+ *stack_.template Push<SizeType>(1) = 0;
+ // Call handler
+ bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return dst;
+ }
+ }
+
+ case IterativeParsingMemberKeyState:
+ ParseString<parseFlags>(is, handler, true);
+ if (HasParseError())
+ return IterativeParsingErrorState;
+ else
+ return dst;
+
+ case IterativeParsingKeyValueDelimiterState:
+ RAPIDJSON_ASSERT(token == ColonToken);
+ is.Take();
+ return dst;
+
+ case IterativeParsingMemberValueState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingElementState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingMemberDelimiterState:
+ case IterativeParsingElementDelimiterState:
+ is.Take();
+ // Update member/element count.
+ *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
+ return dst;
+
+ case IterativeParsingObjectFinishState:
+ {
+ // Transit from delimiter is only allowed when trailing commas are enabled
+ if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ // Get member count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the object is not empty, count the last member.
+ if (src == IterativeParsingMemberValueState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndObject(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ case IterativeParsingArrayFinishState:
+ {
+ // Transit from delimiter is only allowed when trailing commas are enabled
+ if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ // Get element count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the array is not empty, count the last element.
+ if (src == IterativeParsingElementState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndArray(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ default:
+ // This branch is for IterativeParsingValueState actually.
+ // Use `default:` rather than
+ // `case IterativeParsingValueState:` is for code coverage.
+
+ // The IterativeParsingStartState is not enumerated in this switch-case.
+ // It is impossible for that case. And it can be caught by following assertion.
+
+ // The IterativeParsingFinishState is not enumerated in this switch-case either.
+ // It is a "derivative" state which cannot triggered from Predict() directly.
+ // Therefore it cannot happen here. And it can be caught by following assertion.
+ RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
+
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return IterativeParsingFinishState;
+ }
+ }
+
+ template <typename InputStream>
+ void HandleError(IterativeParsingState src, InputStream& is) {
+ if (HasParseError()) {
+ // Error flag has been set.
+ return;
+ }
+
+ switch (src) {
+ case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
+ case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
+ case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
+ case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
+ case IterativeParsingKeyValueDelimiterState:
+ case IterativeParsingArrayInitialState:
+ case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
+ default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
+ }
+ }
+
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult IterativeParse(InputStream& is, Handler& handler) {
+ parseResult_.Clear();
+ ClearStackOnExit scope(*this);
+ IterativeParsingState state = IterativeParsingStartState;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ while (is.Peek() != '\0') {
+ Token t = Tokenize(is.Peek());
+ IterativeParsingState n = Predict(state, t);
+ IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
+
+ if (d == IterativeParsingErrorState) {
+ HandleError(state, is);
+ break;
+ }
+
+ state = d;
+
+ // Do not further consume streams if a root JSON has been parsed.
+ if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
+ break;
+
+ SkipWhitespaceAndComments<parseFlags>(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+
+ // Handle the end of file.
+ if (state != IterativeParsingFinishState)
+ HandleError(state, is);
+
+ return parseResult_;
+ }
+
+ static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
+ internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
+ ParseResult parseResult_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<>, UTF8<> > Reader;
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_READER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/schema.h b/ext/librethinkdbxx/src/rapidjson/schema.h
new file mode 100644
index 00000000..b182aa27
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/schema.h
@@ -0,0 +1,2006 @@
+// Tencent is pleased to support the open source community by making RapidJSON available->
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License-> You may obtain a copy of the License at
+//
+// http://opensource->org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied-> See the License for the
+// specific language governing permissions and limitations under the License->
+
+#ifndef RAPIDJSON_SCHEMA_H_
+#define RAPIDJSON_SCHEMA_H_
+
+#include "document.h"
+#include "pointer.h"
+#include <cmath> // abs, floor
+
+#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
+#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
+#else
+#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
+#endif
+
+#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
+#define RAPIDJSON_SCHEMA_USE_STDREGEX 1
+#else
+#define RAPIDJSON_SCHEMA_USE_STDREGEX 0
+#endif
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+#include "internal/regex.h"
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+#include <regex>
+#endif
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX
+#define RAPIDJSON_SCHEMA_HAS_REGEX 1
+#else
+#define RAPIDJSON_SCHEMA_HAS_REGEX 0
+#endif
+
+#ifndef RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_SCHEMA_VERBOSE 0
+#endif
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#include "stringbuffer.h"
+#endif
+
+RAPIDJSON_DIAG_PUSH
+
+#if defined(__GNUC__)
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_OFF(weak-vtables)
+RAPIDJSON_DIAG_OFF(exit-time-destructors)
+RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
+RAPIDJSON_DIAG_OFF(variadic-macros)
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Verbose Utilities
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+
+namespace internal {
+
+inline void PrintInvalidKeyword(const char* keyword) {
+ printf("Fail keyword: %s\n", keyword);
+}
+
+inline void PrintInvalidKeyword(const wchar_t* keyword) {
+ wprintf(L"Fail keyword: %ls\n", keyword);
+}
+
+inline void PrintInvalidDocument(const char* document) {
+ printf("Fail document: %s\n\n", document);
+}
+
+inline void PrintInvalidDocument(const wchar_t* document) {
+ wprintf(L"Fail document: %ls\n\n", document);
+}
+
+inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
+ printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
+}
+
+inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
+ wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
+}
+
+} // namespace internal
+
+#endif // RAPIDJSON_SCHEMA_VERBOSE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_INVALID_KEYWORD_RETURN
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
+#else
+#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
+#endif
+
+#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
+RAPIDJSON_MULTILINEMACRO_BEGIN\
+ context.invalidKeyword = keyword.GetString();\
+ RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
+ return false;\
+RAPIDJSON_MULTILINEMACRO_END
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+
+template <typename ValueType, typename Allocator>
+class GenericSchemaDocument;
+
+namespace internal {
+
+template <typename SchemaDocumentType>
+class Schema;
+
+///////////////////////////////////////////////////////////////////////////////
+// ISchemaValidator
+
+class ISchemaValidator {
+public:
+ virtual ~ISchemaValidator() {}
+ virtual bool IsValid() const = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ISchemaStateFactory
+
+template <typename SchemaType>
+class ISchemaStateFactory {
+public:
+ virtual ~ISchemaStateFactory() {}
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
+ virtual void* CreateHasher() = 0;
+ virtual uint64_t GetHashCode(void* hasher) = 0;
+ virtual void DestroryHasher(void* hasher) = 0;
+ virtual void* MallocState(size_t size) = 0;
+ virtual void FreeState(void* p) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Hasher
+
+// For comparison of compound value
+template<typename Encoding, typename Allocator>
+class Hasher {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
+
+ bool Null() { return WriteType(kNullType); }
+ bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
+ bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
+ bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
+ bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
+ bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
+ bool Double(double d) {
+ Number n;
+ if (d < 0) n.u.i = static_cast<int64_t>(d);
+ else n.u.u = static_cast<uint64_t>(d);
+ n.d = d;
+ return WriteNumber(n);
+ }
+
+ bool RawNumber(const Ch* str, SizeType len, bool) {
+ WriteBuffer(kNumberType, str, len * sizeof(Ch));
+ return true;
+ }
+
+ bool String(const Ch* str, SizeType len, bool) {
+ WriteBuffer(kStringType, str, len * sizeof(Ch));
+ return true;
+ }
+
+ bool StartObject() { return true; }
+ bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
+ bool EndObject(SizeType memberCount) {
+ uint64_t h = Hash(0, kObjectType);
+ uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
+ for (SizeType i = 0; i < memberCount; i++)
+ h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ bool StartArray() { return true; }
+ bool EndArray(SizeType elementCount) {
+ uint64_t h = Hash(0, kArrayType);
+ uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
+ for (SizeType i = 0; i < elementCount; i++)
+ h = Hash(h, e[i]); // Use hash to achieve element order sensitive
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
+
+ uint64_t GetHashCode() const {
+ RAPIDJSON_ASSERT(IsValid());
+ return *stack_.template Top<uint64_t>();
+ }
+
+private:
+ static const size_t kDefaultSize = 256;
+ struct Number {
+ union U {
+ uint64_t u;
+ int64_t i;
+ }u;
+ double d;
+ };
+
+ bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
+
+ bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
+
+ bool WriteBuffer(Type type, const void* data, size_t len) {
+ // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
+ uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
+ const unsigned char* d = static_cast<const unsigned char*>(data);
+ for (size_t i = 0; i < len; i++)
+ h = Hash(h, d[i]);
+ *stack_.template Push<uint64_t>() = h;
+ return true;
+ }
+
+ static uint64_t Hash(uint64_t h, uint64_t d) {
+ static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
+ h ^= d;
+ h *= kPrime;
+ return h;
+ }
+
+ Stack<Allocator> stack_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// SchemaValidationContext
+
+template <typename SchemaDocumentType>
+struct SchemaValidationContext {
+ typedef Schema<SchemaDocumentType> SchemaType;
+ typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
+ typedef typename SchemaType::ValueType ValueType;
+ typedef typename ValueType::Ch Ch;
+
+ enum PatternValidatorType {
+ kPatternValidatorOnly,
+ kPatternValidatorWithProperty,
+ kPatternValidatorWithAdditionalProperty
+ };
+
+ SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) :
+ factory(f),
+ schema(s),
+ valueSchema(),
+ invalidKeyword(),
+ hasher(),
+ arrayElementHashCodes(),
+ validators(),
+ validatorCount(),
+ patternPropertiesValidators(),
+ patternPropertiesValidatorCount(),
+ patternPropertiesSchemas(),
+ patternPropertiesSchemaCount(),
+ valuePatternValidatorType(kPatternValidatorOnly),
+ propertyExist(),
+ inArray(false),
+ valueUniqueness(false),
+ arrayUniqueness(false)
+ {
+ }
+
+ ~SchemaValidationContext() {
+ if (hasher)
+ factory.DestroryHasher(hasher);
+ if (validators) {
+ for (SizeType i = 0; i < validatorCount; i++)
+ factory.DestroySchemaValidator(validators[i]);
+ factory.FreeState(validators);
+ }
+ if (patternPropertiesValidators) {
+ for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
+ factory.DestroySchemaValidator(patternPropertiesValidators[i]);
+ factory.FreeState(patternPropertiesValidators);
+ }
+ if (patternPropertiesSchemas)
+ factory.FreeState(patternPropertiesSchemas);
+ if (propertyExist)
+ factory.FreeState(propertyExist);
+ }
+
+ SchemaValidatorFactoryType& factory;
+ const SchemaType* schema;
+ const SchemaType* valueSchema;
+ const Ch* invalidKeyword;
+ void* hasher; // Only validator access
+ void* arrayElementHashCodes; // Only validator access this
+ ISchemaValidator** validators;
+ SizeType validatorCount;
+ ISchemaValidator** patternPropertiesValidators;
+ SizeType patternPropertiesValidatorCount;
+ const SchemaType** patternPropertiesSchemas;
+ SizeType patternPropertiesSchemaCount;
+ PatternValidatorType valuePatternValidatorType;
+ PatternValidatorType objectPatternValidatorType;
+ SizeType arrayElementIndex;
+ bool* propertyExist;
+ bool inArray;
+ bool valueUniqueness;
+ bool arrayUniqueness;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Schema
+
+template <typename SchemaDocumentType>
+class Schema {
+public:
+ typedef typename SchemaDocumentType::ValueType ValueType;
+ typedef typename SchemaDocumentType::AllocatorType AllocatorType;
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+ typedef SchemaValidationContext<SchemaDocumentType> Context;
+ typedef Schema<SchemaDocumentType> SchemaType;
+ typedef GenericValue<EncodingType, AllocatorType> SValue;
+ friend class GenericSchemaDocument<ValueType, AllocatorType>;
+
+ Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
+ allocator_(allocator),
+ enum_(),
+ enumCount_(),
+ not_(),
+ type_((1 << kTotalSchemaType) - 1), // typeless
+ validatorCount_(),
+ properties_(),
+ additionalPropertiesSchema_(),
+ patternProperties_(),
+ patternPropertyCount_(),
+ propertyCount_(),
+ minProperties_(),
+ maxProperties_(SizeType(~0)),
+ additionalProperties_(true),
+ hasDependencies_(),
+ hasRequired_(),
+ hasSchemaDependencies_(),
+ additionalItemsSchema_(),
+ itemsList_(),
+ itemsTuple_(),
+ itemsTupleCount_(),
+ minItems_(),
+ maxItems_(SizeType(~0)),
+ additionalItems_(true),
+ uniqueItems_(false),
+ pattern_(),
+ minLength_(0),
+ maxLength_(~SizeType(0)),
+ exclusiveMinimum_(false),
+ exclusiveMaximum_(false)
+ {
+ typedef typename SchemaDocumentType::ValueType ValueType;
+ typedef typename ValueType::ConstValueIterator ConstValueIterator;
+ typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
+
+ if (!value.IsObject())
+ return;
+
+ if (const ValueType* v = GetMember(value, GetTypeString())) {
+ type_ = 0;
+ if (v->IsString())
+ AddType(*v);
+ else if (v->IsArray())
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
+ AddType(*itr);
+ }
+
+ if (const ValueType* v = GetMember(value, GetEnumString()))
+ if (v->IsArray() && v->Size() > 0) {
+ enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
+ typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
+ char buffer[256 + 24];
+ MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
+ EnumHasherType h(&hasherAllocator, 256);
+ itr->Accept(h);
+ enum_[enumCount_++] = h.GetHashCode();
+ }
+ }
+
+ if (schemaDocument) {
+ AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
+ AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
+ AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
+ }
+
+ if (const ValueType* v = GetMember(value, GetNotString())) {
+ schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
+ notValidatorIndex_ = validatorCount_;
+ validatorCount_++;
+ }
+
+ // Object
+
+ const ValueType* properties = GetMember(value, GetPropertiesString());
+ const ValueType* required = GetMember(value, GetRequiredString());
+ const ValueType* dependencies = GetMember(value, GetDependenciesString());
+ {
+ // Gather properties from properties/required/dependencies
+ SValue allProperties(kArrayType);
+
+ if (properties && properties->IsObject())
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
+ AddUniqueElement(allProperties, itr->name);
+
+ if (required && required->IsArray())
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
+ if (itr->IsString())
+ AddUniqueElement(allProperties, *itr);
+
+ if (dependencies && dependencies->IsObject())
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
+ AddUniqueElement(allProperties, itr->name);
+ if (itr->value.IsArray())
+ for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
+ if (i->IsString())
+ AddUniqueElement(allProperties, *i);
+ }
+
+ if (allProperties.Size() > 0) {
+ propertyCount_ = allProperties.Size();
+ properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
+ for (SizeType i = 0; i < propertyCount_; i++) {
+ new (&properties_[i]) Property();
+ properties_[i].name = allProperties[i];
+ properties_[i].schema = GetTypeless();
+ }
+ }
+ }
+
+ if (properties && properties->IsObject()) {
+ PointerType q = p.Append(GetPropertiesString(), allocator_);
+ for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
+ SizeType index;
+ if (FindPropertyIndex(itr->name, &index))
+ schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
+ }
+ }
+
+ if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
+ PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
+ patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
+ patternPropertyCount_ = 0;
+
+ for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
+ new (&patternProperties_[patternPropertyCount_]) PatternProperty();
+ patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
+ schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
+ patternPropertyCount_++;
+ }
+ }
+
+ if (required && required->IsArray())
+ for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
+ if (itr->IsString()) {
+ SizeType index;
+ if (FindPropertyIndex(*itr, &index)) {
+ properties_[index].required = true;
+ hasRequired_ = true;
+ }
+ }
+
+ if (dependencies && dependencies->IsObject()) {
+ PointerType q = p.Append(GetDependenciesString(), allocator_);
+ hasDependencies_ = true;
+ for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
+ SizeType sourceIndex;
+ if (FindPropertyIndex(itr->name, &sourceIndex)) {
+ if (itr->value.IsArray()) {
+ properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
+ std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
+ for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
+ SizeType targetIndex;
+ if (FindPropertyIndex(*targetItr, &targetIndex))
+ properties_[sourceIndex].dependencies[targetIndex] = true;
+ }
+ }
+ else if (itr->value.IsObject()) {
+ hasSchemaDependencies_ = true;
+ schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
+ properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
+ validatorCount_++;
+ }
+ }
+ }
+ }
+
+ if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
+ if (v->IsBool())
+ additionalProperties_ = v->GetBool();
+ else if (v->IsObject())
+ schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
+ }
+
+ AssignIfExist(minProperties_, value, GetMinPropertiesString());
+ AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
+
+ // Array
+ if (const ValueType* v = GetMember(value, GetItemsString())) {
+ PointerType q = p.Append(GetItemsString(), allocator_);
+ if (v->IsObject()) // List validation
+ schemaDocument->CreateSchema(&itemsList_, q, *v, document);
+ else if (v->IsArray()) { // Tuple validation
+ itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
+ SizeType index = 0;
+ for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
+ schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
+ }
+ }
+
+ AssignIfExist(minItems_, value, GetMinItemsString());
+ AssignIfExist(maxItems_, value, GetMaxItemsString());
+
+ if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
+ if (v->IsBool())
+ additionalItems_ = v->GetBool();
+ else if (v->IsObject())
+ schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
+ }
+
+ AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
+
+ // String
+ AssignIfExist(minLength_, value, GetMinLengthString());
+ AssignIfExist(maxLength_, value, GetMaxLengthString());
+
+ if (const ValueType* v = GetMember(value, GetPatternString()))
+ pattern_ = CreatePattern(*v);
+
+ // Number
+ if (const ValueType* v = GetMember(value, GetMinimumString()))
+ if (v->IsNumber())
+ minimum_.CopyFrom(*v, *allocator_);
+
+ if (const ValueType* v = GetMember(value, GetMaximumString()))
+ if (v->IsNumber())
+ maximum_.CopyFrom(*v, *allocator_);
+
+ AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
+ AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
+
+ if (const ValueType* v = GetMember(value, GetMultipleOfString()))
+ if (v->IsNumber() && v->GetDouble() > 0.0)
+ multipleOf_.CopyFrom(*v, *allocator_);
+ }
+
+ ~Schema() {
+ if (allocator_) {
+ allocator_->Free(enum_);
+ }
+ if (properties_) {
+ for (SizeType i = 0; i < propertyCount_; i++)
+ properties_[i].~Property();
+ AllocatorType::Free(properties_);
+ }
+ if (patternProperties_) {
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
+ patternProperties_[i].~PatternProperty();
+ AllocatorType::Free(patternProperties_);
+ }
+ AllocatorType::Free(itemsTuple_);
+#if RAPIDJSON_SCHEMA_HAS_REGEX
+ if (pattern_) {
+ pattern_->~RegexType();
+ allocator_->Free(pattern_);
+ }
+#endif
+ }
+
+ bool BeginValue(Context& context) const {
+ if (context.inArray) {
+ if (uniqueItems_)
+ context.valueUniqueness = true;
+
+ if (itemsList_)
+ context.valueSchema = itemsList_;
+ else if (itemsTuple_) {
+ if (context.arrayElementIndex < itemsTupleCount_)
+ context.valueSchema = itemsTuple_[context.arrayElementIndex];
+ else if (additionalItemsSchema_)
+ context.valueSchema = additionalItemsSchema_;
+ else if (additionalItems_)
+ context.valueSchema = GetTypeless();
+ else
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
+ }
+ else
+ context.valueSchema = GetTypeless();
+
+ context.arrayElementIndex++;
+ }
+ return true;
+ }
+
+ RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
+ if (context.patternPropertiesValidatorCount > 0) {
+ bool otherValid = false;
+ SizeType count = context.patternPropertiesValidatorCount;
+ if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
+ otherValid = context.patternPropertiesValidators[--count]->IsValid();
+
+ bool patternValid = true;
+ for (SizeType i = 0; i < count; i++)
+ if (!context.patternPropertiesValidators[i]->IsValid()) {
+ patternValid = false;
+ break;
+ }
+
+ if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
+ if (!patternValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+ else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
+ if (!patternValid || !otherValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+ else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
+ }
+
+ if (enum_) {
+ const uint64_t h = context.factory.GetHashCode(context.hasher);
+ for (SizeType i = 0; i < enumCount_; i++)
+ if (enum_[i] == h)
+ goto foundEnum;
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
+ foundEnum:;
+ }
+
+ if (allOf_.schemas)
+ for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
+ if (!context.validators[i]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
+
+ if (anyOf_.schemas) {
+ for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
+ if (context.validators[i]->IsValid())
+ goto foundAny;
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
+ foundAny:;
+ }
+
+ if (oneOf_.schemas) {
+ bool oneValid = false;
+ for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
+ if (context.validators[i]->IsValid()) {
+ if (oneValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
+ else
+ oneValid = true;
+ }
+ if (!oneValid)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
+ }
+
+ if (not_ && context.validators[notValidatorIndex_]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
+
+ return true;
+ }
+
+ bool Null(Context& context) const {
+ if (!(type_ & (1 << kNullSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+ return CreateParallelValidator(context);
+ }
+
+ bool Bool(Context& context, bool) const {
+ if (!(type_ & (1 << kBooleanSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+ return CreateParallelValidator(context);
+ }
+
+ bool Int(Context& context, int i) const {
+ if (!CheckInt(context, i))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Uint(Context& context, unsigned u) const {
+ if (!CheckUint(context, u))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Int64(Context& context, int64_t i) const {
+ if (!CheckInt(context, i))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Uint64(Context& context, uint64_t u) const {
+ if (!CheckUint(context, u))
+ return false;
+ return CreateParallelValidator(context);
+ }
+
+ bool Double(Context& context, double d) const {
+ if (!(type_ & (1 << kNumberSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
+ return false;
+
+ if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
+ return false;
+
+ if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
+ return false;
+
+ return CreateParallelValidator(context);
+ }
+
+ bool String(Context& context, const Ch* str, SizeType length, bool) const {
+ if (!(type_ & (1 << kStringSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
+ SizeType count;
+ if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
+ if (count < minLength_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
+ if (count > maxLength_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
+ }
+ }
+
+ if (pattern_ && !IsPatternMatch(pattern_, str, length))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
+
+ return CreateParallelValidator(context);
+ }
+
+ bool StartObject(Context& context) const {
+ if (!(type_ & (1 << kObjectSchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (hasDependencies_ || hasRequired_) {
+ context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
+ std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
+ }
+
+ if (patternProperties_) { // pre-allocate schema array
+ SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
+ context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
+ context.patternPropertiesSchemaCount = 0;
+ std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
+ }
+
+ return CreateParallelValidator(context);
+ }
+
+ bool Key(Context& context, const Ch* str, SizeType len, bool) const {
+ if (patternProperties_) {
+ context.patternPropertiesSchemaCount = 0;
+ for (SizeType i = 0; i < patternPropertyCount_; i++)
+ if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len))
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
+ }
+
+ SizeType index;
+ if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
+ if (context.patternPropertiesSchemaCount > 0) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
+ context.valueSchema = GetTypeless();
+ context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
+ }
+ else
+ context.valueSchema = properties_[index].schema;
+
+ if (context.propertyExist)
+ context.propertyExist[index] = true;
+
+ return true;
+ }
+
+ if (additionalPropertiesSchema_) {
+ if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
+ context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
+ context.valueSchema = GetTypeless();
+ context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
+ }
+ else
+ context.valueSchema = additionalPropertiesSchema_;
+ return true;
+ }
+ else if (additionalProperties_) {
+ context.valueSchema = GetTypeless();
+ return true;
+ }
+
+ if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
+
+ return true;
+ }
+
+ bool EndObject(Context& context, SizeType memberCount) const {
+ if (hasRequired_)
+ for (SizeType index = 0; index < propertyCount_; index++)
+ if (properties_[index].required)
+ if (!context.propertyExist[index])
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
+
+ if (memberCount < minProperties_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
+
+ if (memberCount > maxProperties_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
+
+ if (hasDependencies_) {
+ for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
+ if (context.propertyExist[sourceIndex]) {
+ if (properties_[sourceIndex].dependencies) {
+ for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
+ if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
+ }
+ else if (properties_[sourceIndex].dependenciesSchema)
+ if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
+ }
+ }
+
+ return true;
+ }
+
+ bool StartArray(Context& context) const {
+ if (!(type_ & (1 << kArraySchemaType)))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ context.arrayElementIndex = 0;
+ context.inArray = true;
+
+ return CreateParallelValidator(context);
+ }
+
+ bool EndArray(Context& context, SizeType elementCount) const {
+ context.inArray = false;
+
+ if (elementCount < minItems_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
+
+ if (elementCount > maxItems_)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
+
+ return true;
+ }
+
+ // Generate functions for string literal according to Ch
+#define RAPIDJSON_STRING_(name, ...) \
+ static const ValueType& Get##name##String() {\
+ static const Ch s[] = { __VA_ARGS__, '\0' };\
+ static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\
+ return v;\
+ }
+
+ RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
+ RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
+ RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
+ RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
+ RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
+ RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
+ RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
+ RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
+ RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
+ RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
+ RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
+ RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
+ RAPIDJSON_STRING_(Not, 'n', 'o', 't')
+ RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
+ RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
+ RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
+ RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
+ RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
+ RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
+ RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
+ RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
+ RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
+
+#undef RAPIDJSON_STRING_
+
+private:
+ enum SchemaValueType {
+ kNullSchemaType,
+ kBooleanSchemaType,
+ kObjectSchemaType,
+ kArraySchemaType,
+ kStringSchemaType,
+ kNumberSchemaType,
+ kIntegerSchemaType,
+ kTotalSchemaType
+ };
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+ typedef internal::GenericRegex<EncodingType> RegexType;
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+ typedef std::basic_regex<Ch> RegexType;
+#else
+ typedef char RegexType;
+#endif
+
+ struct SchemaArray {
+ SchemaArray() : schemas(), count() {}
+ ~SchemaArray() { AllocatorType::Free(schemas); }
+ const SchemaType** schemas;
+ SizeType begin; // begin index of context.validators
+ SizeType count;
+ };
+
+ static const SchemaType* GetTypeless() {
+ static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
+ return &typeless;
+ }
+
+ template <typename V1, typename V2>
+ void AddUniqueElement(V1& a, const V2& v) {
+ for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
+ if (*itr == v)
+ return;
+ V1 c(v, *allocator_);
+ a.PushBack(c, *allocator_);
+ }
+
+ static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
+ typename ValueType::ConstMemberIterator itr = value.FindMember(name);
+ return itr != value.MemberEnd() ? &(itr->value) : 0;
+ }
+
+ static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
+ if (const ValueType* v = GetMember(value, name))
+ if (v->IsBool())
+ out = v->GetBool();
+ }
+
+ static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
+ if (const ValueType* v = GetMember(value, name))
+ if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
+ out = static_cast<SizeType>(v->GetUint64());
+ }
+
+ void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
+ if (const ValueType* v = GetMember(value, name)) {
+ if (v->IsArray() && v->Size() > 0) {
+ PointerType q = p.Append(name, allocator_);
+ out.count = v->Size();
+ out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
+ memset(out.schemas, 0, sizeof(Schema*)* out.count);
+ for (SizeType i = 0; i < out.count; i++)
+ schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
+ out.begin = validatorCount_;
+ validatorCount_ += out.count;
+ }
+ }
+ }
+
+#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType& value) {
+ if (value.IsString()) {
+ RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString());
+ if (!r->IsValid()) {
+ r->~RegexType();
+ AllocatorType::Free(r);
+ r = 0;
+ }
+ return r;
+ }
+ return 0;
+ }
+
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
+ return pattern->Search(str);
+ }
+#elif RAPIDJSON_SCHEMA_USE_STDREGEX
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType& value) {
+ if (value.IsString())
+ try {
+ return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
+ }
+ catch (const std::regex_error&) {
+ }
+ return 0;
+ }
+
+ static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
+ std::match_results<const Ch*> r;
+ return std::regex_search(str, str + length, r, *pattern);
+ }
+#else
+ template <typename ValueType>
+ RegexType* CreatePattern(const ValueType&) { return 0; }
+
+ static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
+#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
+
+ void AddType(const ValueType& type) {
+ if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
+ else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
+ else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
+ else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
+ else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
+ else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
+ else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
+ }
+
+ bool CreateParallelValidator(Context& context) const {
+ if (enum_ || context.arrayUniqueness)
+ context.hasher = context.factory.CreateHasher();
+
+ if (validatorCount_) {
+ RAPIDJSON_ASSERT(context.validators == 0);
+ context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
+ context.validatorCount = validatorCount_;
+
+ if (allOf_.schemas)
+ CreateSchemaValidators(context, allOf_);
+
+ if (anyOf_.schemas)
+ CreateSchemaValidators(context, anyOf_);
+
+ if (oneOf_.schemas)
+ CreateSchemaValidators(context, oneOf_);
+
+ if (not_)
+ context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
+
+ if (hasSchemaDependencies_) {
+ for (SizeType i = 0; i < propertyCount_; i++)
+ if (properties_[i].dependenciesSchema)
+ context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
+ }
+ }
+
+ return true;
+ }
+
+ void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
+ for (SizeType i = 0; i < schemas.count; i++)
+ context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
+ }
+
+ // O(n)
+ bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
+ SizeType len = name.GetStringLength();
+ const Ch* str = name.GetString();
+ for (SizeType index = 0; index < propertyCount_; index++)
+ if (properties_[index].name.GetStringLength() == len &&
+ (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
+ {
+ *outIndex = index;
+ return true;
+ }
+ return false;
+ }
+
+ bool CheckInt(Context& context, int64_t i) const {
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull()) {
+ if (minimum_.IsInt64()) {
+ if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ }
+ else if (minimum_.IsUint64()) {
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
+ }
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!maximum_.IsNull()) {
+ if (maximum_.IsInt64()) {
+ if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ }
+ else if (maximum_.IsUint64())
+ /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64()
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!multipleOf_.IsNull()) {
+ if (multipleOf_.IsUint64()) {
+ if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ }
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckUint(Context& context, uint64_t i) const {
+ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
+
+ if (!minimum_.IsNull()) {
+ if (minimum_.IsUint64()) {
+ if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ }
+ else if (minimum_.IsInt64())
+ /* do nothing */; // i >= 0 > minimum.Getint64()
+ else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!maximum_.IsNull()) {
+ if (maximum_.IsUint64()) {
+ if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ }
+ else if (maximum_.IsInt64())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
+ else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
+ return false;
+ }
+
+ if (!multipleOf_.IsNull()) {
+ if (multipleOf_.IsUint64()) {
+ if (i % multipleOf_.GetUint64() != 0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ }
+ else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckDoubleMinimum(Context& context, double d) const {
+ if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
+ return true;
+ }
+
+ bool CheckDoubleMaximum(Context& context, double d) const {
+ if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
+ return true;
+ }
+
+ bool CheckDoubleMultipleOf(Context& context, double d) const {
+ double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
+ double q = std::floor(a / b);
+ double r = a - q * b;
+ if (r > 0.0)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
+ return true;
+ }
+
+ struct Property {
+ Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
+ ~Property() { AllocatorType::Free(dependencies); }
+ SValue name;
+ const SchemaType* schema;
+ const SchemaType* dependenciesSchema;
+ SizeType dependenciesValidatorIndex;
+ bool* dependencies;
+ bool required;
+ };
+
+ struct PatternProperty {
+ PatternProperty() : schema(), pattern() {}
+ ~PatternProperty() {
+ if (pattern) {
+ pattern->~RegexType();
+ AllocatorType::Free(pattern);
+ }
+ }
+ const SchemaType* schema;
+ RegexType* pattern;
+ };
+
+ AllocatorType* allocator_;
+ uint64_t* enum_;
+ SizeType enumCount_;
+ SchemaArray allOf_;
+ SchemaArray anyOf_;
+ SchemaArray oneOf_;
+ const SchemaType* not_;
+ unsigned type_; // bitmask of kSchemaType
+ SizeType validatorCount_;
+ SizeType notValidatorIndex_;
+
+ Property* properties_;
+ const SchemaType* additionalPropertiesSchema_;
+ PatternProperty* patternProperties_;
+ SizeType patternPropertyCount_;
+ SizeType propertyCount_;
+ SizeType minProperties_;
+ SizeType maxProperties_;
+ bool additionalProperties_;
+ bool hasDependencies_;
+ bool hasRequired_;
+ bool hasSchemaDependencies_;
+
+ const SchemaType* additionalItemsSchema_;
+ const SchemaType* itemsList_;
+ const SchemaType** itemsTuple_;
+ SizeType itemsTupleCount_;
+ SizeType minItems_;
+ SizeType maxItems_;
+ bool additionalItems_;
+ bool uniqueItems_;
+
+ RegexType* pattern_;
+ SizeType minLength_;
+ SizeType maxLength_;
+
+ SValue minimum_;
+ SValue maximum_;
+ SValue multipleOf_;
+ bool exclusiveMinimum_;
+ bool exclusiveMaximum_;
+};
+
+template<typename Stack, typename Ch>
+struct TokenHelper {
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
+ *documentStack.template Push<Ch>() = '/';
+ char buffer[21];
+ size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
+ for (size_t i = 0; i < length; i++)
+ *documentStack.template Push<Ch>() = buffer[i];
+ }
+};
+
+// Partial specialized version for char to prevent buffer copying.
+template <typename Stack>
+struct TokenHelper<Stack, char> {
+ RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
+ if (sizeof(SizeType) == 4) {
+ char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
+ *buffer++ = '/';
+ const char* end = internal::u32toa(index, buffer);
+ documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
+ }
+ else {
+ char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
+ *buffer++ = '/';
+ const char* end = internal::u64toa(index, buffer);
+ documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
+ }
+ }
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// IGenericRemoteSchemaDocumentProvider
+
+template <typename SchemaDocumentType>
+class IGenericRemoteSchemaDocumentProvider {
+public:
+ typedef typename SchemaDocumentType::Ch Ch;
+
+ virtual ~IGenericRemoteSchemaDocumentProvider() {}
+ virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericSchemaDocument
+
+//! JSON schema document.
+/*!
+ A JSON schema document is a compiled version of a JSON schema.
+ It is basically a tree of internal::Schema.
+
+ \note This is an immutable class (i.e. its instance cannot be modified after construction).
+ \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding.
+ \tparam Allocator Allocator type for allocating memory of this document.
+*/
+template <typename ValueT, typename Allocator = CrtAllocator>
+class GenericSchemaDocument {
+public:
+ typedef ValueT ValueType;
+ typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
+ typedef Allocator AllocatorType;
+ typedef typename ValueType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+ typedef internal::Schema<GenericSchemaDocument> SchemaType;
+ typedef GenericPointer<ValueType, Allocator> PointerType;
+ friend class internal::Schema<GenericSchemaDocument>;
+ template <typename, typename, typename>
+ friend class GenericSchemaValidator;
+
+ //! Constructor.
+ /*!
+ Compile a JSON document into schema document.
+
+ \param document A JSON document as source.
+ \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
+ \param allocator An optional allocator instance for allocating memory. Can be null.
+ */
+ explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
+ remoteProvider_(remoteProvider),
+ allocator_(allocator),
+ ownAllocator_(),
+ root_(),
+ schemaMap_(allocator, kInitialSchemaMapSize),
+ schemaRef_(allocator, kInitialSchemaRefSize)
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+
+ // Generate root schema, it will call CreateSchema() to create sub-schemas,
+ // And call AddRefSchema() if there are $ref.
+ CreateSchemaRecursive(&root_, PointerType(), document, document);
+
+ // Resolve $ref
+ while (!schemaRef_.Empty()) {
+ SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
+ if (const SchemaType* s = GetSchema(refEntry->target)) {
+ if (refEntry->schema)
+ *refEntry->schema = s;
+
+ // Create entry in map if not exist
+ if (!GetSchema(refEntry->source)) {
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
+ }
+ }
+ refEntry->~SchemaRefEntry();
+ }
+
+ RAPIDJSON_ASSERT(root_ != 0);
+
+ schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
+ remoteProvider_(rhs.remoteProvider_),
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ root_(rhs.root_),
+ schemaMap_(std::move(rhs.schemaMap_)),
+ schemaRef_(std::move(rhs.schemaRef_))
+ {
+ rhs.remoteProvider_ = 0;
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ }
+#endif
+
+ //! Destructor
+ ~GenericSchemaDocument() {
+ while (!schemaMap_.Empty())
+ schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
+
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ //! Get the root schema.
+ const SchemaType& GetRoot() const { return *root_; }
+
+private:
+ //! Prohibit copying
+ GenericSchemaDocument(const GenericSchemaDocument&);
+ //! Prohibit assignment
+ GenericSchemaDocument& operator=(const GenericSchemaDocument&);
+
+ struct SchemaRefEntry {
+ SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
+ PointerType source;
+ PointerType target;
+ const SchemaType** schema;
+ };
+
+ struct SchemaEntry {
+ SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
+ ~SchemaEntry() {
+ if (owned) {
+ schema->~SchemaType();
+ Allocator::Free(schema);
+ }
+ }
+ PointerType pointer;
+ SchemaType* schema;
+ bool owned;
+ };
+
+ void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
+ if (schema)
+ *schema = SchemaType::GetTypeless();
+
+ if (v.GetType() == kObjectType) {
+ const SchemaType* s = GetSchema(pointer);
+ if (!s)
+ CreateSchema(schema, pointer, v, document);
+
+ for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
+ CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
+ }
+ else if (v.GetType() == kArrayType)
+ for (SizeType i = 0; i < v.Size(); i++)
+ CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
+ }
+
+ void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
+ RAPIDJSON_ASSERT(pointer.IsValid());
+ if (v.IsObject()) {
+ if (!HandleRefSchema(pointer, schema, v, document)) {
+ SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
+ new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
+ if (schema)
+ *schema = s;
+ }
+ }
+ }
+
+ bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
+ static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
+ static const ValueType kRefValue(kRefString, 4);
+
+ typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
+ if (itr == v.MemberEnd())
+ return false;
+
+ if (itr->value.IsString()) {
+ SizeType len = itr->value.GetStringLength();
+ if (len > 0) {
+ const Ch* s = itr->value.GetString();
+ SizeType i = 0;
+ while (i < len && s[i] != '#') // Find the first #
+ i++;
+
+ if (i > 0) { // Remote reference, resolve immediately
+ if (remoteProvider_) {
+ if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
+ PointerType pointer(&s[i], len - i, allocator_);
+ if (pointer.IsValid()) {
+ if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
+ if (schema)
+ *schema = sc;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ else if (s[i] == '#') { // Local reference, defer resolution
+ PointerType pointer(&s[i], len - i, allocator_);
+ if (pointer.IsValid()) {
+ if (const ValueType* nv = pointer.Get(document))
+ if (HandleRefSchema(source, schema, *nv, document))
+ return true;
+
+ new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ const SchemaType* GetSchema(const PointerType& pointer) const {
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
+ if (pointer == target->pointer)
+ return target->schema;
+ return 0;
+ }
+
+ PointerType GetPointer(const SchemaType* schema) const {
+ for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
+ if (schema == target->schema)
+ return target->pointer;
+ return PointerType();
+ }
+
+ static const size_t kInitialSchemaMapSize = 64;
+ static const size_t kInitialSchemaRefSize = 64;
+
+ IRemoteSchemaDocumentProviderType* remoteProvider_;
+ Allocator *allocator_;
+ Allocator *ownAllocator_;
+ const SchemaType* root_; //!< Root schema.
+ internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
+ internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
+};
+
+//! GenericSchemaDocument using Value type.
+typedef GenericSchemaDocument<Value> SchemaDocument;
+//! IGenericRemoteSchemaDocumentProvider using SchemaDocument.
+typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericSchemaValidator
+
+//! JSON Schema Validator.
+/*!
+ A SAX style JSON schema validator.
+ It uses a \c GenericSchemaDocument to validate SAX events.
+ It delegates the incoming SAX events to an output handler.
+ The default output handler does nothing.
+ It can be reused multiple times by calling \c Reset().
+
+ \tparam SchemaDocumentType Type of schema document.
+ \tparam OutputHandler Type of output handler. Default handler does nothing.
+ \tparam StateAllocator Allocator for storing the internal validation states.
+*/
+template <
+ typename SchemaDocumentType,
+ typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
+ typename StateAllocator = CrtAllocator>
+class GenericSchemaValidator :
+ public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
+ public internal::ISchemaValidator
+{
+public:
+ typedef typename SchemaDocumentType::SchemaType SchemaType;
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename SchemaType::EncodingType EncodingType;
+ typedef typename EncodingType::Ch Ch;
+
+ //! Constructor without output handler.
+ /*!
+ \param schemaDocument The schema document to conform to.
+ \param allocator Optional allocator for storing internal validation states.
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
+ \param documentStackCapacity Optional initial capacity of document path stack.
+ */
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(schemaDocument.GetRoot()),
+ outputHandler_(GetNullHandler()),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(0)
+#endif
+ {
+ }
+
+ //! Constructor with output handler.
+ /*!
+ \param schemaDocument The schema document to conform to.
+ \param allocator Optional allocator for storing internal validation states.
+ \param schemaStackCapacity Optional initial capacity of schema path stack.
+ \param documentStackCapacity Optional initial capacity of document path stack.
+ */
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ OutputHandler& outputHandler,
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(schemaDocument.GetRoot()),
+ outputHandler_(outputHandler),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(0)
+#endif
+ {
+ }
+
+ //! Destructor.
+ ~GenericSchemaValidator() {
+ Reset();
+ RAPIDJSON_DELETE(ownStateAllocator_);
+ }
+
+ //! Reset the internal states.
+ void Reset() {
+ while (!schemaStack_.Empty())
+ PopSchema();
+ documentStack_.Clear();
+ valid_ = true;
+ }
+
+ //! Checks whether the current state is valid.
+ // Implementation of ISchemaValidator
+ virtual bool IsValid() const { return valid_; }
+
+ //! Gets the JSON pointer pointed to the invalid schema.
+ PointerType GetInvalidSchemaPointer() const {
+ return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
+ }
+
+ //! Gets the keyword of invalid schema.
+ const Ch* GetInvalidSchemaKeyword() const {
+ return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
+ }
+
+ //! Gets the JSON pointer pointed to the invalid value.
+ PointerType GetInvalidDocumentPointer() const {
+ return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
+ }
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
+RAPIDJSON_MULTILINEMACRO_BEGIN\
+ *documentStack_.template Push<Ch>() = '\0';\
+ documentStack_.template Pop<Ch>(1);\
+ internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
+RAPIDJSON_MULTILINEMACRO_END
+#else
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
+#endif
+
+#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
+ if (!valid_) return false; \
+ if (!BeginValue() || !CurrentSchema().method arg1) {\
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
+ return valid_ = false;\
+ }
+
+#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
+ for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
+ if (context->hasher)\
+ static_cast<HasherType*>(context->hasher)->method arg2;\
+ if (context->validators)\
+ for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
+ static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
+ if (context->patternPropertiesValidators)\
+ for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
+ static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
+ }
+
+#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
+ return valid_ = EndValue() && outputHandler_.method arg2
+
+#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
+ RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
+
+ bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); }
+ bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
+ bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
+ bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
+ bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
+ bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
+ bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
+ bool RawNumber(const Ch* str, SizeType length, bool copy)
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
+ bool String(const Ch* str, SizeType length, bool copy)
+ { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
+
+ bool StartObject() {
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
+ return valid_ = outputHandler_.StartObject();
+ }
+
+ bool Key(const Ch* str, SizeType len, bool copy) {
+ if (!valid_) return false;
+ AppendToken(str, len);
+ if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
+ return valid_ = outputHandler_.Key(str, len, copy);
+ }
+
+ bool EndObject(SizeType memberCount) {
+ if (!valid_) return false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
+ if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
+ }
+
+ bool StartArray() {
+ RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
+ return valid_ = outputHandler_.StartArray();
+ }
+
+ bool EndArray(SizeType elementCount) {
+ if (!valid_) return false;
+ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
+ if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
+ RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
+ }
+
+#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
+#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
+#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
+#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
+
+ // Implementation of ISchemaStateFactory<SchemaType>
+ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
+ return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root,
+#if RAPIDJSON_SCHEMA_VERBOSE
+ depth_ + 1,
+#endif
+ &GetStateAllocator());
+ }
+
+ virtual void DestroySchemaValidator(ISchemaValidator* validator) {
+ GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
+ v->~GenericSchemaValidator();
+ StateAllocator::Free(v);
+ }
+
+ virtual void* CreateHasher() {
+ return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
+ }
+
+ virtual uint64_t GetHashCode(void* hasher) {
+ return static_cast<HasherType*>(hasher)->GetHashCode();
+ }
+
+ virtual void DestroryHasher(void* hasher) {
+ HasherType* h = static_cast<HasherType*>(hasher);
+ h->~HasherType();
+ StateAllocator::Free(h);
+ }
+
+ virtual void* MallocState(size_t size) {
+ return GetStateAllocator().Malloc(size);
+ }
+
+ virtual void FreeState(void* p) {
+ return StateAllocator::Free(p);
+ }
+
+private:
+ typedef typename SchemaType::Context Context;
+ typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
+ typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
+
+ GenericSchemaValidator(
+ const SchemaDocumentType& schemaDocument,
+ const SchemaType& root,
+#if RAPIDJSON_SCHEMA_VERBOSE
+ unsigned depth,
+#endif
+ StateAllocator* allocator = 0,
+ size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
+ size_t documentStackCapacity = kDefaultDocumentStackCapacity)
+ :
+ schemaDocument_(&schemaDocument),
+ root_(root),
+ outputHandler_(GetNullHandler()),
+ stateAllocator_(allocator),
+ ownStateAllocator_(0),
+ schemaStack_(allocator, schemaStackCapacity),
+ documentStack_(allocator, documentStackCapacity),
+ valid_(true)
+#if RAPIDJSON_SCHEMA_VERBOSE
+ , depth_(depth)
+#endif
+ {
+ }
+
+ StateAllocator& GetStateAllocator() {
+ if (!stateAllocator_)
+ stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator());
+ return *stateAllocator_;
+ }
+
+ bool BeginValue() {
+ if (schemaStack_.Empty())
+ PushSchema(root_);
+ else {
+ if (CurrentContext().inArray)
+ internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
+
+ if (!CurrentSchema().BeginValue(CurrentContext()))
+ return false;
+
+ SizeType count = CurrentContext().patternPropertiesSchemaCount;
+ const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
+ typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
+ bool valueUniqueness = CurrentContext().valueUniqueness;
+ if (CurrentContext().valueSchema)
+ PushSchema(*CurrentContext().valueSchema);
+
+ if (count > 0) {
+ CurrentContext().objectPatternValidatorType = patternValidatorType;
+ ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
+ SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
+ va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
+ for (SizeType i = 0; i < count; i++)
+ va[validatorCount++] = CreateSchemaValidator(*sa[i]);
+ }
+
+ CurrentContext().arrayUniqueness = valueUniqueness;
+ }
+ return true;
+ }
+
+ bool EndValue() {
+ if (!CurrentSchema().EndValue(CurrentContext()))
+ return false;
+
+#if RAPIDJSON_SCHEMA_VERBOSE
+ GenericStringBuffer<EncodingType> sb;
+ schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
+
+ *documentStack_.template Push<Ch>() = '\0';
+ documentStack_.template Pop<Ch>(1);
+ internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
+#endif
+
+ uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
+
+ PopSchema();
+
+ if (!schemaStack_.Empty()) {
+ Context& context = CurrentContext();
+ if (context.valueUniqueness) {
+ HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
+ if (!a)
+ CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
+ for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
+ if (itr->GetUint64() == h)
+ RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
+ a->PushBack(h, GetStateAllocator());
+ }
+ }
+
+ // Remove the last token of document pointer
+ while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
+ ;
+
+ return true;
+ }
+
+ void AppendToken(const Ch* str, SizeType len) {
+ documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
+ *documentStack_.template PushUnsafe<Ch>() = '/';
+ for (SizeType i = 0; i < len; i++) {
+ if (str[i] == '~') {
+ *documentStack_.template PushUnsafe<Ch>() = '~';
+ *documentStack_.template PushUnsafe<Ch>() = '0';
+ }
+ else if (str[i] == '/') {
+ *documentStack_.template PushUnsafe<Ch>() = '~';
+ *documentStack_.template PushUnsafe<Ch>() = '1';
+ }
+ else
+ *documentStack_.template PushUnsafe<Ch>() = str[i];
+ }
+ }
+
+ RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); }
+
+ RAPIDJSON_FORCEINLINE void PopSchema() {
+ Context* c = schemaStack_.template Pop<Context>(1);
+ if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
+ a->~HashCodeArray();
+ StateAllocator::Free(a);
+ }
+ c->~Context();
+ }
+
+ const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
+ Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
+ const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
+
+ static OutputHandler& GetNullHandler() {
+ static OutputHandler nullHandler;
+ return nullHandler;
+ }
+
+ static const size_t kDefaultSchemaStackCapacity = 1024;
+ static const size_t kDefaultDocumentStackCapacity = 256;
+ const SchemaDocumentType* schemaDocument_;
+ const SchemaType& root_;
+ OutputHandler& outputHandler_;
+ StateAllocator* stateAllocator_;
+ StateAllocator* ownStateAllocator_;
+ internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
+ internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
+ bool valid_;
+#if RAPIDJSON_SCHEMA_VERBOSE
+ unsigned depth_;
+#endif
+};
+
+typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
+
+///////////////////////////////////////////////////////////////////////////////
+// SchemaValidatingReader
+
+//! A helper class for parsing with validation.
+/*!
+ This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate().
+
+ \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam SchemaDocumentType Type of schema document.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <
+ unsigned parseFlags,
+ typename InputStream,
+ typename SourceEncoding,
+ typename SchemaDocumentType = SchemaDocument,
+ typename StackAllocator = CrtAllocator>
+class SchemaValidatingReader {
+public:
+ typedef typename SchemaDocumentType::PointerType PointerType;
+ typedef typename InputStream::Ch Ch;
+
+ //! Constructor
+ /*!
+ \param is Input stream.
+ \param sd Schema document.
+ */
+ SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {}
+
+ template <typename Handler>
+ bool operator()(Handler& handler) {
+ GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
+ GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
+ parseResult_ = reader.template Parse<parseFlags>(is_, validator);
+
+ isValid_ = validator.IsValid();
+ if (isValid_) {
+ invalidSchemaPointer_ = PointerType();
+ invalidSchemaKeyword_ = 0;
+ invalidDocumentPointer_ = PointerType();
+ }
+ else {
+ invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
+ invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
+ invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
+ }
+
+ return parseResult_;
+ }
+
+ const ParseResult& GetParseResult() const { return parseResult_; }
+ bool IsValid() const { return isValid_; }
+ const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
+ const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
+ const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
+
+private:
+ InputStream& is_;
+ const SchemaDocumentType& sd_;
+
+ ParseResult parseResult_;
+ PointerType invalidSchemaPointer_;
+ const Ch* invalidSchemaKeyword_;
+ PointerType invalidDocumentPointer_;
+ bool isValid_;
+};
+
+RAPIDJSON_NAMESPACE_END
+RAPIDJSON_DIAG_POP
+
+#endif // RAPIDJSON_SCHEMA_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/stream.h b/ext/librethinkdbxx/src/rapidjson/stream.h
new file mode 100644
index 00000000..fef82c25
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/stream.h
@@ -0,0 +1,179 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#include "rapidjson.h"
+
+#ifndef RAPIDJSON_STREAM_H_
+#define RAPIDJSON_STREAM_H_
+
+#include "encodings.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Stream
+
+/*! \class rapidjson::Stream
+ \brief Concept for reading and writing characters.
+
+ For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
+
+ For write-only stream, only need to implement Put() and Flush().
+
+\code
+concept Stream {
+ typename Ch; //!< Character type of the stream.
+
+ //! Read the current character from stream without moving the read cursor.
+ Ch Peek() const;
+
+ //! Read the current character from stream and moving the read cursor to next character.
+ Ch Take();
+
+ //! Get the current read cursor.
+ //! \return Number of characters read from start.
+ size_t Tell();
+
+ //! Begin writing operation at the current read pointer.
+ //! \return The begin writer pointer.
+ Ch* PutBegin();
+
+ //! Write a character.
+ void Put(Ch c);
+
+ //! Flush the buffer.
+ void Flush();
+
+ //! End the writing operation.
+ //! \param begin The begin write pointer returned by PutBegin().
+ //! \return Number of characters written.
+ size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Provides additional information for stream.
+/*!
+ By using traits pattern, this type provides a default configuration for stream.
+ For custom stream, this type can be specialized for other configuration.
+ See TEST(Reader, CustomStringStream) in readertest.cpp for example.
+*/
+template<typename Stream>
+struct StreamTraits {
+ //! Whether to make local copy of stream for optimization during parsing.
+ /*!
+ By default, for safety, streams do not use local copy optimization.
+ Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
+ */
+ enum { copyOptimization = 0 };
+};
+
+//! Reserve n characters for writing to a stream.
+template<typename Stream>
+inline void PutReserve(Stream& stream, size_t count) {
+ (void)stream;
+ (void)count;
+}
+
+//! Write character to a stream, presuming buffer is reserved.
+template<typename Stream>
+inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
+ stream.Put(c);
+}
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+ PutReserve(stream, n);
+ for (size_t i = 0; i < n; i++)
+ PutUnsafe(stream, c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+ Ch Peek() const { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ void Flush() { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! String stream with UTF8 encoding.
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+ \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+ // Read
+ Ch Peek() { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() { return static_cast<size_t>(src_ - head_); }
+
+ // Write
+ void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
+
+ Ch* PutBegin() { return dst_ = src_; }
+ size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
+ void Flush() {}
+
+ Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
+ void Pop(size_t count) { dst_ -= count; }
+
+ Ch* src_;
+ Ch* dst_;
+ Ch* head_;
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericInsituStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! Insitu string stream with UTF8 encoding.
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STREAM_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/stringbuffer.h b/ext/librethinkdbxx/src/rapidjson/stringbuffer.h
new file mode 100644
index 00000000..78f34d20
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/stringbuffer.h
@@ -0,0 +1,117 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "stream.h"
+#include "internal/stack.h"
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+#include "internal/stack.h"
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output stream.
+/*!
+ \tparam Encoding Encoding of the stream.
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericStringBuffer {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
+ GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
+ if (&rhs != this)
+ stack_ = std::move(rhs.stack_);
+ return *this;
+ }
+#endif
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.ShrinkToFit();
+ stack_.template Pop<Ch>(1);
+ }
+
+ void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetString() const {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.template Pop<Ch>(1);
+
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericStringBuffer(const GenericStringBuffer&);
+ GenericStringBuffer& operator=(const GenericStringBuffer&);
+};
+
+//! String buffer with UTF8 encoding
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+template<typename Encoding, typename Allocator>
+inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
+ stream.Reserve(count);
+}
+
+template<typename Encoding, typename Allocator>
+inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
+ stream.PutUnsafe(c);
+}
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+ std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
diff --git a/ext/librethinkdbxx/src/rapidjson/writer.h b/ext/librethinkdbxx/src/rapidjson/writer.h
new file mode 100644
index 00000000..7d0610eb
--- /dev/null
+++ b/ext/librethinkdbxx/src/rapidjson/writer.h
@@ -0,0 +1,609 @@
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "stream.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include "internal/dtoa.h"
+#include "internal/itoa.h"
+#include "stringbuffer.h"
+#include <new> // placement new
+
+#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
+#include <intrin.h>
+#pragma intrinsic(_BitScanForward)
+#endif
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(padded)
+RAPIDJSON_DIAG_OFF(unreachable-code)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// WriteFlag
+
+/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kWriteDefaultFlags definition.
+
+ User can define this as any \c WriteFlag combinations.
+*/
+#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
+#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
+#endif
+
+//! Combination of writeFlags
+enum WriteFlag {
+ kWriteNoFlags = 0, //!< No flags are set.
+ kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
+ kWriteNanAndInfFlag = 2, //!< Allow writing of Inf, -Inf and NaN.
+ kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
+};
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+ It generates JSON text by events to an output os.
+
+ User may programmatically calls the functions of a writer to generate JSON text.
+
+ On the other side, a writer can also be passed to objects that generates events,
+
+ for example Reader::Parse() and Document::Accept().
+
+ \tparam OutputStream Type of output stream.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+ \note implements Handler concept
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
+class Writer {
+public:
+ typedef typename SourceEncoding::Ch Ch;
+
+ static const int kDefaultMaxDecimalPlaces = 324;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param stackAllocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ explicit
+ Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
+
+ explicit
+ Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
+
+ //! Reset the writer with a new stream.
+ /*!
+ This function reset the writer with a new stream and default settings,
+ in order to make a Writer object reusable for output multiple JSONs.
+
+ \param os New output stream.
+ \code
+ Writer<OutputStream> writer(os1);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+
+ writer.Reset(os2);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+ \endcode
+ */
+ void Reset(OutputStream& os) {
+ os_ = &os;
+ hasRoot_ = false;
+ level_stack_.Clear();
+ }
+
+ //! Checks whether the output is a complete JSON.
+ /*!
+ A complete JSON has a complete root object or array.
+ */
+ bool IsComplete() const {
+ return hasRoot_ && level_stack_.Empty();
+ }
+
+ int GetMaxDecimalPlaces() const {
+ return maxDecimalPlaces_;
+ }
+
+ //! Sets the maximum number of decimal places for double output.
+ /*!
+ This setting truncates the output with specified number of decimal places.
+
+ For example,
+
+ \code
+ writer.SetMaxDecimalPlaces(3);
+ writer.StartArray();
+ writer.Double(0.12345); // "0.123"
+ writer.Double(0.0001); // "0.0"
+ writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
+ writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
+ writer.EndArray();
+ \endcode
+
+ The default setting does not truncate any decimal places. You can restore to this setting by calling
+ \code
+ writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
+ \endcode
+ */
+ void SetMaxDecimalPlaces(int maxDecimalPlaces) {
+ maxDecimalPlaces_ = maxDecimalPlaces;
+ }
+
+ /*!@name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { Prefix(kNullType); return WriteNull(); }
+ bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
+ bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
+ bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
+ bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
+ bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
+
+ //! Writes the given \c double value to the stream
+ /*!
+ \param d The value to be written.
+ \return Whether it is succeed.
+ */
+ bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
+
+ bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kNumberType);
+ return WriteString(str, length);
+ }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kStringType);
+ return WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ Prefix(kObjectType);
+ new (level_stack_.template Push<Level>()) Level(false);
+ return WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ bool ret = WriteEndObject();
+ if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
+ os_->Flush();
+ return ret;
+ }
+
+ bool StartArray() {
+ Prefix(kArrayType);
+ new (level_stack_.template Push<Level>()) Level(true);
+ return WriteStartArray();
+ }
+
+ bool EndArray(SizeType elementCount = 0) {
+ (void)elementCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ bool ret = WriteEndArray();
+ if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
+ os_->Flush();
+ return ret;
+ }
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! Simpler but slower overload.
+ bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
+ bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
+
+ //@}
+
+ //! Write a raw JSON value.
+ /*!
+ For user to write a stringified JSON as a value.
+
+ \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
+ \param length Length of the json.
+ \param type Type of the root of json.
+ */
+ bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return WriteRawValue(json, length); }
+
+protected:
+ //! Information for each nested level
+ struct Level {
+ Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
+ size_t valueCount; //!< number of values in this level
+ bool inArray; //!< true if in array, otherwise in object
+ };
+
+ static const size_t kDefaultLevelDepth = 32;
+
+ bool WriteNull() {
+ PutReserve(*os_, 4);
+ PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
+ }
+
+ bool WriteBool(bool b) {
+ if (b) {
+ PutReserve(*os_, 4);
+ PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
+ }
+ else {
+ PutReserve(*os_, 5);
+ PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
+ }
+ return true;
+ }
+
+ bool WriteInt(int i) {
+ char buffer[11];
+ const char* end = internal::i32toa(i, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (const char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteUint(unsigned u) {
+ char buffer[10];
+ const char* end = internal::u32toa(u, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (const char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteInt64(int64_t i64) {
+ char buffer[21];
+ const char* end = internal::i64toa(i64, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (const char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteUint64(uint64_t u64) {
+ char buffer[20];
+ char* end = internal::u64toa(u64, buffer);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteDouble(double d) {
+ if (internal::Double(d).IsNanOrInf()) {
+ if (!(writeFlags & kWriteNanAndInfFlag))
+ return false;
+ if (internal::Double(d).IsNan()) {
+ PutReserve(*os_, 3);
+ PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
+ return true;
+ }
+ if (internal::Double(d).Sign()) {
+ PutReserve(*os_, 9);
+ PutUnsafe(*os_, '-');
+ }
+ else
+ PutReserve(*os_, 8);
+ PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
+ PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
+ return true;
+ }
+
+ char buffer[25];
+ char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
+ PutReserve(*os_, static_cast<size_t>(end - buffer));
+ for (char* p = buffer; p != end; ++p)
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
+ return true;
+ }
+
+ bool WriteString(const Ch* str, SizeType length) {
+ static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ static const char escape[256] = {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ //0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+ 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
+ Z16, Z16, // 30~4F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
+#undef Z16
+ };
+
+ if (TargetEncoding::supportUnicode)
+ PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
+ else
+ PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
+
+ PutUnsafe(*os_, '\"');
+ GenericStringStream<SourceEncoding> is(str);
+ while (ScanWriteUnescapedString(is, length)) {
+ const Ch c = is.Peek();
+ if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
+ // Unicode escaping
+ unsigned codepoint;
+ if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
+ return false;
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, 'u');
+ if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
+ PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
+ // Surrogate pair
+ unsigned s = codepoint - 0x010000;
+ unsigned lead = (s >> 10) + 0xD800;
+ unsigned trail = (s & 0x3FF) + 0xDC00;
+ PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(lead ) & 15]);
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, 'u');
+ PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
+ PutUnsafe(*os_, hexDigits[(trail ) & 15]);
+ }
+ }
+ else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
+ is.Take();
+ PutUnsafe(*os_, '\\');
+ PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
+ if (escape[static_cast<unsigned char>(c)] == 'u') {
+ PutUnsafe(*os_, '0');
+ PutUnsafe(*os_, '0');
+ PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
+ PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
+ }
+ }
+ else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
+ Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
+ Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
+ return false;
+ }
+ PutUnsafe(*os_, '\"');
+ return true;
+ }
+
+ bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+
+ bool WriteStartObject() { os_->Put('{'); return true; }
+ bool WriteEndObject() { os_->Put('}'); return true; }
+ bool WriteStartArray() { os_->Put('['); return true; }
+ bool WriteEndArray() { os_->Put(']'); return true; }
+
+ bool WriteRawValue(const Ch* json, size_t length) {
+ PutReserve(*os_, length);
+ for (size_t i = 0; i < length; i++) {
+ RAPIDJSON_ASSERT(json[i] != '\0');
+ PutUnsafe(*os_, json[i]);
+ }
+ return true;
+ }
+
+ void Prefix(Type type) {
+ (void)type;
+ if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
+ Level* level = level_stack_.template Top<Level>();
+ if (level->valueCount > 0) {
+ if (level->inArray)
+ os_->Put(','); // add comma if it is not the first element in array
+ else // in object
+ os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
+ hasRoot_ = true;
+ }
+ }
+
+ OutputStream* os_;
+ internal::Stack<StackAllocator> level_stack_;
+ int maxDecimalPlaces_;
+ bool hasRoot_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ Writer(const Writer&);
+ Writer& operator=(const Writer&);
+};
+
+// Full specialization for StringStream to prevent memory copying
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt(int i) {
+ char *buffer = os_->Push(11);
+ const char* end = internal::i32toa(i, buffer);
+ os_->Pop(static_cast<size_t>(11 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
+ char *buffer = os_->Push(10);
+ const char* end = internal::u32toa(u, buffer);
+ os_->Pop(static_cast<size_t>(10 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
+ char *buffer = os_->Push(21);
+ const char* end = internal::i64toa(i64, buffer);
+ os_->Pop(static_cast<size_t>(21 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
+ char *buffer = os_->Push(20);
+ const char* end = internal::u64toa(u, buffer);
+ os_->Pop(static_cast<size_t>(20 - (end - buffer)));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteDouble(double d) {
+ if (internal::Double(d).IsNanOrInf()) {
+ // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
+ if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
+ return false;
+ if (internal::Double(d).IsNan()) {
+ PutReserve(*os_, 3);
+ PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
+ return true;
+ }
+ if (internal::Double(d).Sign()) {
+ PutReserve(*os_, 9);
+ PutUnsafe(*os_, '-');
+ }
+ else
+ PutReserve(*os_, 8);
+ PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
+ PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
+ return true;
+ }
+
+ char *buffer = os_->Push(25);
+ char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
+ os_->Pop(static_cast<size_t>(25 - (end - buffer)));
+ return true;
+}
+
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+template<>
+inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
+ if (length < 16)
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+
+ if (!RAPIDJSON_LIKELY(is.Tell() < length))
+ return false;
+
+ const char* p = is.src_;
+ const char* end = is.head_ + length;
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
+ const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
+ if (nextAligned > end)
+ return true;
+
+ while (p != nextAligned)
+ if (*p < 0x20 || *p == '\"' || *p == '\\') {
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+ }
+ else
+ os_->PutUnsafe(*p++);
+
+ // The rest of string using SIMD
+ static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
+ static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
+ static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
+ const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
+ const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
+ const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
+
+ for (; p != endAligned; p += 16) {
+ const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
+ const __m128i t1 = _mm_cmpeq_epi8(s, dq);
+ const __m128i t2 = _mm_cmpeq_epi8(s, bs);
+ const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
+ const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
+ unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
+ if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
+ SizeType len;
+#ifdef _MSC_VER // Find the index of first escaped
+ unsigned long offset;
+ _BitScanForward(&offset, r);
+ len = offset;
+#else
+ len = static_cast<SizeType>(__builtin_ffs(r) - 1);
+#endif
+ char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
+ for (size_t i = 0; i < len; i++)
+ q[i] = p[i];
+
+ p += len;
+ break;
+ }
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
+ }
+
+ is.src_ = p;
+ return RAPIDJSON_LIKELY(is.Tell() < length);
+}
+#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/ext/librethinkdbxx/src/term.cc b/ext/librethinkdbxx/src/term.cc
new file mode 100644
index 00000000..711ef27d
--- /dev/null
+++ b/ext/librethinkdbxx/src/term.cc
@@ -0,0 +1,285 @@
+#include <cstdlib>
+#include <set>
+
+#include "term.h"
+#include "json_p.h"
+
+namespace RethinkDB {
+
+using TT = Protocol::Term::TermType;
+
+struct {
+ Datum operator() (const Array& array) {
+ Array copy;
+ copy.reserve(array.size());
+ for (const auto& it : array) {
+ copy.emplace_back(it.apply<Datum>(*this));
+ }
+ return Datum(Array{TT::MAKE_ARRAY, std::move(copy)});
+ }
+ Datum operator() (const Object& object) {
+ Object copy;
+ for (const auto& it : object) {
+ copy.emplace(it.first, it.second.apply<Datum>(*this));
+ }
+ return std::move(copy);
+ }
+ template<class T>
+ Datum operator() (T&& atomic) {
+ return Datum(std::forward<T>(atomic));
+ }
+} datum_to_term;
+
+Term::Term(Datum&& datum_) : datum(datum_.apply<Datum>(datum_to_term)) { }
+Term::Term(const Datum& datum_) : datum(datum_.apply<Datum>(datum_to_term)) { }
+
+Term::Term(Term&& orig, OptArgs&& new_optargs) : datum(Nil()) {
+ Datum* cur = orig.datum.get_nth(2);
+ Object optargs;
+ free_vars = std::move(orig.free_vars);
+ if (cur) {
+ optargs = std::move(cur->extract_object());
+ }
+ for (auto& it : new_optargs) {
+ optargs.emplace(std::move(it.first), alpha_rename(std::move(it.second)));
+ }
+ datum = Array{ std::move(orig.datum.extract_nth(0)), std::move(orig.datum.extract_nth(1)), std::move(optargs) };
+}
+
+Term nil() {
+ return Term(Nil());
+}
+
+Cursor Term::run(Connection& conn, OptArgs&& opts) {
+ if (!free_vars.empty()) {
+ throw Error("run: term has free variables");
+ }
+
+ return conn.start_query(this, std::move(opts));
+}
+
+struct {
+ Datum operator() (Object&& object, const std::map<int, int>& subst, bool) {
+ Object ret;
+ for (auto& it : object) {
+ ret.emplace(std::move(it.first), std::move(it.second).apply<Datum>(*this, subst, false));
+ }
+ return ret;
+ }
+ Datum operator() (Array&& array, const std::map<int, int>& subst, bool args) {
+ if (!args) {
+ double cmd = array[0].extract_number();
+ if (cmd == static_cast<int>(TT::VAR)) {
+ double var = array[1].extract_nth(0).extract_number();
+ auto it = subst.find(static_cast<int>(var));
+ if (it != subst.end()) {
+ return Array{ TT::VAR, { it->second }};
+ }
+ }
+ if (array.size() == 2) {
+ return Array{ std::move(array[0]), std::move(array[1]).apply<Datum>(*this, subst, true) };
+ } else {
+ return Array{
+ std::move(array[0]),
+ std::move(array[1]).apply<Datum>(*this, subst, true),
+ std::move(array[2]).apply<Datum>(*this, subst, false) };
+ }
+ } else {
+ Array ret;
+ for (auto& it : array) {
+ ret.emplace_back(std::move(it).apply<Datum>(*this, subst, false));
+ }
+ return ret;
+ }
+ }
+ template <class T>
+ Datum operator() (T&& a, const std::map<int, int>&, bool) {
+ return std::move(a);
+ }
+} alpha_renamer;
+
+static int new_var_id(const std::map<int, int*>& vars) {
+ while (true) {
+ int id = gen_var_id();
+ if (vars.find(id) == vars.end()) {
+ return id;
+ }
+ }
+}
+
+Datum Term::alpha_rename(Term&& term) {
+ if (free_vars.empty()) {
+ free_vars = std::move(term.free_vars);
+ return std::move(term.datum);
+ }
+
+ std::map<int, int> subst;
+ for (auto it = term.free_vars.begin(); it != term.free_vars.end(); ++it) {
+ auto var = free_vars.find(it->first);
+ if (var == free_vars.end()) {
+ free_vars.emplace(it->first, it->second);
+ } else if (var->second != it->second) {
+ int id = new_var_id(free_vars);
+ subst.emplace(it->first, id);
+ free_vars.emplace(id, it->second);
+ }
+ }
+ if (subst.empty()) {
+ return std::move(term.datum);
+ } else {
+ return term.datum.apply<Datum>(alpha_renamer, subst, false);
+ }
+}
+
+int gen_var_id() {
+ return ::random() % (1<<30);
+}
+
+C0_IMPL(db_list, DB_LIST)
+C0_IMPL(table_list, TABLE_LIST)
+C0_IMPL(random, RANDOM)
+C0_IMPL(now, NOW)
+C0_IMPL(range, RANGE)
+C0_IMPL(error, ERROR)
+C0_IMPL(uuid, UUID)
+C0_IMPL(literal, LITERAL)
+CO0_IMPL(wait, WAIT)
+C0_IMPL(rebalance, REBALANCE)
+CO0_IMPL(random, RANDOM)
+
+Term row(TT::IMPLICIT_VAR, {});
+Term minval(TT::MINVAL, {});
+Term maxval(TT::MAXVAL, {});
+
+Term binary(const std::string& data) {
+ return expr(Binary(data));
+}
+
+Term binary(std::string&& data) {
+ return expr(Binary(data));
+}
+
+Term binary(const char* data) {
+ return expr(Binary(data));
+}
+
+struct {
+ bool operator() (const Object& object) {
+ for (const auto& it : object) {
+ if (it.second.apply<bool>(*this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ bool operator() (const Array& array) {
+ int type = *array[0].get_number();
+ if (type == static_cast<int>(TT::IMPLICIT_VAR)) {
+ return true;
+ }
+ if (type == static_cast<int>(TT::FUNC)) {
+ return false;
+ }
+ for (const auto& it : *array[1].get_array()) {
+ if (it.apply<bool>(*this)) {
+ return true;
+ }
+ }
+ if (array.size() == 3) {
+ return array[2].apply<bool>(*this);
+ } else {
+ return false;
+ }
+ }
+ template <class T>
+ bool operator() (T) {
+ return false;
+ }
+} needs_func_wrap;
+
+Term Term::func_wrap(Term&& term) {
+ if (term.datum.apply<bool>(needs_func_wrap)) {
+ return Term(TT::FUNC, {expr(Array{new_var_id(term.free_vars)}), std::move(term)});
+ }
+ return term;
+}
+
+Term Term::func_wrap(const Term& term) {
+ if (term.datum.apply<bool>(needs_func_wrap)) {
+ // TODO return Term(TT::FUNC, {expr(Array{new_var_id(Term.free_vars)}), Term.copy()});
+ return Term(Nil());
+ }
+ return term;
+}
+
+Term Term::make_object(std::vector<Term>&& args) {
+ if (args.size() % 2 != 0) {
+ return Term(TT::OBJECT, std::move(args));
+ }
+ std::set<std::string> keys;
+ for (auto it = args.begin(); it != args.end() && it + 1 != args.end(); it += 2) {
+ std::string* key = it->datum.get_string();
+ if (!key || keys.count(*key)) {
+ return Term(TT::OBJECT, std::move(args));
+ }
+ keys.insert(*key);
+ }
+ Term ret{Nil()};
+ Object object;
+ for (auto it = args.begin(); it != args.end(); it += 2) {
+ std::string* key = it->datum.get_string();
+ object.emplace(std::move(*key), ret.alpha_rename(std::move(*(it + 1))));
+ }
+ ret.datum = std::move(object);
+ return ret;
+}
+
+Term Term::make_binary(Term&& term) {
+ std::string* string = term.datum.get_string();
+ if (string) {
+ return expr(Binary(std::move(*string)));
+ }
+ return Term(TT::BINARY, std::vector<Term>{term});
+}
+
+Term::Term(OptArgs&& optargs) : datum(Nil()) {
+ Object oargs;
+ for (auto& it : optargs) {
+ oargs.emplace(it.first, alpha_rename(std::move(it.second)));
+ }
+ datum = std::move(oargs);
+}
+
+OptArgs optargs() {
+ return OptArgs{};
+}
+
+Term january(TT::JANUARY, {});
+Term february(TT::FEBRUARY, {});
+Term march(TT::MARCH, {});
+Term april(TT::APRIL, {});
+Term may(TT::MAY, {});
+Term june(TT::JUNE, {});
+Term july(TT::JULY, {});
+Term august(TT::AUGUST, {});
+Term september(TT::SEPTEMBER, {});
+Term october(TT::OCTOBER, {});
+Term november(TT::NOVEMBER, {});
+Term december(TT::DECEMBER, {});
+Term monday(TT::MONDAY, {});
+Term tuesday(TT::TUESDAY, {});
+Term wednesday(TT::WEDNESDAY, {});
+Term thursday(TT::THURSDAY, {});
+Term friday(TT::FRIDAY, {});
+Term saturday(TT::SATURDAY, {});
+Term sunday(TT::SUNDAY, {});
+
+Term Term::copy() const {
+ return *this;
+}
+
+Datum Term::get_datum() const {
+ return datum;
+}
+
+}
diff --git a/ext/librethinkdbxx/src/term.h b/ext/librethinkdbxx/src/term.h
new file mode 100644
index 00000000..cdee5ec4
--- /dev/null
+++ b/ext/librethinkdbxx/src/term.h
@@ -0,0 +1,592 @@
+#pragma once
+
+#include "datum.h"
+#include "connection.h"
+#include "protocol_defs.h"
+#include "cursor.h"
+
+namespace RethinkDB {
+
+using TT = Protocol::Term::TermType;
+
+class Term;
+class Var;
+
+// An alias for the Term constructor
+template <class T>
+Term expr(T&&);
+
+int gen_var_id();
+
+// Can be used as the last argument to some ReQL commands that expect named arguments
+using OptArgs = std::map<std::string, Term>;
+
+// Represents a ReQL Term (RethinkDB Query Language)
+// Designed to be used with r-value *this
+class Term {
+public:
+ Term(const Term& other) = default;
+ Term(Term&& other) = default;
+ Term& operator= (const Term& other) = default;
+ Term& operator= (Term&& other) = default;
+
+ explicit Term(Datum&&);
+ explicit Term(const Datum&);
+ explicit Term(OptArgs&&);
+
+ // Create a copy of the Term
+ Term copy() const;
+
+ Term(std::function<Term()> f) : datum(Nil()) { set_function<std::function<Term()>>(f); }
+ Term(std::function<Term(Var)> f) : datum(Nil()) { set_function<std::function<Term(Var)>, 0>(f); }
+ Term(std::function<Term(Var, Var)> f) : datum(Nil()) { set_function<std::function<Term(Var, Var)>, 0, 1>(f); }
+ Term(std::function<Term(Var, Var, Var)> f) : datum(Nil()) { set_function<std::function<Term(Var, Var, Var)>, 0, 1, 2>(f); }
+ Term(Protocol::Term::TermType type, std::vector<Term>&& args) : datum(Array()) {
+ Array dargs;
+ for (auto& it : args) {
+ dargs.emplace_back(alpha_rename(std::move(it)));
+ }
+ datum = Datum(Array{ type, std::move(dargs) });
+ }
+
+ Term(Protocol::Term::TermType type, std::vector<Term>&& args, OptArgs&& optargs) : datum(Array()) {
+ Array dargs;
+ for (auto& it : args) {
+ dargs.emplace_back(alpha_rename(std::move(it)));
+ }
+ Object oargs;
+ for (auto& it : optargs) {
+ oargs.emplace(it.first, alpha_rename(std::move(it.second)));
+ }
+ datum = Array{ type, std::move(dargs), std::move(oargs) };
+ }
+
+ // Used internally to support row
+ static Term func_wrap(Term&&);
+ static Term func_wrap(const Term&);
+
+
+ // These macros are used to define most ReQL commands
+ // * Cn represents a method with n arguments
+ // * COn represents a method with n arguments and optional named arguments
+ // * C_ represents a method with any number of arguments
+ // Each method is implemented twice, once with r-value *this, and once with const *this
+ // The third argument, wrap, allows converting arguments into functions if they contain row
+
+#define C0(name, type) \
+ Term name() && { return Term(TT::type, std::vector<Term>{ std::move(*this) }); } \
+ Term name() const & { return Term(TT::type, std::vector<Term>{ *this }); }
+#define C1(name, type, wrap) \
+ template <class T> \
+ Term name(T&& a) && { return Term(TT::type, std::vector<Term>{ std::move(*this), wrap(expr(std::forward<T>(a))) }); } \
+ template <class T> \
+ Term name(T&& a) const & { return Term(TT::type, std::vector<Term>{ *this, wrap(expr(std::forward<T>(a))) }); }
+#define C2(name, type) \
+ template <class T, class U> Term name(T&& a, U&& b) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this), \
+ expr(std::forward<T>(a)), expr(std::forward<U>(b)) }); } \
+ template <class T, class U> Term name(T&& a, U&& b) const & { \
+ return Term(TT::type, std::vector<Term>{ *this, \
+ expr(std::forward<T>(a)), expr(std::forward<U>(b)) }); }
+#define C_(name, type, wrap) \
+ template <class ...T> Term name(T&& ...a) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this), \
+ wrap(expr(std::forward<T>(a)))... }); } \
+ template <class ...T> Term name(T&& ...a) const & { \
+ return Term(TT::type, std::vector<Term>{ *this, \
+ wrap(expr(std::forward<T>(a)))... }); }
+#define CO0(name, type) \
+ Term name(OptArgs&& optarg = {}) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this) }, std::move(optarg)); } \
+ Term name(OptArgs&& optarg = {}) const & { \
+ return Term(TT::type, std::vector<Term>{ *this }, std::move(optarg)); }
+#define CO1(name, type, wrap) \
+ template <class T> Term name(T&& a, OptArgs&& optarg = {}) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this), \
+ wrap(expr(std::forward<T>(a))) }, std::move(optarg)); } \
+ template <class T> Term name(T&& a, OptArgs&& optarg = {}) const & { \
+ return Term(TT::type, std::vector<Term>{ *this, \
+ wrap(expr(std::forward<T>(a))) }, std::move(optarg)); }
+#define CO2(name, type, wrap) \
+ template <class T, class U> Term name(T&& a, U&& b, OptArgs&& optarg = {}) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this), \
+ wrap(expr(std::forward<T>(a))), wrap(expr(std::forward<U>(b))) }, std::move(optarg)); } \
+ template <class T, class U> Term name(T&& a, U&& b, OptArgs&& optarg = {}) const & { \
+ return Term(TT::type, std::vector<Term>{ *this, \
+ wrap(expr(std::forward<T>(a))), wrap(expr(std::forward<U>(b))) }, std::move(optarg)); }
+#define CO3(name, type, wrap) \
+ template <class T, class U, class V> Term name(T&& a, U&& b, V&& c, OptArgs&& optarg = {}) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this), \
+ wrap(expr(std::forward<T>(a))), wrap(expr(std::forward<U>(b))), \
+ wrap(expr(std::forward<V>(c))) }, std::move(optarg)); } \
+ template <class T, class U, class V> Term name(T&& a, U&& b, V&& c, OptArgs&& optarg = {}) const & { \
+ return Term(TT::type, std::vector<Term>{ *this, \
+ wrap(expr(std::forward<T>(a))), wrap(expr(std::forward<U>(b))), \
+ wrap(expr(std::forward<V>(c)))}, std::move(optarg)); }
+#define CO4(name, type, wrap) \
+ template <class T, class U, class V, class W> Term name(T&& a, U&& b, V&& c, W&& d, OptArgs&& optarg = {}) && { \
+ return Term(TT::type, std::vector<Term>{ std::move(*this), \
+ wrap(expr(std::forward<T>(a))), wrap(expr(std::forward<U>(b))), \
+ wrap(expr(std::forward<V>(c))), wrap(expr(std::forward<W>(d))) }, std::move(optarg)); } \
+ template <class T, class U, class V, class W> Term name(T&& a, U&& b, V&& c, W&& d, OptArgs&& optarg = {}) const & { \
+ return Term(TT::type, std::vector<Term>{ *this, \
+ wrap(expr(std::forward<T>(a))), wrap(expr(std::forward<U>(b))), \
+ wrap(expr(std::forward<V>(c))), wrap(expr(std::forward<W>(d))) }, std::move(optarg)); }
+#define CO_(name, type, wrap) \
+ C_(name, type, wrap) \
+ CO0(name, type) \
+ CO1(name, type, wrap) \
+ CO2(name, type, wrap) \
+ CO3(name, type, wrap) \
+ CO4(name, type, wrap)
+#define no_wrap(x) x
+
+ CO1(table_create, TABLE_CREATE, no_wrap)
+ C1(table_drop, TABLE_DROP, no_wrap)
+ C0(table_list, TABLE_LIST)
+ CO1(index_create, INDEX_CREATE, no_wrap)
+ CO2(index_create, INDEX_CREATE, func_wrap)
+ C1(index_drop, INDEX_DROP, no_wrap)
+ C0(index_list, INDEX_LIST)
+ CO2(index_rename, INDEX_RENAME, no_wrap)
+ C_(index_status, INDEX_STATUS, no_wrap)
+ C_(index_wait, INDEX_WAIT, no_wrap)
+ CO0(changes, CHANGES)
+ CO1(insert, INSERT, no_wrap)
+ CO1(update, UPDATE, func_wrap)
+ CO1(replace, REPLACE, func_wrap)
+ CO0(delete_, DELETE)
+ C0(sync, SYNC)
+ CO1(table, TABLE, no_wrap)
+ C1(get, GET, no_wrap)
+ CO_(get_all, GET_ALL, no_wrap)
+ CO2(between, BETWEEN, no_wrap)
+ CO1(filter, FILTER, func_wrap)
+ C2(inner_join, INNER_JOIN)
+ C2(outer_join, OUTER_JOIN)
+ CO2(eq_join, EQ_JOIN, func_wrap)
+ C0(zip, ZIP)
+ C_(map, MAP, func_wrap)
+ C_(with_fields, WITH_FIELDS, no_wrap)
+ C1(concat_map, CONCAT_MAP, func_wrap)
+ CO_(order_by, ORDER_BY, func_wrap)
+ C1(skip, SKIP, no_wrap)
+ C1(limit, LIMIT, no_wrap)
+ CO1(slice, SLICE, no_wrap)
+ CO2(slice, SLICE, no_wrap)
+ C1(nth, NTH, no_wrap)
+ C1(offsets_of, OFFSETS_OF, func_wrap)
+ C0(is_empty, IS_EMPTY)
+ CO_(union_, UNION, no_wrap)
+ C1(sample, SAMPLE, no_wrap)
+ CO_(group, GROUP, func_wrap)
+ C0(ungroup, UNGROUP)
+ C1(reduce, REDUCE, no_wrap)
+ CO2(fold, FOLD, no_wrap)
+ C0(count, COUNT)
+ C1(count, COUNT, func_wrap)
+ C0(sum, SUM)
+ C1(sum, SUM, func_wrap)
+ C0(avg, AVG)
+ C1(avg, AVG, func_wrap)
+ C1(min, MIN, func_wrap)
+ CO0(min, MIN)
+ C1(max, MAX, func_wrap)
+ CO0(max, MAX)
+ CO0(distinct, DISTINCT)
+ C_(contains, CONTAINS, func_wrap)
+ C_(pluck, PLUCK, no_wrap)
+ C_(without, WITHOUT, no_wrap)
+ C_(merge, MERGE, func_wrap)
+ C1(append, APPEND, no_wrap)
+ C1(prepend, PREPEND, no_wrap)
+ C1(difference, DIFFERENCE, no_wrap)
+ C1(set_insert, SET_INSERT, no_wrap)
+ C1(set_union, SET_UNION, no_wrap)
+ C1(set_intersection, SET_INTERSECTION, no_wrap)
+ C1(set_difference, SET_DIFFERENCE, no_wrap)
+ C1(operator[], BRACKET, no_wrap)
+ C1(get_field, GET_FIELD, no_wrap)
+ C_(has_fields, HAS_FIELDS, no_wrap)
+ C2(insert_at, INSERT_AT)
+ C2(splice_at, SPLICE_AT)
+ C1(delete_at, DELETE_AT, no_wrap)
+ C2(delete_at, DELETE_AT)
+ C2(change_at, CHANGE_AT)
+ C0(keys, KEYS)
+ C1(match, MATCH, no_wrap)
+ C0(split, SPLIT)
+ C1(split, SPLIT, no_wrap)
+ C2(split, SPLIT)
+ C0(upcase, UPCASE)
+ C0(downcase, DOWNCASE)
+ C_(add, ADD, no_wrap)
+ C1(operator+, ADD, no_wrap)
+ C_(sub, SUB, no_wrap)
+ C1(operator-, SUB, no_wrap)
+ C_(mul, MUL, no_wrap)
+ C1(operator*, MUL, no_wrap)
+ C_(div, DIV, no_wrap)
+ C1(operator/, DIV, no_wrap)
+ C1(mod, MOD, no_wrap)
+ C1(operator%, MOD, no_wrap)
+ C_(and_, AND, no_wrap)
+ C1(operator&&, AND, no_wrap)
+ C_(or_, OR, no_wrap)
+ C1(operator||, OR, no_wrap)
+ C1(eq, EQ, no_wrap)
+ C1(operator==, EQ, no_wrap)
+ C1(ne, NE, no_wrap)
+ C1(operator!=, NE, no_wrap)
+ C1(gt, GT, no_wrap)
+ C1(operator>, GT, no_wrap)
+ C1(ge, GE, no_wrap)
+ C1(operator>=, GE, no_wrap)
+ C1(lt, LT, no_wrap)
+ C1(operator<, LT, no_wrap)
+ C1(le, LE, no_wrap)
+ C1(operator<=, LE, no_wrap)
+ C0(not_, NOT)
+ C0(operator!, NOT)
+ C1(in_timezone, IN_TIMEZONE, no_wrap)
+ C0(timezone, TIMEZONE)
+ CO2(during, DURING, no_wrap)
+ C0(date, DATE)
+ C0(time_of_day, TIME_OF_DAY)
+ C0(year, YEAR)
+ C0(month, MONTH)
+ C0(day, DAY)
+ C0(day_of_week, DAY_OF_WEEK)
+ C0(day_of_year, DAY_OF_YEAR)
+ C0(hours, HOURS)
+ C0(minutes, MINUTES)
+ C0(seconds, SECONDS)
+ C0(to_iso8601, TO_ISO8601)
+ C0(to_epoch_time, TO_EPOCH_TIME)
+ C1(for_each, FOR_EACH, func_wrap)
+ C1(default_, DEFAULT, no_wrap)
+ CO1(js, JAVASCRIPT, no_wrap)
+ C1(coerce_to, COERCE_TO, no_wrap)
+ C0(type_of, TYPE_OF)
+ C0(info, INFO)
+ C0(to_json, TO_JSON_STRING)
+ C0(to_json_string, TO_JSON_STRING)
+ C1(distance, DISTANCE, no_wrap)
+ C0(fill, FILL)
+ C0(to_geojson, TO_GEOJSON)
+ CO1(get_intersecting, GET_INTERSECTING, no_wrap)
+ CO1(get_nearest, GET_NEAREST, no_wrap)
+ C1(includes, INCLUDES, no_wrap)
+ C1(intersects, INTERSECTS, no_wrap)
+ C1(polygon_sub, POLYGON_SUB, no_wrap)
+ C0(config, CONFIG)
+ C0(rebalance, REBALANCE)
+ CO0(reconfigure, RECONFIGURE)
+ C0(status, STATUS)
+ CO0(wait, WAIT)
+ C0(floor, FLOOR)
+ C0(ceil, CEIL)
+ C0(round, ROUND)
+ C0(values, VALUES)
+
+ // The expansion of this macro fails to compile on some versions of GCC and Clang:
+ // C_(operator(), FUNCALL, no_wrap)
+ // The std::enable_if makes the error go away
+
+ // $doc(do)
+
+ template <class T, class ...U>
+ typename std::enable_if<!std::is_same<T, Var>::value, Term>::type
+ operator() (T&& a, U&& ...b) && {
+ return Term(TT::FUNCALL, std::vector<Term>{
+ std::move(*this),
+ expr(std::forward<T>(a)),
+ expr(std::forward<U>(b))... });
+ }
+ template <class T, class ...U>
+ typename std::enable_if<!std::is_same<T, Var>::value, Term>::type
+ operator() (T&& a, U&& ...b) const & {
+ return Term(TT::FUNCALL, std::vector<Term>{
+ *this,
+ expr(std::forward<T>(a)),
+ expr(std::forward<U>(b))... });
+ }
+
+#undef C0
+#undef C1
+#undef C2
+#undef C_
+#undef CO0
+#undef CO1
+#undef CO2
+
+ // Send the term to the server and return the results.
+ // Errors returned by the server are thrown.
+ Cursor run(Connection&, OptArgs&& args = {});
+
+ // $doc(do)
+ template <class ...T>
+ Term do_(T&& ...a) && {
+ auto list = { std::move(*this), Term::func_wrap(expr(std::forward<T>(a)))... };
+ std::vector<Term> args;
+ args.reserve(list.size() + 1);
+ args.emplace_back(func_wrap(std::move(*(list.end()-1))));
+ for (auto it = list.begin(); it + 1 != list.end(); ++it) {
+ args.emplace_back(std::move(*it));
+ }
+ return Term(TT::FUNCALL, std::move(args));
+ }
+
+ // Adds optargs to an already built term
+ Term opt(OptArgs&& optargs) && {
+ return Term(std::move(*this), std::move(optargs));
+ }
+
+ // Used internally to implement object()
+ static Term make_object(std::vector<Term>&&);
+
+ // Used internally to implement array()
+ static Term make_binary(Term&&);
+
+ Datum get_datum() const;
+
+private:
+ friend class Var;
+ friend class Connection;
+ friend struct Query;
+
+ template <int _>
+ Var mkvar(std::vector<int>& vars);
+
+ template <class F, int ...N>
+ void set_function(F);
+
+ Datum alpha_rename(Term&&);
+
+ Term(Term&& orig, OptArgs&& optargs);
+
+ std::map<int, int*> free_vars;
+ Datum datum;
+};
+
+// A term representing null
+Term nil();
+
+template <class T>
+Term expr(T&& a) {
+ return Term(std::forward<T>(a));
+}
+
+// Represents a ReQL variable.
+// This type is passed to functions used in ReQL queries.
+class Var {
+public:
+ // Convert to a term
+ Term operator*() const {
+ Term term(TT::VAR, std::vector<Term>{expr(*id)});
+ term.free_vars = {{*id, id}};
+ return term;
+ }
+
+ Var(int* id_) : id(id_) { }
+private:
+ int* id;
+};
+
+template <int N>
+Var Term::mkvar(std::vector<int>& vars) {
+ int id = gen_var_id();
+ vars.push_back(id);
+ return Var(&*vars.rbegin());
+}
+
+template <class F, int ...N>
+void Term::set_function(F f) {
+ std::vector<int> vars;
+ vars.reserve(sizeof...(N));
+ std::vector<Var> args = { mkvar<N>(vars)... };
+ Term body = f(args[N] ...);
+
+ int* low = &*vars.begin();
+ int* high = &*(vars.end() - 1);
+ for (auto it = body.free_vars.begin(); it != body.free_vars.end(); ) {
+ if (it->second >= low && it->second <= high) {
+ if (it->first != *it->second) {
+ throw Error("Internal error: variable index mis-match");
+ }
+ ++it;
+ } else {
+ free_vars.emplace(*it);
+ ++it;
+ }
+ }
+ datum = Array{TT::FUNC, Array{Array{TT::MAKE_ARRAY, vars}, body.datum}};
+}
+
+// These macros are similar to those defined above, but for top-level ReQL operations
+
+#define C0(name) Term name();
+#define C0_IMPL(name, type) Term name() { return Term(TT::type, std::vector<Term>{}); }
+#define CO0(name) Term name(OptArgs&& optargs = {});
+#define CO0_IMPL(name, type) Term name(OptArgs&& optargs) { return Term(TT::type, std::vector<Term>{}, std::move(optargs)); }
+#define C1(name, type, wrap) template <class T> Term name(T&& a) { \
+ return Term(TT::type, std::vector<Term>{ wrap(expr(std::forward<T>(a))) }); }
+#define C2(name, type) template <class T, class U> Term name(T&& a, U&& b) { \
+ return Term(TT::type, std::vector<Term>{ expr(std::forward<T>(a)), expr(std::forward<U>(b)) }); }
+#define C3(name, type) template <class A, class B, class C> \
+ Term name(A&& a, B&& b, C&& c) { return Term(TT::type, std::vector<Term>{ \
+ expr(std::forward<A>(a)), expr(std::forward<B>(b)), expr(std::forward<C>(c)) }); }
+#define C4(name, type) template <class A, class B, class C, class D> \
+ Term name(A&& a, B&& b, C&& c, D&& d) { return Term(TT::type, std::vector<Term>{ \
+ expr(std::forward<A>(a)), expr(std::forward<B>(b)), \
+ expr(std::forward<C>(c)), expr(std::forward<D>(d))}); }
+#define C7(name, type) template <class A, class B, class C, class D, class E, class F, class G> \
+ Term name(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f, G&& g) { return Term(TT::type, std::vector<Term>{ \
+ expr(std::forward<A>(a)), expr(std::forward<B>(b)), expr(std::forward<C>(c)), \
+ expr(std::forward<D>(d)), expr(std::forward<E>(e)), expr(std::forward<F>(f)), \
+ expr(std::forward<G>(g))}); }
+#define C_(name, type, wrap) template <class ...T> Term name(T&& ...a) { \
+ return Term(TT::type, std::vector<Term>{ wrap(expr(std::forward<T>(a)))... }); }
+#define CO1(name, type, wrap) template <class T> Term name(T&& a, OptArgs&& optarg = {}) { \
+ return Term(TT::type, std::vector<Term>{ wrap(expr(std::forward<T>(a)))}, std::move(optarg)); }
+#define CO2(name, type) template <class T, class U> Term name(T&& a, U&& b, OptArgs&& optarg = {}) { \
+ return Term(TT::type, std::vector<Term>{ expr(std::forward<T>(a)), expr(std::forward<U>(b))}, std::move(optarg)); }
+#define func_wrap Term::func_wrap
+
+C1(db_create, DB_CREATE, no_wrap)
+C1(db_drop, DB_DROP, no_wrap)
+C0(db_list)
+CO1(table_create, TABLE_CREATE, no_wrap)
+C1(table_drop, TABLE_DROP, no_wrap)
+C0(table_list)
+C1(db, DB, no_wrap)
+CO1(table, TABLE, no_wrap)
+C_(add, ADD, no_wrap)
+C2(sub, SUB)
+C_(mul, MUL, no_wrap)
+C_(div, DIV, no_wrap)
+C2(mod, MOD)
+C_(and_, AND, no_wrap)
+C_(or_, OR, no_wrap)
+C2(eq, EQ)
+C2(ne, NE)
+C2(gt, GT)
+C2(ge, GE)
+C2(lt, LT)
+C2(le, LE)
+C1(not_, NOT, no_wrap)
+CO0(random)
+CO1(random, RANDOM, no_wrap)
+CO2(random, RANDOM)
+C0(now)
+C4(time, TIME)
+C7(time, TIME)
+C1(epoch_time, EPOCH_TIME, no_wrap)
+CO1(iso8601, ISO8601, no_wrap)
+CO1(js, JAVASCRIPT, no_wrap)
+C1(args, ARGS, no_wrap)
+C_(branch, BRANCH, no_wrap)
+C0(range)
+C1(range, RANGE, no_wrap)
+C2(range, RANGE)
+C0(error)
+C1(error, ERROR, no_wrap)
+C1(json, JSON, no_wrap)
+CO1(http, HTTP, func_wrap)
+C0(uuid)
+C1(uuid, UUID, no_wrap)
+CO2(circle, CIRCLE)
+C1(geojson, GEOJSON, no_wrap)
+C_(line, LINE, no_wrap)
+C2(point, POINT)
+C_(polygon, POLYGON, no_wrap)
+C_(array, MAKE_ARRAY, no_wrap)
+C1(desc, DESC, func_wrap)
+C1(asc, ASC, func_wrap)
+C0(literal)
+C1(literal, LITERAL, no_wrap)
+C1(type_of, TYPE_OF, no_wrap)
+C_(map, MAP, func_wrap)
+C1(floor, FLOOR, no_wrap)
+C1(ceil, CEIL, no_wrap)
+C1(round, ROUND, no_wrap)
+C_(union_, UNION, no_wrap)
+C_(group, GROUP, func_wrap)
+C1(count, COUNT, no_wrap)
+C_(count, COUNT, func_wrap)
+C1(sum, SUM, no_wrap)
+C_(sum, SUM, func_wrap)
+C1(avg, AVG, no_wrap)
+C_(avg, AVG, func_wrap)
+C1(min, MIN, no_wrap)
+C_(min, MIN, func_wrap)
+C1(max, MAX, no_wrap)
+C_(max, MAX, func_wrap)
+C1(distinct, DISTINCT, no_wrap)
+C1(contains, CONTAINS, no_wrap)
+C_(contains, CONTAINS, func_wrap)
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef C4
+#undef C7
+#undef C_
+#undef CO1
+#undef CO2
+#undef func_wrap
+
+// $doc(do)
+template <class R, class ...T>
+Term do_(R&& a, T&& ...b) {
+ return expr(std::forward<R>(a)).do_(std::forward<T>(b)...);
+}
+
+// $doc(object)
+template <class ...T>
+Term object(T&& ...a) {
+ return Term::make_object(std::vector<Term>{ expr(std::forward<T>(a))... });
+}
+
+// $doc(binary)
+template <class T>
+Term binary(T&& a) {
+ return Term::make_binary(expr(std::forward<T>(a)));
+}
+
+// Construct an empty optarg
+OptArgs optargs();
+
+// Construct an optarg made out of pairs of arguments
+// For example: optargs("k1", v1, "k2", v2)
+template <class V, class ...T>
+OptArgs optargs(const char* key, V&& val, T&& ...rest) {
+ OptArgs opts = optargs(rest...);
+ opts.emplace(key, expr(std::forward<V>(val)));
+ return opts;
+}
+
+extern Term row;
+extern Term maxval;
+extern Term minval;
+extern Term january;
+extern Term february;
+extern Term march;
+extern Term april;
+extern Term may;
+extern Term june;
+extern Term july;
+extern Term august;
+extern Term september;
+extern Term october;
+extern Term november;
+extern Term december;
+extern Term monday;
+extern Term tuesday;
+extern Term wednesday;
+extern Term thursday;
+extern Term friday;
+extern Term saturday;
+extern Term sunday;
+}
diff --git a/ext/librethinkdbxx/src/types.cc b/ext/librethinkdbxx/src/types.cc
new file mode 100644
index 00000000..ea9becaf
--- /dev/null
+++ b/ext/librethinkdbxx/src/types.cc
@@ -0,0 +1,47 @@
+#include <cstdlib>
+
+#include "types.h"
+#include "error.h"
+
+namespace RethinkDB {
+
+bool Time::parse_utc_offset(const std::string& string, double* offset) {
+ const char *s = string.c_str();
+ double sign = 1;
+ switch (s[0]) {
+ case '-':
+ sign = -1;
+ case '+':
+ ++s;
+ break;
+ case 0:
+ return false;
+ }
+ for (int i = 0; i < 5; ++i) {
+ if (s[i] == 0) return false;
+ if (i == 2) continue;
+ if (s[i] < '0' || s[i] > '9') return false;
+ }
+ if (s[2] != ':') return false;
+ *offset = sign * ((s[0] - '0') * 36000 + (s[1] - '0') * 3600 + (s[3] - '0') * 600 + (s[4] - '0') * 60);
+ return true;
+}
+
+double Time::parse_utc_offset(const std::string& string) {
+ double out;
+ if (!parse_utc_offset(string, &out)) {
+ throw Error("invalid utc offset `%s'", string.c_str());
+ }
+ return out;
+}
+
+std::string Time::utc_offset_string(double offset) {
+ char buf[8];
+ int hour = offset / 3600;
+ int minutes = std::abs(static_cast<int>(offset / 60)) % 60;
+ int n = snprintf(buf, 7, "%+03d:%02d", hour, minutes);
+ buf[n] = 0;
+ return std::string(buf);
+}
+
+}
diff --git a/ext/librethinkdbxx/src/types.h b/ext/librethinkdbxx/src/types.h
new file mode 100644
index 00000000..ac35a871
--- /dev/null
+++ b/ext/librethinkdbxx/src/types.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <vector>
+#include <map>
+#include <ctime>
+#include <string>
+
+namespace RethinkDB {
+
+class Datum;
+
+// Represents a null datum
+struct Nil { };
+
+using Array = std::vector<Datum>;
+using Object = std::map<std::string, Datum>;
+
+// Represents a string of bytes. Plain std::strings are passed on to the server as utf-8 strings
+struct Binary {
+ bool operator== (const Binary& other) const {
+ return data == other.data;
+ }
+
+ Binary(const std::string& data_) : data(data_) { }
+ Binary(std::string&& data_) : data(std::move(data_)) { }
+ std::string data;
+};
+
+// Represents a point in time as
+// * A floating amount of seconds since the UNIX epoch
+// * And a timezone offset represented as seconds relative to UTC
+struct Time {
+ Time(double epoch_time_, double utc_offset_ = 0) :
+ epoch_time(epoch_time_), utc_offset(utc_offset_) { }
+
+ static Time now() {
+ return Time(time(NULL));
+ }
+
+ static bool parse_utc_offset(const std::string&, double*);
+ static double parse_utc_offset(const std::string&);
+ static std::string utc_offset_string(double);
+
+ double epoch_time;
+ double utc_offset;
+};
+
+// Not implemented
+class Point;
+class Line;
+class Polygon;
+
+}
diff --git a/ext/librethinkdbxx/src/utils.cc b/ext/librethinkdbxx/src/utils.cc
new file mode 100644
index 00000000..5a2c244d
--- /dev/null
+++ b/ext/librethinkdbxx/src/utils.cc
@@ -0,0 +1,153 @@
+#include "utils.h"
+#include "error.h"
+
+namespace RethinkDB {
+
+size_t utf8_encode(unsigned int code, char* buf) {
+ if (!(code & ~0x7F)) {
+ buf[0] = code;
+ return 1;
+ } else if (!(code & ~0x7FF)) {
+ buf[0] = 0xC0 | (code >> 6);
+ buf[1] = 0x80 | (code & 0x3F);
+ return 2;
+ } else if (!(code & ~0xFFFF)) {
+ buf[0] = 0xE0 | (code >> 12);
+ buf[1] = 0x80 | ((code >> 6) & 0x3F);
+ buf[2] = 0x80 | (code & 0x3F);
+ return 3;
+ } else if (!(code & ~0x1FFFFF)) {
+ buf[0] = 0xF0 | (code >> 18);
+ buf[1] = 0x80 | ((code >> 12) & 0x3F);
+ buf[2] = 0x80 | ((code >> 6) & 0x3F);
+ buf[3] = 0x80 | (code & 0x3F);
+ return 4;
+ } else if (!(code & ~0x3FFFFFF)) {
+ buf[0] = 0xF8 | (code >> 24);
+ buf[1] = 0x80 | ((code >> 18) & 0x3F);
+ buf[2] = 0x80 | ((code >> 12) & 0x3F);
+ buf[3] = 0x80 | ((code >> 6) & 0x3F);
+ buf[4] = 0x80 | (code & 0x3F);
+ return 5;
+ } else if (!(code & ~0x7FFFFFFF)) {
+ buf[0] = 0xFC | (code >> 30);
+ buf[1] = 0x80 | ((code >> 24) & 0x3F);
+ buf[2] = 0x80 | ((code >> 18) & 0x3F);
+ buf[3] = 0x80 | ((code >> 12) & 0x3F);
+ buf[4] = 0x80 | ((code >> 6) & 0x3F);
+ buf[5] = 0x80 | (code & 0x3F);
+ return 6;
+ } else {
+ throw Error("Invalid unicode codepoint %ud", code);
+ }
+}
+
+bool base64_decode(char c, int* out) {
+ if (c >= 'A' && c <= 'Z') {
+ *out = c - 'A';
+ } else if (c >= 'a' && c <= 'z') {
+ *out = c - ('a' - 26);
+ } else if (c >= '0' && c <= '9') {
+ *out = c - ('0' - 52);
+ } else if (c == '+') {
+ *out = 62;
+ } else if (c == '/') {
+ *out = 63;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool base64_decode(const std::string& in, std::string& out) {
+ out.clear();
+ out.reserve(in.size() * 3 / 4);
+ auto read = in.begin();
+ while (true) {
+ int c[4];
+ int end = 4;
+ for (int i = 0; i < 4; i++) {
+ while (true) {
+ if (read == in.end()) {
+ c[i] = 0;
+ end = i;
+ i = 3;
+ break;
+ } else if (base64_decode(*read, &c[i])) {
+ ++read;
+ break;
+ } else {
+ ++read;
+ }
+ }
+ }
+ if (end == 1) return false;
+ int val = c[0] << 18 | c[1] << 12 | c[2] << 6 | c[3];
+ if (end > 1) out.append(1, val >> 16);
+ if (end > 2) out.append(1, val >> 8 & 0xFF);
+ if (end > 3) out.append(1, val & 0xFF);
+ if (end != 4) break;
+ }
+ return true;
+}
+
+char base64_encode(unsigned int c) {
+ if (c < 26) {
+ return 'A' + c;
+ } else if (c < 52) {
+ return 'a' + c - 26;
+ } else if (c < 62) {
+ return '0' + c - 52;
+ } else if (c == 62) {
+ return '+';
+ } else if (c == 63) {
+ return '/';
+ } else {
+ throw Error("unreachable: base64 encoding %d", c);
+ }
+}
+
+void base64_encode(unsigned int* c, int n, std::string& out) {
+ if (n == 0) {
+ return;
+ }
+ out.append(1, base64_encode(c[0] >> 2));
+ out.append(1, base64_encode((c[0] & 0x3) << 4 | c[1] >> 4));
+ if (n == 1) {
+ out.append("==");
+ return;
+ }
+ out.append(1, base64_encode((c[1] & 0xF) << 2 | c[2] >> 6));
+ if (n == 2) {
+ out.append("=");
+ return;
+ }
+ out.append(1, base64_encode(c[2] & 0x3F));
+}
+
+std::string base64_encode(const std::string& in) {
+ std::string out;
+ out.reserve(in.size() * 4 / 3 + in.size() / 48 + 3);
+ auto read = in.begin();
+ while (true) {
+ for (int group = 0; group < 16; ++group) {
+ unsigned int c[3];
+ int i = 0;
+ for (; i < 3; ++i) {
+ if (read == in.end()) {
+ c[i] = 0;
+ break;
+ } else {
+ c[i] = static_cast<unsigned char>(*read++);
+ }
+ }
+ base64_encode(c, i, out);
+ if (i != 3) {
+ return out;
+ }
+ }
+ out.append("\n");
+ }
+}
+
+}
diff --git a/ext/librethinkdbxx/src/utils.h b/ext/librethinkdbxx/src/utils.h
new file mode 100644
index 00000000..04496e2c
--- /dev/null
+++ b/ext/librethinkdbxx/src/utils.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <cstddef>
+#include <string>
+
+namespace RethinkDB {
+
+// The size of the longest UTF-8 encoded unicode codepoint
+const size_t max_utf8_encoded_size = 6;
+
+// Decode a base64 string. Returns false on failure.
+bool base64_decode(const std::string& in, std::string& out);
+std::string base64_encode(const std::string&);
+
+// Encodes a single unicode codepoint into UTF-8. Returns the number of bytes written.
+// Does not add a trailing null byte
+size_t utf8_encode(unsigned int, char*);
+
+}
diff --git a/ext/lz4/lz4.c b/ext/lz4/lz4.c
deleted file mode 100644
index 08cf6b5c..00000000
--- a/ext/lz4/lz4.c
+++ /dev/null
@@ -1,1516 +0,0 @@
-/*
- LZ4 - Fast LZ compression algorithm
- Copyright (C) 2011-2015, Yann Collet.
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- You can contact the author at :
- - LZ4 source repository : https://github.com/Cyan4973/lz4
- - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
-*/
-
-
-/**************************************
-* Tuning parameters
-**************************************/
-/*
- * HEAPMODE :
- * Select how default compression functions will allocate memory for their hash table,
- * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
- */
-#define HEAPMODE 0
-
-/*
- * ACCELERATION_DEFAULT :
- * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
- */
-#define ACCELERATION_DEFAULT 1
-
-
-/**************************************
-* CPU Feature Detection
-**************************************/
-/*
- * LZ4_FORCE_SW_BITCOUNT
- * Define this parameter if your target system or compiler does not support hardware bit count
- */
-#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
-# define LZ4_FORCE_SW_BITCOUNT
-#endif
-
-
-/**************************************
-* Includes
-**************************************/
-#include "lz4.h"
-
-
-/**************************************
-* Compiler Options
-**************************************/
-#ifdef _MSC_VER /* Visual Studio */
-# define FORCE_INLINE static __forceinline
-# include <intrin.h>
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
-#else
-# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
-# if defined(__GNUC__) || defined(__clang__)
-# define FORCE_INLINE static inline __attribute__((always_inline))
-# else
-# define FORCE_INLINE static inline
-# endif
-# else
-# define FORCE_INLINE static
-# endif /* __STDC_VERSION__ */
-#endif /* _MSC_VER */
-
-/* LZ4_GCC_VERSION is defined into lz4.h */
-#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
-# define expect(expr,value) (__builtin_expect ((expr),(value)) )
-#else
-# define expect(expr,value) (expr)
-#endif
-
-#define likely(expr) expect((expr) != 0, 1)
-#define unlikely(expr) expect((expr) != 0, 0)
-
-
-/**************************************
-* Memory routines
-**************************************/
-#include <stdlib.h> /* malloc, calloc, free */
-#define ALLOCATOR(n,s) calloc(n,s)
-#define FREEMEM free
-#include <string.h> /* memset, memcpy */
-#define MEM_INIT memset
-
-
-/**************************************
-* Basic Types
-**************************************/
-#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
-# include <stdint.h>
- typedef uint8_t BYTE;
- typedef uint16_t U16;
- typedef uint32_t U32;
- typedef int32_t S32;
- typedef uint64_t U64;
-#else
- typedef unsigned char BYTE;
- typedef unsigned short U16;
- typedef unsigned int U32;
- typedef signed int S32;
- typedef unsigned long long U64;
-#endif
-
-
-/**************************************
-* Reading and writing into memory
-**************************************/
-#define STEPSIZE sizeof(size_t)
-
-static unsigned LZ4_64bits(void) { return sizeof(void*)==8; }
-
-static unsigned LZ4_isLittleEndian(void)
-{
- const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
- return one.c[0];
-}
-
-
-static U16 LZ4_read16(const void* memPtr)
-{
- U16 val16;
- memcpy(&val16, memPtr, 2);
- return val16;
-}
-
-static U16 LZ4_readLE16(const void* memPtr)
-{
- if (LZ4_isLittleEndian())
- {
- return LZ4_read16(memPtr);
- }
- else
- {
- const BYTE* p = (const BYTE*)memPtr;
- return (U16)((U16)p[0] + (p[1]<<8));
- }
-}
-
-static void LZ4_writeLE16(void* memPtr, U16 value)
-{
- if (LZ4_isLittleEndian())
- {
- memcpy(memPtr, &value, 2);
- }
- else
- {
- BYTE* p = (BYTE*)memPtr;
- p[0] = (BYTE) value;
- p[1] = (BYTE)(value>>8);
- }
-}
-
-static U32 LZ4_read32(const void* memPtr)
-{
- U32 val32;
- memcpy(&val32, memPtr, 4);
- return val32;
-}
-
-static U64 LZ4_read64(const void* memPtr)
-{
- U64 val64;
- memcpy(&val64, memPtr, 8);
- return val64;
-}
-
-static size_t LZ4_read_ARCH(const void* p)
-{
- if (LZ4_64bits())
- return (size_t)LZ4_read64(p);
- else
- return (size_t)LZ4_read32(p);
-}
-
-
-static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); }
-
-static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); }
-
-/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
-static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
-{
- BYTE* d = (BYTE*)dstPtr;
- const BYTE* s = (const BYTE*)srcPtr;
- BYTE* e = (BYTE*)dstEnd;
- do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
-}
-
-
-/**************************************
-* Common Constants
-**************************************/
-#define MINMATCH 4
-
-#define COPYLENGTH 8
-#define LASTLITERALS 5
-#define MFLIMIT (COPYLENGTH+MINMATCH)
-static const int LZ4_minLength = (MFLIMIT+1);
-
-#define KB *(1 <<10)
-#define MB *(1 <<20)
-#define GB *(1U<<30)
-
-#define MAXD_LOG 16
-#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
-
-#define ML_BITS 4
-#define ML_MASK ((1U<<ML_BITS)-1)
-#define RUN_BITS (8-ML_BITS)
-#define RUN_MASK ((1U<<RUN_BITS)-1)
-
-
-/**************************************
-* Common Utils
-**************************************/
-#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
-
-
-/**************************************
-* Common functions
-**************************************/
-static unsigned LZ4_NbCommonBytes (register size_t val)
-{
- if (LZ4_isLittleEndian())
- {
- if (LZ4_64bits())
- {
-# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
- unsigned long r = 0;
- _BitScanForward64( &r, (U64)val );
- return (int)(r>>3);
-# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
- return (__builtin_ctzll((U64)val) >> 3);
-# else
- static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
- return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
-# endif
- }
- else /* 32 bits */
- {
-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
- unsigned long r;
- _BitScanForward( &r, (U32)val );
- return (int)(r>>3);
-# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
- return (__builtin_ctz((U32)val) >> 3);
-# else
- static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
- return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
-# endif
- }
- }
- else /* Big Endian CPU */
- {
- if (LZ4_64bits())
- {
-# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
- unsigned long r = 0;
- _BitScanReverse64( &r, val );
- return (unsigned)(r>>3);
-# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
- return (__builtin_clzll((U64)val) >> 3);
-# else
- unsigned r;
- if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
- if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
- r += (!val);
- return r;
-# endif
- }
- else /* 32 bits */
- {
-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
- unsigned long r = 0;
- _BitScanReverse( &r, (unsigned long)val );
- return (unsigned)(r>>3);
-# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
- return (__builtin_clz((U32)val) >> 3);
-# else
- unsigned r;
- if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
- r += (!val);
- return r;
-# endif
- }
- }
-}
-
-static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
-{
- const BYTE* const pStart = pIn;
-
- while (likely(pIn<pInLimit-(STEPSIZE-1)))
- {
- size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
- if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
- pIn += LZ4_NbCommonBytes(diff);
- return (unsigned)(pIn - pStart);
- }
-
- if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
- if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
- if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
- return (unsigned)(pIn - pStart);
-}
-
-
-#ifndef LZ4_COMMONDEFS_ONLY
-/**************************************
-* Local Constants
-**************************************/
-#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
-#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
-#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
-
-static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
-static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
-
-
-/**************************************
-* Local Structures and types
-**************************************/
-typedef struct {
- U32 hashTable[HASH_SIZE_U32];
- U32 currentOffset;
- U32 initCheck;
- const BYTE* dictionary;
- BYTE* bufferStart; /* obsolete, used for slideInputBuffer */
- U32 dictSize;
-} LZ4_stream_t_internal;
-
-typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
-typedef enum { byPtr, byU32, byU16 } tableType_t;
-
-typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
-typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
-
-typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
-typedef enum { full = 0, partial = 1 } earlyEnd_directive;
-
-
-/**************************************
-* Local Utils
-**************************************/
-int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
-int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
-int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
-
-
-
-/********************************
-* Compression functions
-********************************/
-
-static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType)
-{
- if (tableType == byU16)
- return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
- else
- return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
-}
-
-static const U64 prime5bytes = 889523592379ULL;
-static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType)
-{
- const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
- const U32 hashMask = (1<<hashLog) - 1;
- return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
-}
-
-static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
-{
- if (LZ4_64bits())
- return LZ4_hashSequence64(sequence, tableType);
- return LZ4_hashSequence((U32)sequence, tableType);
-}
-
-static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); }
-
-static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
-{
- switch (tableType)
- {
- case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
- case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
- case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
- }
-}
-
-static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
-{
- U32 h = LZ4_hashPosition(p, tableType);
- LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
-}
-
-static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
-{
- if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
- if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
- { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
-}
-
-static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
-{
- U32 h = LZ4_hashPosition(p, tableType);
- return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
-}
-
-FORCE_INLINE int LZ4_compress_generic(
- void* const ctx,
- const char* const source,
- char* const dest,
- const int inputSize,
- const int maxOutputSize,
- const limitedOutput_directive outputLimited,
- const tableType_t tableType,
- const dict_directive dict,
- const dictIssue_directive dictIssue,
- const U32 acceleration)
-{
- LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx;
-
- const BYTE* ip = (const BYTE*) source;
- const BYTE* base;
- const BYTE* lowLimit;
- const BYTE* const lowRefLimit = ip - dictPtr->dictSize;
- const BYTE* const dictionary = dictPtr->dictionary;
- const BYTE* const dictEnd = dictionary + dictPtr->dictSize;
- const size_t dictDelta = dictEnd - (const BYTE*)source;
- const BYTE* anchor = (const BYTE*) source;
- const BYTE* const iend = ip + inputSize;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = iend - LASTLITERALS;
-
- BYTE* op = (BYTE*) dest;
- BYTE* const olimit = op + maxOutputSize;
-
- U32 forwardH;
- size_t refDelta=0;
-
- /* Init conditions */
- if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
- switch(dict)
- {
- case noDict:
- default:
- base = (const BYTE*)source;
- lowLimit = (const BYTE*)source;
- break;
- case withPrefix64k:
- base = (const BYTE*)source - dictPtr->currentOffset;
- lowLimit = (const BYTE*)source - dictPtr->dictSize;
- break;
- case usingExtDict:
- base = (const BYTE*)source - dictPtr->currentOffset;
- lowLimit = (const BYTE*)source;
- break;
- }
- if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
- if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
-
- /* First Byte */
- LZ4_putPosition(ip, ctx, tableType, base);
- ip++; forwardH = LZ4_hashPosition(ip, tableType);
-
- /* Main Loop */
- for ( ; ; )
- {
- const BYTE* match;
- BYTE* token;
- {
- const BYTE* forwardIp = ip;
- unsigned step = 1;
- unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
-
- /* Find a match */
- do {
- U32 h = forwardH;
- ip = forwardIp;
- forwardIp += step;
- step = (searchMatchNb++ >> LZ4_skipTrigger);
-
- if (unlikely(forwardIp > mflimit)) goto _last_literals;
-
- match = LZ4_getPositionOnHash(h, ctx, tableType, base);
- if (dict==usingExtDict)
- {
- if (match<(const BYTE*)source)
- {
- refDelta = dictDelta;
- lowLimit = dictionary;
- }
- else
- {
- refDelta = 0;
- lowLimit = (const BYTE*)source;
- }
- }
- forwardH = LZ4_hashPosition(forwardIp, tableType);
- LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
-
- } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
- || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
- || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
- }
-
- /* Catch up */
- while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
-
- {
- /* Encode Literal length */
- unsigned litLength = (unsigned)(ip - anchor);
- token = op++;
- if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
- return 0; /* Check output limit */
- if (litLength>=RUN_MASK)
- {
- int len = (int)litLength-RUN_MASK;
- *token=(RUN_MASK<<ML_BITS);
- for(; len >= 255 ; len-=255) *op++ = 255;
- *op++ = (BYTE)len;
- }
- else *token = (BYTE)(litLength<<ML_BITS);
-
- /* Copy Literals */
- LZ4_wildCopy(op, anchor, op+litLength);
- op+=litLength;
- }
-
-_next_match:
- /* Encode Offset */
- LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
-
- /* Encode MatchLength */
- {
- unsigned matchLength;
-
- if ((dict==usingExtDict) && (lowLimit==dictionary))
- {
- const BYTE* limit;
- match += refDelta;
- limit = ip + (dictEnd-match);
- if (limit > matchlimit) limit = matchlimit;
- matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
- ip += MINMATCH + matchLength;
- if (ip==limit)
- {
- unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit);
- matchLength += more;
- ip += more;
- }
- }
- else
- {
- matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
- ip += MINMATCH + matchLength;
- }
-
- if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))
- return 0; /* Check output limit */
- if (matchLength>=ML_MASK)
- {
- *token += ML_MASK;
- matchLength -= ML_MASK;
- for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }
- if (matchLength >= 255) { matchLength-=255; *op++ = 255; }
- *op++ = (BYTE)matchLength;
- }
- else *token += (BYTE)(matchLength);
- }
-
- anchor = ip;
-
- /* Test end of chunk */
- if (ip > mflimit) break;
-
- /* Fill table */
- LZ4_putPosition(ip-2, ctx, tableType, base);
-
- /* Test next position */
- match = LZ4_getPosition(ip, ctx, tableType, base);
- if (dict==usingExtDict)
- {
- if (match<(const BYTE*)source)
- {
- refDelta = dictDelta;
- lowLimit = dictionary;
- }
- else
- {
- refDelta = 0;
- lowLimit = (const BYTE*)source;
- }
- }
- LZ4_putPosition(ip, ctx, tableType, base);
- if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
- && (match+MAX_DISTANCE>=ip)
- && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
- { token=op++; *token=0; goto _next_match; }
-
- /* Prepare next loop */
- forwardH = LZ4_hashPosition(++ip, tableType);
- }
-
-_last_literals:
- /* Encode Last Literals */
- {
- const size_t lastRun = (size_t)(iend - anchor);
- if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize))
- return 0; /* Check output limit */
- if (lastRun >= RUN_MASK)
- {
- size_t accumulator = lastRun - RUN_MASK;
- *op++ = RUN_MASK << ML_BITS;
- for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
- *op++ = (BYTE) accumulator;
- }
- else
- {
- *op++ = (BYTE)(lastRun<<ML_BITS);
- }
- memcpy(op, anchor, lastRun);
- op += lastRun;
- }
-
- /* End */
- return (int) (((char*)op)-dest);
-}
-
-
-int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
-{
- LZ4_resetStream((LZ4_stream_t*)state);
- if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
-
- if (maxOutputSize >= LZ4_compressBound(inputSize))
- {
- if (inputSize < LZ4_64Klimit)
- return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
- else
- return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
- }
- else
- {
- if (inputSize < LZ4_64Klimit)
- return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
- else
- return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
- }
-}
-
-
-int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
-{
-#if (HEAPMODE)
- void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
-#else
- LZ4_stream_t ctx;
- void* ctxPtr = &ctx;
-#endif
-
- int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
-
-#if (HEAPMODE)
- FREEMEM(ctxPtr);
-#endif
- return result;
-}
-
-
-int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
-{
- return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
-}
-
-
-/* hidden debug function */
-/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
-int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
-{
- LZ4_stream_t ctx;
-
- LZ4_resetStream(&ctx);
-
- if (inputSize < LZ4_64Klimit)
- return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);
- else
- return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
-}
-
-
-/********************************
-* destSize variant
-********************************/
-
-static int LZ4_compress_destSize_generic(
- void* const ctx,
- const char* const src,
- char* const dst,
- int* const srcSizePtr,
- const int targetDstSize,
- const tableType_t tableType)
-{
- const BYTE* ip = (const BYTE*) src;
- const BYTE* base = (const BYTE*) src;
- const BYTE* lowLimit = (const BYTE*) src;
- const BYTE* anchor = ip;
- const BYTE* const iend = ip + *srcSizePtr;
- const BYTE* const mflimit = iend - MFLIMIT;
- const BYTE* const matchlimit = iend - LASTLITERALS;
-
- BYTE* op = (BYTE*) dst;
- BYTE* const oend = op + targetDstSize;
- BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
- BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
- BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
-
- U32 forwardH;
-
-
- /* Init conditions */
- if (targetDstSize < 1) return 0; /* Impossible to store anything */
- if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
- if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
- if (*srcSizePtr<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
-
- /* First Byte */
- *srcSizePtr = 0;
- LZ4_putPosition(ip, ctx, tableType, base);
- ip++; forwardH = LZ4_hashPosition(ip, tableType);
-
- /* Main Loop */
- for ( ; ; )
- {
- const BYTE* match;
- BYTE* token;
- {
- const BYTE* forwardIp = ip;
- unsigned step = 1;
- unsigned searchMatchNb = 1 << LZ4_skipTrigger;
-
- /* Find a match */
- do {
- U32 h = forwardH;
- ip = forwardIp;
- forwardIp += step;
- step = (searchMatchNb++ >> LZ4_skipTrigger);
-
- if (unlikely(forwardIp > mflimit))
- goto _last_literals;
-
- match = LZ4_getPositionOnHash(h, ctx, tableType, base);
- forwardH = LZ4_hashPosition(forwardIp, tableType);
- LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
-
- } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
- || (LZ4_read32(match) != LZ4_read32(ip)) );
- }
-
- /* Catch up */
- while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
-
- {
- /* Encode Literal length */
- unsigned litLength = (unsigned)(ip - anchor);
- token = op++;
- if (op + ((litLength+240)/255) + litLength > oMaxLit)
- {
- /* Not enough space for a last match */
- op--;
- goto _last_literals;
- }
- if (litLength>=RUN_MASK)
- {
- unsigned len = litLength - RUN_MASK;
- *token=(RUN_MASK<<ML_BITS);
- for(; len >= 255 ; len-=255) *op++ = 255;
- *op++ = (BYTE)len;
- }
- else *token = (BYTE)(litLength<<ML_BITS);
-
- /* Copy Literals */
- LZ4_wildCopy(op, anchor, op+litLength);
- op += litLength;
- }
-
-_next_match:
- /* Encode Offset */
- LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
-
- /* Encode MatchLength */
- {
- size_t matchLength;
-
- matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
-
- if (op + ((matchLength+240)/255) > oMaxMatch)
- {
- /* Match description too long : reduce it */
- matchLength = (15-1) + (oMaxMatch-op) * 255;
- }
- //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);
- ip += MINMATCH + matchLength;
-
- if (matchLength>=ML_MASK)
- {
- *token += ML_MASK;
- matchLength -= ML_MASK;
- while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
- *op++ = (BYTE)matchLength;
- }
- else *token += (BYTE)(matchLength);
- }
-
- anchor = ip;
-
- /* Test end of block */
- if (ip > mflimit) break;
- if (op > oMaxSeq) break;
-
- /* Fill table */
- LZ4_putPosition(ip-2, ctx, tableType, base);
-
- /* Test next position */
- match = LZ4_getPosition(ip, ctx, tableType, base);
- LZ4_putPosition(ip, ctx, tableType, base);
- if ( (match+MAX_DISTANCE>=ip)
- && (LZ4_read32(match)==LZ4_read32(ip)) )
- { token=op++; *token=0; goto _next_match; }
-
- /* Prepare next loop */
- forwardH = LZ4_hashPosition(++ip, tableType);
- }
-
-_last_literals:
- /* Encode Last Literals */
- {
- size_t lastRunSize = (size_t)(iend - anchor);
- if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend)
- {
- /* adapt lastRunSize to fill 'dst' */
- lastRunSize = (oend-op) - 1;
- lastRunSize -= (lastRunSize+240)/255;
- }
- ip = anchor + lastRunSize;
-
- if (lastRunSize >= RUN_MASK)
- {
- size_t accumulator = lastRunSize - RUN_MASK;
- *op++ = RUN_MASK << ML_BITS;
- for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
- *op++ = (BYTE) accumulator;
- }
- else
- {
- *op++ = (BYTE)(lastRunSize<<ML_BITS);
- }
- memcpy(op, anchor, lastRunSize);
- op += lastRunSize;
- }
-
- /* End */
- *srcSizePtr = (int) (((const char*)ip)-src);
- return (int) (((char*)op)-dst);
-}
-
-
-static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
-{
- LZ4_resetStream((LZ4_stream_t*)state);
-
- if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */
- {
- return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
- }
- else
- {
- if (*srcSizePtr < LZ4_64Klimit)
- return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
- else
- return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr);
- }
-}
-
-
-int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
-{
-#if (HEAPMODE)
- void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
-#else
- LZ4_stream_t ctxBody;
- void* ctx = &ctxBody;
-#endif
-
- int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
-
-#if (HEAPMODE)
- FREEMEM(ctx);
-#endif
- return result;
-}
-
-
-
-/********************************
-* Streaming functions
-********************************/
-
-LZ4_stream_t* LZ4_createStream(void)
-{
- LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
- LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
- LZ4_resetStream(lz4s);
- return lz4s;
-}
-
-void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
-{
- MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));
-}
-
-int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
-{
- FREEMEM(LZ4_stream);
- return (0);
-}
-
-
-#define HASH_UNIT sizeof(size_t)
-int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
-{
- LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
- const BYTE* p = (const BYTE*)dictionary;
- const BYTE* const dictEnd = p + dictSize;
- const BYTE* base;
-
- if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */
- LZ4_resetStream(LZ4_dict);
-
- if (dictSize < (int)HASH_UNIT)
- {
- dict->dictionary = NULL;
- dict->dictSize = 0;
- return 0;
- }
-
- if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
- dict->currentOffset += 64 KB;
- base = p - dict->currentOffset;
- dict->dictionary = p;
- dict->dictSize = (U32)(dictEnd - p);
- dict->currentOffset += dict->dictSize;
-
- while (p <= dictEnd-HASH_UNIT)
- {
- LZ4_putPosition(p, dict->hashTable, byU32, base);
- p+=3;
- }
-
- return dict->dictSize;
-}
-
-
-static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
-{
- if ((LZ4_dict->currentOffset > 0x80000000) ||
- ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */
- {
- /* rescale hash table */
- U32 delta = LZ4_dict->currentOffset - 64 KB;
- const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
- int i;
- for (i=0; i<HASH_SIZE_U32; i++)
- {
- if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
- else LZ4_dict->hashTable[i] -= delta;
- }
- LZ4_dict->currentOffset = 64 KB;
- if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
- LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
- }
-}
-
-
-int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
-{
- LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream;
- const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
-
- const BYTE* smallest = (const BYTE*) source;
- if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */
- if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
- LZ4_renormDictT(streamPtr, smallest);
- if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
-
- /* Check overlapping input/dictionary space */
- {
- const BYTE* sourceEnd = (const BYTE*) source + inputSize;
- if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd))
- {
- streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
- if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
- if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
- streamPtr->dictionary = dictEnd - streamPtr->dictSize;
- }
- }
-
- /* prefix mode : source data follows dictionary */
- if (dictEnd == (const BYTE*)source)
- {
- int result;
- if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
- else
- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);
- streamPtr->dictSize += (U32)inputSize;
- streamPtr->currentOffset += (U32)inputSize;
- return result;
- }
-
- /* external dictionary mode */
- {
- int result;
- if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
- else
- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
- streamPtr->dictionary = (const BYTE*)source;
- streamPtr->dictSize = (U32)inputSize;
- streamPtr->currentOffset += (U32)inputSize;
- return result;
- }
-}
-
-
-/* Hidden debug function, to force external dictionary mode */
-int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize)
-{
- LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict;
- int result;
- const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
-
- const BYTE* smallest = dictEnd;
- if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
- LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest);
-
- result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
-
- streamPtr->dictionary = (const BYTE*)source;
- streamPtr->dictSize = (U32)inputSize;
- streamPtr->currentOffset += (U32)inputSize;
-
- return result;
-}
-
-
-int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
-{
- LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
- const BYTE* previousDictEnd = dict->dictionary + dict->dictSize;
-
- if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
- if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
-
- memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
-
- dict->dictionary = (const BYTE*)safeBuffer;
- dict->dictSize = (U32)dictSize;
-
- return dictSize;
-}
-
-
-
-/*******************************
-* Decompression functions
-*******************************/
-/*
- * This generic decompression function cover all use cases.
- * It shall be instantiated several times, using different sets of directives
- * Note that it is essential this generic function is really inlined,
- * in order to remove useless branches during compilation optimization.
- */
-FORCE_INLINE int LZ4_decompress_generic(
- const char* const source,
- char* const dest,
- int inputSize,
- int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
-
- int endOnInput, /* endOnOutputSize, endOnInputSize */
- int partialDecoding, /* full, partial */
- int targetOutputSize, /* only used if partialDecoding==partial */
- int dict, /* noDict, withPrefix64k, usingExtDict */
- const BYTE* const lowPrefix, /* == dest if dict == noDict */
- const BYTE* const dictStart, /* only if dict==usingExtDict */
- const size_t dictSize /* note : = 0 if noDict */
- )
-{
- /* Local Variables */
- const BYTE* ip = (const BYTE*) source;
- const BYTE* const iend = ip + inputSize;
-
- BYTE* op = (BYTE*) dest;
- BYTE* const oend = op + outputSize;
- BYTE* cpy;
- BYTE* oexit = op + targetOutputSize;
- const BYTE* const lowLimit = lowPrefix - dictSize;
-
- const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
- const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
- const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
-
- const int safeDecode = (endOnInput==endOnInputSize);
- const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
-
-
- /* Special cases */
- if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
- if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
- if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
-
-
- /* Main Loop */
- while (1)
- {
- unsigned token;
- size_t length;
- const BYTE* match;
-
- /* get literal length */
- token = *ip++;
- if ((length=(token>>ML_BITS)) == RUN_MASK)
- {
- unsigned s;
- do
- {
- s = *ip++;
- length += s;
- }
- while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255));
- if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
- if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
- }
-
- /* copy literals */
- cpy = op+length;
- if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
- || ((!endOnInput) && (cpy>oend-COPYLENGTH)))
- {
- if (partialDecoding)
- {
- if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
- if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
- }
- else
- {
- if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
- if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
- }
- memcpy(op, ip, length);
- ip += length;
- op += length;
- break; /* Necessarily EOF, due to parsing restrictions */
- }
- LZ4_wildCopy(op, ip, cpy);
- ip += length; op = cpy;
-
- /* get offset */
- match = cpy - LZ4_readLE16(ip); ip+=2;
- if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
-
- /* get matchlength */
- length = token & ML_MASK;
- if (length == ML_MASK)
- {
- unsigned s;
- do
- {
- if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
- s = *ip++;
- length += s;
- } while (s==255);
- if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
- }
- length += MINMATCH;
-
- /* check external dictionary */
- if ((dict==usingExtDict) && (match < lowPrefix))
- {
- if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
-
- if (length <= (size_t)(lowPrefix-match))
- {
- /* match can be copied as a single segment from external dictionary */
- match = dictEnd - (lowPrefix-match);
- memmove(op, match, length); op += length;
- }
- else
- {
- /* match encompass external dictionary and current segment */
- size_t copySize = (size_t)(lowPrefix-match);
- memcpy(op, dictEnd - copySize, copySize);
- op += copySize;
- copySize = length - copySize;
- if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */
- {
- BYTE* const endOfMatch = op + copySize;
- const BYTE* copyFrom = lowPrefix;
- while (op < endOfMatch) *op++ = *copyFrom++;
- }
- else
- {
- memcpy(op, lowPrefix, copySize);
- op += copySize;
- }
- }
- continue;
- }
-
- /* copy repeated sequence */
- cpy = op + length;
- if (unlikely((op-match)<8))
- {
- const size_t dec64 = dec64table[op-match];
- op[0] = match[0];
- op[1] = match[1];
- op[2] = match[2];
- op[3] = match[3];
- match += dec32table[op-match];
- LZ4_copy4(op+4, match);
- op += 8; match -= dec64;
- } else { LZ4_copy8(op, match); op+=8; match+=8; }
-
- if (unlikely(cpy>oend-12))
- {
- if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
- if (op < oend-8)
- {
- LZ4_wildCopy(op, match, oend-8);
- match += (oend-8) - op;
- op = oend-8;
- }
- while (op<cpy) *op++ = *match++;
- }
- else
- LZ4_wildCopy(op, match, cpy);
- op=cpy; /* correction */
- }
-
- /* end of decoding */
- if (endOnInput)
- return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
- else
- return (int) (((const char*)ip)-source); /* Nb of input bytes read */
-
- /* Overflow error detected */
-_output_error:
- return (int) (-(((const char*)ip)-source))-1;
-}
-
-
-int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
-{
- return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
-}
-
-int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
-{
- return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
-}
-
-int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
-{
- return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
-}
-
-
-/* streaming decompression functions */
-
-typedef struct
-{
- const BYTE* externalDict;
- size_t extDictSize;
- const BYTE* prefixEnd;
- size_t prefixSize;
-} LZ4_streamDecode_t_internal;
-
-/*
- * If you prefer dynamic allocation methods,
- * LZ4_createStreamDecode()
- * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
- */
-LZ4_streamDecode_t* LZ4_createStreamDecode(void)
-{
- LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
- return lz4s;
-}
-
-int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
-{
- FREEMEM(LZ4_stream);
- return 0;
-}
-
-/*
- * LZ4_setStreamDecode
- * Use this function to instruct where to find the dictionary
- * This function is not necessary if previous data is still available where it was decoded.
- * Loading a size of 0 is allowed (same effect as no dictionary).
- * Return : 1 if OK, 0 if error
- */
-int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
-{
- LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
- lz4sd->prefixSize = (size_t) dictSize;
- lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
- lz4sd->externalDict = NULL;
- lz4sd->extDictSize = 0;
- return 1;
-}
-
-/*
-*_continue() :
- These decoding functions allow decompression of multiple blocks in "streaming" mode.
- Previously decoded blocks must still be available at the memory position where they were decoded.
- If it's not possible, save the relevant part of decoded data into a safe buffer,
- and indicate where it stands using LZ4_setStreamDecode()
-*/
-int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
-{
- LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
- int result;
-
- if (lz4sd->prefixEnd == (BYTE*)dest)
- {
- result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
- endOnInputSize, full, 0,
- usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
- if (result <= 0) return result;
- lz4sd->prefixSize += result;
- lz4sd->prefixEnd += result;
- }
- else
- {
- lz4sd->extDictSize = lz4sd->prefixSize;
- lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
- result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
- endOnInputSize, full, 0,
- usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
- if (result <= 0) return result;
- lz4sd->prefixSize = result;
- lz4sd->prefixEnd = (BYTE*)dest + result;
- }
-
- return result;
-}
-
-int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
-{
- LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
- int result;
-
- if (lz4sd->prefixEnd == (BYTE*)dest)
- {
- result = LZ4_decompress_generic(source, dest, 0, originalSize,
- endOnOutputSize, full, 0,
- usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
- if (result <= 0) return result;
- lz4sd->prefixSize += originalSize;
- lz4sd->prefixEnd += originalSize;
- }
- else
- {
- lz4sd->extDictSize = lz4sd->prefixSize;
- lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize;
- result = LZ4_decompress_generic(source, dest, 0, originalSize,
- endOnOutputSize, full, 0,
- usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
- if (result <= 0) return result;
- lz4sd->prefixSize = originalSize;
- lz4sd->prefixEnd = (BYTE*)dest + originalSize;
- }
-
- return result;
-}
-
-
-/*
-Advanced decoding functions :
-*_usingDict() :
- These decoding functions work the same as "_continue" ones,
- the dictionary must be explicitly provided within parameters
-*/
-
-FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
-{
- if (dictSize==0)
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
- if (dictStart+dictSize == dest)
- {
- if (dictSize >= (int)(64 KB - 1))
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
- }
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
-}
-
-int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
-{
- return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
-}
-
-int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
-{
- return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
-}
-
-/* debug function */
-int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
-{
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
-}
-
-
-/***************************************************
-* Obsolete Functions
-***************************************************/
-/* obsolete compression functions */
-int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); }
-int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); }
-int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); }
-int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); }
-int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); }
-int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); }
-
-/*
-These function names are deprecated and should no longer be used.
-They are only provided here for compatibility with older user programs.
-- LZ4_uncompress is totally equivalent to LZ4_decompress_fast
-- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
-*/
-int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); }
-int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
-
-
-/* Obsolete Streaming functions */
-
-int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
-
-static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base)
-{
- MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE);
- lz4ds->bufferStart = base;
-}
-
-int LZ4_resetStreamState(void* state, char* inputBuffer)
-{
- if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */
- LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer);
- return 0;
-}
-
-void* LZ4_create (char* inputBuffer)
-{
- void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64);
- LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer);
- return lz4ds;
-}
-
-char* LZ4_slideInputBuffer (void* LZ4_Data)
-{
- LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data;
- int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB);
- return (char*)(ctx->bufferStart + dictSize);
-}
-
-/* Obsolete streaming decompression functions */
-
-int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
-{
- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
-}
-
-int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
-{
- return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
-}
-
-#endif /* LZ4_COMMONDEFS_ONLY */
-
diff --git a/ext/lz4/lz4.h b/ext/lz4/lz4.h
deleted file mode 100644
index 3e740022..00000000
--- a/ext/lz4/lz4.h
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- LZ4 - Fast LZ compression algorithm
- Header File
- Copyright (C) 2011-2015, Yann Collet.
-
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
- distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- You can contact the author at :
- - LZ4 source repository : https://github.com/Cyan4973/lz4
- - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
-*/
-#pragma once
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/*
- * lz4.h provides block compression functions, and gives full buffer control to programmer.
- * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
- * and can let the library handle its own memory, please use lz4frame.h instead.
-*/
-
-/**************************************
-* Version
-**************************************/
-#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
-#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
-#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
-#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
-int LZ4_versionNumber (void);
-
-/**************************************
-* Tuning parameter
-**************************************/
-/*
- * LZ4_MEMORY_USAGE :
- * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
- * Increasing memory usage improves compression ratio
- * Reduced memory usage can improve speed, due to cache effect
- * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
- */
-#define LZ4_MEMORY_USAGE 14
-
-
-/**************************************
-* Simple Functions
-**************************************/
-
-int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
-int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
-
-/*
-LZ4_compress_default() :
- Compresses 'sourceSize' bytes from buffer 'source'
- into already allocated 'dest' buffer of size 'maxDestSize'.
- Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
- It also runs faster, so it's a recommended setting.
- If the function cannot compress 'source' into a more limited 'dest' budget,
- compression stops *immediately*, and the function result is zero.
- As a consequence, 'dest' content is not valid.
- This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
- sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
- maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
- return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
- or 0 if compression fails
-
-LZ4_decompress_safe() :
- compressedSize : is the precise full size of the compressed block.
- maxDecompressedSize : is the size of destination buffer, which must be already allocated.
- return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
- If destination buffer is not large enough, decoding will stop and output an error code (<0).
- If the source stream is detected malformed, the function will stop decoding and return a negative result.
- This function is protected against buffer overflow exploits, including malicious data packets.
- It never writes outside output buffer, nor reads outside input buffer.
-*/
-
-
-/**************************************
-* Advanced Functions
-**************************************/
-#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
-#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
-
-/*
-LZ4_compressBound() :
- Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
- This function is primarily useful for memory allocation purposes (destination buffer size).
- Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
- Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
- inputSize : max supported value is LZ4_MAX_INPUT_SIZE
- return : maximum output size in a "worst case" scenario
- or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
-*/
-int LZ4_compressBound(int inputSize);
-
-/*
-LZ4_compress_fast() :
- Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
- The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
- It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
- An acceleration value of "1" is the same as regular LZ4_compress_default()
- Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
-*/
-int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
-
-
-/*
-LZ4_compress_fast_extState() :
- Same compression function, just using an externally allocated memory space to store compression state.
- Use LZ4_sizeofState() to know how much memory must be allocated,
- and allocate it on 8-bytes boundaries (using malloc() typically).
- Then, provide it as 'void* state' to compression function.
-*/
-int LZ4_sizeofState(void);
-int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
-
-
-/*
-LZ4_compress_destSize() :
- Reverse the logic, by compressing as much data as possible from 'source' buffer
- into already allocated buffer 'dest' of size 'targetDestSize'.
- This function either compresses the entire 'source' content into 'dest' if it's large enough,
- or fill 'dest' buffer completely with as much data as possible from 'source'.
- *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
- New value is necessarily <= old value.
- return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
- or 0 if compression fails
-*/
-int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
-
-
-/*
-LZ4_decompress_fast() :
- originalSize : is the original and therefore uncompressed size
- return : the number of bytes read from the source buffer (in other words, the compressed size)
- If the source stream is detected malformed, the function will stop decoding and return a negative result.
- Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
- note : This function fully respect memory boundaries for properly formed compressed data.
- It is a bit faster than LZ4_decompress_safe().
- However, it does not provide any protection against intentionally modified data stream (malicious input).
- Use this function in trusted environment only (data to decode comes from a trusted source).
-*/
-int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
-
-/*
-LZ4_decompress_safe_partial() :
- This function decompress a compressed block of size 'compressedSize' at position 'source'
- into destination buffer 'dest' of size 'maxDecompressedSize'.
- The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
- reducing decompression time.
- return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
- Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
- Always control how many bytes were decoded.
- If the source stream is detected malformed, the function will stop decoding and return a negative result.
- This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
-*/
-int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
-
-
-/***********************************************
-* Streaming Compression Functions
-***********************************************/
-#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
-#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
-/*
- * LZ4_stream_t
- * information structure to track an LZ4 stream.
- * important : init this structure content before first use !
- * note : only allocated directly the structure if you are statically linking LZ4
- * If you are using liblz4 as a DLL, please use below construction methods instead.
- */
-typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
-
-/*
- * LZ4_resetStream
- * Use this function to init an allocated LZ4_stream_t structure
- */
-void LZ4_resetStream (LZ4_stream_t* streamPtr);
-
-/*
- * LZ4_createStream will allocate and initialize an LZ4_stream_t structure
- * LZ4_freeStream releases its memory.
- * In the context of a DLL (liblz4), please use these methods rather than the static struct.
- * They are more future proof, in case of a change of LZ4_stream_t size.
- */
-LZ4_stream_t* LZ4_createStream(void);
-int LZ4_freeStream (LZ4_stream_t* streamPtr);
-
-/*
- * LZ4_loadDict
- * Use this function to load a static dictionary into LZ4_stream.
- * Any previous data will be forgotten, only 'dictionary' will remain in memory.
- * Loading a size of 0 is allowed.
- * Return : dictionary size, in bytes (necessarily <= 64 KB)
- */
-int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
-
-/*
- * LZ4_compress_fast_continue
- * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
- * Important : Previous data blocks are assumed to still be present and unmodified !
- * 'dst' buffer must be already allocated.
- * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
- * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
- */
-int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
-
-/*
- * LZ4_saveDict
- * If previously compressed data block is not guaranteed to remain available at its memory location
- * save it into a safer place (char* safeBuffer)
- * Note : you don't need to call LZ4_loadDict() afterwards,
- * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
- * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
- */
-int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
-
-
-/************************************************
-* Streaming Decompression Functions
-************************************************/
-
-#define LZ4_STREAMDECODESIZE_U64 4
-#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
-typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t;
-/*
- * LZ4_streamDecode_t
- * information structure to track an LZ4 stream.
- * init this structure content using LZ4_setStreamDecode or memset() before first use !
- *
- * In the context of a DLL (liblz4) please prefer usage of construction methods below.
- * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
- * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
- * LZ4_freeStreamDecode releases its memory.
- */
-LZ4_streamDecode_t* LZ4_createStreamDecode(void);
-int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
-
-/*
- * LZ4_setStreamDecode
- * Use this function to instruct where to find the dictionary.
- * Setting a size of 0 is allowed (same effect as reset).
- * Return : 1 if OK, 0 if error
- */
-int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
-
-/*
-*_continue() :
- These decoding functions allow decompression of multiple blocks in "streaming" mode.
- Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
- In the case of a ring buffers, decoding buffer must be either :
- - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
- In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
- - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
- maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
- In which case, encoding and decoding buffers do not need to be synchronized,
- and encoding ring buffer can have any size, including small ones ( < 64 KB).
- - _At least_ 64 KB + 8 bytes + maxBlockSize.
- In which case, encoding and decoding buffers do not need to be synchronized,
- and encoding ring buffer can have any size, including larger than decoding buffer.
- Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
- and indicate where it is saved using LZ4_setStreamDecode()
-*/
-int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
-int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
-
-
-/*
-Advanced decoding functions :
-*_usingDict() :
- These decoding functions work the same as
- a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
- They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
-*/
-int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
-int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
-
-
-
-/**************************************
-* Obsolete Functions
-**************************************/
-/* Deprecate Warnings */
-/* Should these warnings messages be a problem,
- it is generally possible to disable them,
- with -Wno-deprecated-declarations for gcc
- or _CRT_SECURE_NO_WARNINGS in Visual for example.
- You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
-#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
-# define LZ4_DEPRECATE_WARNING_DEFBLOCK
-# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
-# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
-# elif (LZ4_GCC_VERSION >= 301)
-# define LZ4_DEPRECATED(message) __attribute__((deprecated))
-# elif defined(_MSC_VER)
-# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
-# else
-# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
-# define LZ4_DEPRECATED(message)
-# endif
-#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
-
-/* Obsolete compression functions */
-/* These functions are planned to start generate warnings by r131 approximately */
-int LZ4_compress (const char* source, char* dest, int sourceSize);
-int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
-int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
-int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
-int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
-int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
-
-/* Obsolete decompression functions */
-/* These function names are completely deprecated and must no longer be used.
- They are only provided here for compatibility with older programs.
- - LZ4_uncompress is the same as LZ4_decompress_fast
- - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
- These function prototypes are now disabled; uncomment them only if you really need them.
- It is highly recommended to stop using these prototypes and migrate to maintained ones */
-/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
-/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
-
-/* Obsolete streaming functions; use new streaming interface whenever possible */
-LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
-LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
-LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer);
-LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state);
-
-/* Obsolete streaming decoding functions */
-LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
-LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
-
-
-#if defined (__cplusplus)
-}
-#endif
diff --git a/ext/miniupnpc/Changelog.txt b/ext/miniupnpc/Changelog.txt
index 078bebce..37562c6a 100644
--- a/ext/miniupnpc/Changelog.txt
+++ b/ext/miniupnpc/Changelog.txt
@@ -1,6 +1,20 @@
-$Id: Changelog.txt,v 1.223 2016/04/19 21:06:20 nanard Exp $
+$Id: Changelog.txt,v 1.229 2017/12/12 11:26:25 nanard Exp $
miniUPnP client Changelog.
+2017/12/11:
+ Fix buffer over run in minixml.c
+ Fix uninitialized variable access in upnpreplyparse.c
+
+2017/05/05:
+ Fix CVE-2017-8798 Thanks to tin/Team OSTStrom
+
+2016/11/11:
+ check strlen before memcmp in XML parsing portlistingparse.c
+ fix build under SOLARIS and CYGWIN
+
+2016/10/11:
+ Add python 3 compatibility to IGD test
+
VERSION 2.0 : released 2016/04/19
2016/01/24:
diff --git a/ext/miniupnpc/LICENSE b/ext/miniupnpc/LICENSE
index cb5a0604..08167337 100644
--- a/ext/miniupnpc/LICENSE
+++ b/ext/miniupnpc/LICENSE
@@ -1,5 +1,5 @@
MiniUPnPc
-Copyright (c) 2005-2015, Thomas BERNARD
+Copyright (c) 2005-2016, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/ext/miniupnpc/MANIFEST.in b/ext/miniupnpc/MANIFEST.in
deleted file mode 100644
index 54b86f95..00000000
--- a/ext/miniupnpc/MANIFEST.in
+++ /dev/null
@@ -1,5 +0,0 @@
-include README
-include miniupnpcmodule.c
-include setup.py
-include *.h
-include libminiupnpc.a
diff --git a/ext/miniupnpc/README b/ext/miniupnpc/README
index 91535dbc..0d3b8054 100644
--- a/ext/miniupnpc/README
+++ b/ext/miniupnpc/README
@@ -1,9 +1,8 @@
Project: miniupnp
-Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+Project web page: http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
github: https://github.com/miniupnp/miniupnp
-freecode: http://freecode.com/projects/miniupnp
Author: Thomas Bernard
-Copyright (c) 2005-2016 Thomas Bernard
+Copyright (c) 2005-2017 Thomas Bernard
This software is subject to the conditions detailed in the
LICENSE file provided within this distribution.
@@ -58,7 +57,7 @@ If you are using libminiupnpc in your application, please
send me an email !
For any question, you can use the web forum :
-http://miniupnp.tuxfamily.org/forum/
+https://miniupnp.tuxfamily.org/forum/
Bugs should be reported on github :
https://github.com/miniupnp/miniupnp/issues
diff --git a/ext/miniupnpc/apiversions.txt b/ext/miniupnpc/apiversions.txt
deleted file mode 100644
index 9464a867..00000000
--- a/ext/miniupnpc/apiversions.txt
+++ /dev/null
@@ -1,172 +0,0 @@
-$Id: apiversions.txt,v 1.9 2016/01/24 17:24:36 nanard Exp $
-
-Differences in API between miniUPnPc versions
-
-API version 16
- added "status_code" argument to getHTTPResponse(), miniwget() and miniwget_getaddr()
- updated macro :
- #define MINIUPNPC_API_VERSION 16
-
-API version 15
- changed "sameport" argument of upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice()
- to "localport". When 0 or 1, behaviour is not changed, but it can take
- any other value between 2 and 65535
- Existing programs should be compatible
- updated macro :
- #define MINIUPNPC_API_VERSION 15
-
-API version 14
-miniupnpc.h
- add ttl argument to upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice()
- upnpDiscoverDevices()
- getDevicesFromMiniSSDPD() :
- connectToMiniSSDPD() / disconnectFromMiniSSDPD()
- requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD()
- updated macro :
- #define MINIUPNPC_API_VERSION 14
-
-API version 13
-miniupnpc.h:
- add searchalltype param to upnpDiscoverDevices() function
- updated macro :
- #define MINIUPNPC_API_VERSION 13
-
-API version 12
-miniupnpc.h :
- add upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices()
- functions
- updated macros :
- #define MINIUPNPC_API_VERSION 12
-
-API version 11
-
-upnpreplyparse.h / portlistingparse.h :
- removed usage of sys/queue.h / bsdqueue.h
-
-miniupnpc.h:
- updated macros :
- #define MINIUPNPC_API_VERSION 11
-
-====================== miniUPnPc version 1.9 ======================
-API version 10
-
-upnpcommands.h:
- added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
-
-miniupnpc.h:
- updated macros :
- #define MINIUPNPC_VERSION "1.9"
- #define MINIUPNPC_API_VERSION 10
-
-====================== miniUPnPc version 1.8 ======================
-API version 9
-
-miniupnpc.h:
- updated macros :
- #define MINIUPNPC_VERSION "1.8"
- #define MINIUPNPC_API_VERSION 9
- added "unsigned int scope_id;" to struct UPNPDev
- added scope_id argument to GetUPNPUrls()
-
-
-
-====================== miniUPnPc version 1.7 ======================
-API version 8
-
-miniupnpc.h :
- add new macros :
- #define MINIUPNPC_VERSION "1.7"
- #define MINIUPNPC_API_VERSION 8
- add rootdescURL to struct UPNPUrls
-
-
-
-====================== miniUPnPc version 1.6 ======================
-API version 8
-
-Adding support for IPv6.
-igd_desc_parse.h :
- struct IGDdatas_service :
- add char presentationurl[MINIUPNPC_URL_MAXSIZE];
- struct IGDdatas :
- add struct IGDdatas_service IPv6FC;
-miniupnpc.h :
- new macros :
- #define UPNPDISCOVER_SUCCESS (0)
- #define UPNPDISCOVER_UNKNOWN_ERROR (-1)
- #define UPNPDISCOVER_SOCKET_ERROR (-101)
- #define UPNPDISCOVER_MEMORY_ERROR (-102)
- simpleUPnPcommand() prototype changed (but is normaly not used by API users)
- add arguments ipv6 and error to upnpDiscover() :
- struct UPNPDev *
- upnpDiscover(int delay, const char * multicastif,
- const char * minissdpdsock, int sameport,
- int ipv6,
- int * error);
- add controlURL_6FC member to struct UPNPUrls :
- struct UPNPUrls {
- char * controlURL;
- char * ipcondescURL;
- char * controlURL_CIF;
- char * controlURL_6FC;
- };
-
-upnpcommands.h :
- add leaseDuration argument to UPNP_AddPortMapping()
- add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
- add UPNP_GetListOfPortMappings() function (IGDv2)
- add IGDv2 IPv6 related functions :
- UPNP_GetFirewallStatus()
- UPNP_GetOutboundPinholeTimeout()
- UPNP_AddPinhole()
- UPNP_UpdatePinhole()
- UPNP_DeletePinhole()
- UPNP_CheckPinholeWorking()
- UPNP_GetPinholePackets()
-
-
-
-====================== miniUPnPc version 1.5 ======================
-API version 5
-
-new function :
-int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
-new macro in upnpcommands.h :
-#define UPNPCOMMAND_HTTP_ERROR
-
-====================== miniUPnPc version 1.4 ======================
-Same API as version 1.3
-
-====================== miniUPnPc version 1.3 ======================
-API version 4
-
-Use UNSIGNED_INTEGER type for
-UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
-UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
-Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
-
-====================== miniUPnPc version 1.2 ======================
-API version 3
-
-added sameport argument to upnpDiscover()
-struct UPNPDev *
-upnpDiscover(int delay, const char * multicastif,
- const char * minissdpdsock, int sameport);
-
-====================== miniUPnPc Version 1.1 ======================
-Same API as 1.0
-
-
-====================== miniUPnPc Version 1.0 ======================
-API version 2
-
-
-struct UPNPDev {
- struct UPNPDev * pNext;
- char * descURL;
- char * st;
- char buffer[2];
-};
-struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
- const char * minissdpdsock);
-
diff --git a/ext/miniupnpc/connecthostport.c b/ext/miniupnpc/connecthostport.c
index 854203e0..aed62c76 100644
--- a/ext/miniupnpc/connecthostport.c
+++ b/ext/miniupnpc/connecthostport.c
@@ -1,12 +1,10 @@
-/* $Id: connecthostport.c,v 1.15 2015/10/09 16:26:19 nanard Exp $ */
+/* $Id: connecthostport.c,v 1.17 2017/04/21 09:58:30 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2010-2015 Thomas Bernard
+ * Copyright (c) 2010-2017 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
-#define _CRT_SECURE_NO_WARNINGS
-
/* use getaddrinfo() or gethostbyname()
* uncomment the following line in order to use gethostbyname() */
#ifdef NO_GETADDRINFO
@@ -38,15 +36,13 @@
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
* during the connect() call */
#define MINIUPNPC_IGNORE_EINTR
-#ifndef USE_GETHOSTBYNAME
#include <sys/socket.h>
#include <sys/select.h>
-#endif /* #ifndef USE_GETHOSTBYNAME */
#endif /* #else _WIN32 */
/* definition of PRINT_SOCKET_ERROR */
#ifdef _WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
@@ -102,13 +98,13 @@ int connecthostport(const char * host, unsigned short port,
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
- PRINT_SOCKET_ERROR("setsockopt");
+ PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
- PRINT_SOCKET_ERROR("setsockopt");
+ PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
dest.sin_family = AF_INET;
diff --git a/ext/miniupnpc/external-ip.sh b/ext/miniupnpc/external-ip.sh
deleted file mode 100755
index 965d86b2..00000000
--- a/ext/miniupnpc/external-ip.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $
-# (c) 2010 Reuben Hawkins
-upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g'
diff --git a/ext/miniupnpc/minihttptestserver.c b/ext/miniupnpc/minihttptestserver.c
deleted file mode 100644
index 6663bc08..00000000
--- a/ext/miniupnpc/minihttptestserver.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/* $Id: minihttptestserver.c,v 1.19 2015/11/17 09:07:17 nanard Exp $ */
-/* Project : miniUPnP
- * Author : Thomas Bernard
- * Copyright (c) 2011-2015 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <signal.h>
-#include <time.h>
-#include <errno.h>
-
-#ifndef INADDR_LOOPBACK
-#define INADDR_LOOPBACK 0x7f000001
-#endif
-
-#define CRAP_LENGTH (2048)
-
-volatile sig_atomic_t quit = 0;
-volatile sig_atomic_t child_to_wait_for = 0;
-
-/**
- * signal handler for SIGCHLD (child status has changed)
- */
-void handle_signal_chld(int sig)
-{
- (void)sig;
- /* printf("handle_signal_chld(%d)\n", sig); */
- ++child_to_wait_for;
-}
-
-/**
- * signal handler for SIGINT (CRTL C)
- */
-void handle_signal_int(int sig)
-{
- (void)sig;
- /* printf("handle_signal_int(%d)\n", sig); */
- quit = 1;
-}
-
-/**
- * build a text/plain content of the specified length
- */
-void build_content(char * p, int n)
-{
- char line_buffer[80];
- int k;
- int i = 0;
-
- while(n > 0) {
- k = snprintf(line_buffer, sizeof(line_buffer),
- "%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n",
- i, i);
- if(k != 64) {
- fprintf(stderr, "snprintf() returned %d in build_content()\n", k);
- }
- ++i;
- if(n >= 64) {
- memcpy(p, line_buffer, 64);
- p += 64;
- n -= 64;
- } else {
- memcpy(p, line_buffer, n);
- p += n;
- n = 0;
- }
- }
-}
-
-/**
- * build crappy content
- */
-void build_crap(char * p, int n)
-{
- static const char crap[] = "_CRAP_\r\n";
- int i;
-
- while(n > 0) {
- i = sizeof(crap) - 1;
- if(i > n)
- i = n;
- memcpy(p, crap, i);
- p += i;
- n -= i;
- }
-}
-
-/**
- * build chunked response.
- * return a malloc'ed buffer
- */
-char * build_chunked_response(int content_length, int * response_len)
-{
- char * response_buffer;
- char * content_buffer;
- int buffer_length;
- int i, n;
-
- /* allocate to have some margin */
- buffer_length = 256 + content_length + (content_length >> 4);
- response_buffer = malloc(buffer_length);
- if(response_buffer == NULL)
- return NULL;
- *response_len = snprintf(response_buffer, buffer_length,
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/plain\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n");
-
- /* build the content */
- content_buffer = malloc(content_length);
- if(content_buffer == NULL) {
- free(response_buffer);
- return NULL;
- }
- build_content(content_buffer, content_length);
-
- /* chunk it */
- i = 0;
- while(i < content_length) {
- n = (rand() % 199) + 1;
- if(i + n > content_length) {
- n = content_length - i;
- }
- /* TODO : check buffer size ! */
- *response_len += snprintf(response_buffer + *response_len,
- buffer_length - *response_len,
- "%x\r\n", n);
- memcpy(response_buffer + *response_len, content_buffer + i, n);
- *response_len += n;
- i += n;
- response_buffer[(*response_len)++] = '\r';
- response_buffer[(*response_len)++] = '\n';
- }
- /* the last chunk : "0\r\n" a empty body and then
- * the final "\r\n" */
- memcpy(response_buffer + *response_len, "0\r\n\r\n", 5);
- *response_len += 5;
- free(content_buffer);
-
- printf("resp_length=%d buffer_length=%d content_length=%d\n",
- *response_len, buffer_length, content_length);
- return response_buffer;
-}
-
-/* favicon.ico generator */
-#ifdef OLD_HEADER
-#define FAVICON_LENGTH (6 + 16 + 12 + 8 + 32 * 4)
-#else
-#define FAVICON_LENGTH (6 + 16 + 40 + 8 + 32 * 4)
-#endif
-void build_favicon_content(char * p, int n)
-{
- int i;
- if(n < FAVICON_LENGTH)
- return;
- /* header : 6 bytes */
- *p++ = 0;
- *p++ = 0;
- *p++ = 1; /* type : ICO */
- *p++ = 0;
- *p++ = 1; /* number of images in file */
- *p++ = 0;
- /* image directory (1 entry) : 16 bytes */
- *p++ = 16; /* width */
- *p++ = 16; /* height */
- *p++ = 2; /* number of colors in the palette. 0 = no palette */
- *p++ = 0; /* reserved */
- *p++ = 1; /* color planes */
- *p++ = 0; /* " */
- *p++ = 1; /* bpp */
- *p++ = 0; /* " */
-#ifdef OLD_HEADER
- *p++ = 12 + 8 + 32 * 4; /* bmp size */
-#else
- *p++ = 40 + 8 + 32 * 4; /* bmp size */
-#endif
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 6 + 16; /* bmp offset */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- /* BMP */
-#ifdef OLD_HEADER
- /* BITMAPCOREHEADER */
- *p++ = 12; /* size of this header */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 16; /* width */
- *p++ = 0; /* " */
- *p++ = 16 * 2; /* height x 2 ! */
- *p++ = 0; /* " */
- *p++ = 1; /* color planes */
- *p++ = 0; /* " */
- *p++ = 1; /* bpp */
- *p++ = 0; /* " */
-#else
- /* BITMAPINFOHEADER */
- *p++ = 40; /* size of this header */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 16; /* width */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 16 * 2; /* height x 2 ! */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 0; /* " */
- *p++ = 1; /* color planes */
- *p++ = 0; /* " */
- *p++ = 1; /* bpp */
- *p++ = 0; /* " */
- /* compression method, image size, ppm x, ppm y */
- /* colors in the palette ? */
- /* important colors */
- for(i = 4 * 6; i > 0; --i)
- *p++ = 0;
-#endif
- /* palette */
- *p++ = 0; /* b */
- *p++ = 0; /* g */
- *p++ = 0; /* r */
- *p++ = 0; /* reserved */
- *p++ = 255; /* b */
- *p++ = 255; /* g */
- *p++ = 255; /* r */
- *p++ = 0; /* reserved */
- /* pixel data */
- for(i = 16; i > 0; --i) {
- if(i & 1) {
- *p++ = 0125;
- *p++ = 0125;
- } else {
- *p++ = 0252;
- *p++ = 0252;
- }
- *p++ = 0;
- *p++ = 0;
- }
- /* Opacity MASK */
- for(i = 16 * 4; i > 0; --i) {
- *p++ = 0;
- }
-}
-
-enum modes {
- MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL, MODE_FAVICON
-};
-
-const struct {
- const enum modes mode;
- const char * text;
-} modes_array[] = {
- {MODE_CHUNKED, "chunked"},
- {MODE_ADDCRAP, "addcrap"},
- {MODE_NORMAL, "normal"},
- {MODE_FAVICON, "favicon.ico"},
- {MODE_INVALID, NULL}
-};
-
-/**
- * write the response with random behaviour !
- */
-void send_response(int c, const char * buffer, int len)
-{
- int n;
- while(len > 0) {
- n = (rand() % 99) + 1;
- if(n > len)
- n = len;
- n = write(c, buffer, n);
- if(n < 0) {
- if(errno != EINTR) {
- perror("write");
- return;
- }
- /* if errno == EINTR, try again */
- } else {
- len -= n;
- buffer += n;
- }
- usleep(10000); /* 10ms */
- }
-}
-
-/**
- * handle the HTTP connection
- */
-void handle_http_connection(int c)
-{
- char request_buffer[2048];
- int request_len = 0;
- int headers_found = 0;
- int n, i;
- char request_method[16];
- char request_uri[256];
- char http_version[16];
- char * p;
- char * response_buffer;
- int response_len;
- enum modes mode;
- int content_length = 16*1024;
-
- /* read the request */
- while(request_len < (int)sizeof(request_buffer) && !headers_found) {
- n = read(c,
- request_buffer + request_len,
- sizeof(request_buffer) - request_len);
- if(n < 0) {
- if(errno == EINTR)
- continue;
- perror("read");
- return;
- } else if(n==0) {
- /* remote host closed the connection */
- break;
- } else {
- request_len += n;
- for(i = 0; i < request_len - 3; i++) {
- if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) {
- /* found the end of headers */
- headers_found = 1;
- break;
- }
- }
- }
- }
- if(!headers_found) {
- /* error */
- printf("no HTTP header found in the request\n");
- return;
- }
- printf("headers :\n%.*s", request_len, request_buffer);
- /* the request have been received, now parse the request line */
- p = request_buffer;
- for(i = 0; i < (int)sizeof(request_method) - 1; i++) {
- if(*p == ' ' || *p == '\r')
- break;
- request_method[i] = *p;
- ++p;
- }
- request_method[i] = '\0';
- while(*p == ' ')
- p++;
- for(i = 0; i < (int)sizeof(request_uri) - 1; i++) {
- if(*p == ' ' || *p == '\r')
- break;
- request_uri[i] = *p;
- ++p;
- }
- request_uri[i] = '\0';
- while(*p == ' ')
- p++;
- for(i = 0; i < (int)sizeof(http_version) - 1; i++) {
- if(*p == ' ' || *p == '\r')
- break;
- http_version[i] = *p;
- ++p;
- }
- http_version[i] = '\0';
- printf("Method = %s, URI = %s, %s\n",
- request_method, request_uri, http_version);
- /* check if the request method is allowed */
- if(0 != strcmp(request_method, "GET")) {
- const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n"
- "Allow: GET\r\n\r\n";
- const char * pc;
- /* 405 Method Not Allowed */
- /* The response MUST include an Allow header containing a list
- * of valid methods for the requested resource. */
- n = sizeof(response405) - 1;
- pc = response405;
- while(n > 0) {
- i = write(c, pc, n);
- if(i<0) {
- if(errno != EINTR) {
- perror("write");
- return;
- }
- } else {
- n -= i;
- pc += i;
- }
- }
- return;
- }
-
- mode = MODE_INVALID;
- /* use the request URI to know what to do */
- for(i = 0; modes_array[i].mode != MODE_INVALID; i++) {
- if(strstr(request_uri, modes_array[i].text)) {
- mode = modes_array[i].mode; /* found */
- break;
- }
- }
-
- switch(mode) {
- case MODE_CHUNKED:
- response_buffer = build_chunked_response(content_length, &response_len);
- break;
- case MODE_ADDCRAP:
- response_len = content_length+256;
- response_buffer = malloc(response_len);
- if(!response_buffer)
- break;
- n = snprintf(response_buffer, response_len,
- "HTTP/1.1 200 OK\r\n"
- "Server: minihttptestserver\r\n"
- "Content-Type: text/plain\r\n"
- "Content-Length: %d\r\n"
- "\r\n", content_length);
- response_len = content_length+n+CRAP_LENGTH;
- p = realloc(response_buffer, response_len);
- if(p == NULL) {
- /* error 500 */
- free(response_buffer);
- response_buffer = NULL;
- break;
- }
- response_buffer = p;
- build_content(response_buffer + n, content_length);
- build_crap(response_buffer + n + content_length, CRAP_LENGTH);
- break;
- case MODE_FAVICON:
- content_length = FAVICON_LENGTH;
- response_len = content_length + 256;
- response_buffer = malloc(response_len);
- if(!response_buffer)
- break;
- n = snprintf(response_buffer, response_len,
- "HTTP/1.1 200 OK\r\n"
- "Server: minihttptestserver\r\n"
- "Content-Type: image/vnd.microsoft.icon\r\n"
- "Content-Length: %d\r\n"
- "\r\n", content_length);
- /* image/x-icon */
- build_favicon_content(response_buffer + n, content_length);
- response_len = content_length + n;
- break;
- default:
- response_len = content_length+256;
- response_buffer = malloc(response_len);
- if(!response_buffer)
- break;
- n = snprintf(response_buffer, response_len,
- "HTTP/1.1 200 OK\r\n"
- "Server: minihttptestserver\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n");
- response_len = content_length+n;
- p = realloc(response_buffer, response_len);
- if(p == NULL) {
- /* Error 500 */
- free(response_buffer);
- response_buffer = NULL;
- break;
- }
- response_buffer = p;
- build_content(response_buffer + n, response_len - n);
- }
-
- if(response_buffer) {
- send_response(c, response_buffer, response_len);
- free(response_buffer);
- } else {
- /* Error 500 */
- }
-}
-
-/**
- */
-int main(int argc, char * * argv) {
- int ipv6 = 0;
- int s, c, i;
- unsigned short port = 0;
- struct sockaddr_storage server_addr;
- socklen_t server_addrlen;
- struct sockaddr_storage client_addr;
- socklen_t client_addrlen;
- pid_t pid;
- int child = 0;
- int status;
- const char * expected_file_name = NULL;
- struct sigaction sa;
-
- for(i = 1; i < argc; i++) {
- if(argv[i][0] == '-') {
- switch(argv[i][1]) {
- case '6':
- ipv6 = 1;
- break;
- case 'e':
- /* write expected file ! */
- expected_file_name = argv[++i];
- break;
- case 'p':
- /* port */
- if(++i < argc) {
- port = (unsigned short)atoi(argv[i]);
- }
- break;
- default:
- fprintf(stderr, "unknown command line switch '%s'\n", argv[i]);
- }
- } else {
- fprintf(stderr, "unkown command line argument '%s'\n", argv[i]);
- }
- }
-
- srand(time(NULL));
-
- memset(&sa, 0, sizeof(struct sigaction));
-
- /*signal(SIGCHLD, handle_signal_chld);*/
- sa.sa_handler = handle_signal_chld;
- if(sigaction(SIGCHLD, &sa, NULL) < 0) {
- perror("sigaction");
- return 1;
- }
- /*signal(SIGINT, handle_signal_int);*/
- sa.sa_handler = handle_signal_int;
- if(sigaction(SIGINT, &sa, NULL) < 0) {
- perror("sigaction");
- return 1;
- }
-
- s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
- if(s < 0) {
- perror("socket");
- return 1;
- }
- memset(&server_addr, 0, sizeof(struct sockaddr_storage));
- memset(&client_addr, 0, sizeof(struct sockaddr_storage));
- if(ipv6) {
- struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
- addr->sin6_family = AF_INET6;
- addr->sin6_port = htons(port);
- addr->sin6_addr = in6addr_loopback;
- } else {
- struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr;
- addr->sin_family = AF_INET;
- addr->sin_port = htons(port);
- addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- }
- if(bind(s, (struct sockaddr *)&server_addr,
- ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) {
- perror("bind");
- return 1;
- }
- if(listen(s, 5) < 0) {
- perror("listen");
- }
- if(port == 0) {
- server_addrlen = sizeof(struct sockaddr_storage);
- if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) {
- perror("getsockname");
- return 1;
- }
- if(ipv6) {
- struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr;
- port = ntohs(addr->sin6_port);
- } else {
- struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr;
- port = ntohs(addr->sin_port);
- }
- printf("Listening on port %hu\n", port);
- fflush(stdout);
- }
-
- /* write expected file */
- if(expected_file_name) {
- FILE * f;
- f = fopen(expected_file_name, "wb");
- if(f) {
- char * buffer;
- buffer = malloc(16*1024);
- if(buffer == NULL) {
- fprintf(stderr, "memory allocation error\n");
- } else {
- build_content(buffer, 16*1024);
- i = fwrite(buffer, 1, 16*1024, f);
- if(i != 16*1024) {
- fprintf(stderr, "error writing to file %s : %dbytes written (out of %d)\n", expected_file_name, i, 16*1024);
- }
- free(buffer);
- }
- fclose(f);
- } else {
- fprintf(stderr, "error opening file %s for writing\n", expected_file_name);
- }
- }
-
- /* fork() loop */
- while(!child && !quit) {
- while(child_to_wait_for > 0) {
- pid = wait(&status);
- if(pid < 0) {
- perror("wait");
- } else {
- printf("child(%d) terminated with status %d\n", pid, status);
- }
- --child_to_wait_for;
- }
- client_addrlen = sizeof(struct sockaddr_storage);
- c = accept(s, (struct sockaddr *)&client_addr,
- &client_addrlen);
- if(c < 0) {
- if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
- continue;
- perror("accept");
- return 1;
- }
- printf("accept...\n");
- pid = fork();
- if(pid < 0) {
- perror("fork");
- return 1;
- } else if(pid == 0) {
- /* child */
- child = 1;
- close(s);
- s = -1;
- handle_http_connection(c);
- }
- close(c);
- }
- if(s >= 0) {
- close(s);
- s = -1;
- }
- if(!child) {
- while(child_to_wait_for > 0) {
- pid = wait(&status);
- if(pid < 0) {
- perror("wait");
- } else {
- printf("child(%d) terminated with status %d\n", pid, status);
- }
- --child_to_wait_for;
- }
- printf("Bye...\n");
- }
- return 0;
-}
-
diff --git a/ext/miniupnpc/minisoap.c b/ext/miniupnpc/minisoap.c
index e2efd8f8..5b8c0784 100644
--- a/ext/miniupnpc/minisoap.c
+++ b/ext/miniupnpc/minisoap.c
@@ -1,5 +1,4 @@
-#define _CRT_SECURE_NO_WARNINGS
-/* $Id: minisoap.c,v 1.24 2015/10/26 17:05:07 nanard Exp $ */
+/* $Id: minisoap.c,v 1.25 2017/04/21 10:03:24 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2015 Thomas Bernard
@@ -20,17 +19,24 @@
#include <sys/socket.h>
#endif
#include "minisoap.h"
+
#ifdef _WIN32
#define OS_STRING "Win32"
#define MINIUPNPC_VERSION_STRING "2.0"
#define UPNP_VERSION_STRING "UPnP/1.1"
#endif
+#ifdef __ANDROID__
+#define OS_STRING "Android"
+#define MINIUPNPC_VERSION_STRING "2.0"
+#define UPNP_VERSION_STRING "UPnP/1.1"
+#endif
+
/* only for malloc */
#include <stdlib.h>
#ifdef _WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
@@ -124,3 +130,5 @@ int soapPostSubmit(int fd,
#endif
return httpWrite(fd, body, bodysize, headerbuf, headerssize);
}
+
+
diff --git a/ext/miniupnpc/minissdpc.c b/ext/miniupnpc/minissdpc.c
index 0f7271e2..3479de8e 100644
--- a/ext/miniupnpc/minissdpc.c
+++ b/ext/miniupnpc/minissdpc.c
@@ -1,11 +1,9 @@
-#define _CRT_SECURE_NO_WARNINGS
-
-/* $Id: minissdpc.c,v 1.31 2016/01/19 09:56:46 nanard Exp $ */
+/* $Id: minissdpc.c,v 1.35 2017/11/02 15:34:36 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
- * copyright (c) 2005-2015 Thomas Bernard
+ * copyright (c) 2005-2017 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
/*#include <syslog.h>*/
@@ -13,6 +11,9 @@
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
+#if defined (__NetBSD__)
+#include <net/if.h>
+#endif
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
#ifdef _WIN32
#include <winsock2.h>
@@ -61,7 +62,7 @@ struct sockaddr_un {
#endif
#ifdef _WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
@@ -72,6 +73,9 @@ struct sockaddr_un {
#if !defined(HAS_IP_MREQN) && !defined(_WIN32)
#include <sys/ioctl.h>
+#if defined(__sun)
+#include <sys/sockio.h>
+#endif
#endif
#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN)
@@ -168,7 +172,7 @@ connectToMiniSSDPD(const char * socketpath)
{
int s;
struct sockaddr_un addr;
-#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
+#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun)
struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
@@ -179,23 +183,25 @@ connectToMiniSSDPD(const char * socketpath)
perror("socket(unix)");
return MINISSDPC_SOCKET_ERROR;
}
-#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
+#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun)
/* setting a 3 seconds timeout */
+ /* not supported for AF_UNIX sockets under Solaris */
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
- perror("setsockopt");
+ perror("setsockopt SO_RCVTIMEO unix");
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
{
- perror("setsockopt");
+ perror("setsockopt SO_SNDTIMEO unix");
}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
if(!socketpath)
socketpath = "/var/run/minissdpd.sock";
+ memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
/* TODO : check if we need to handle the EINTR */
@@ -497,6 +503,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
unsigned long _ttl = (unsigned long)ttl;
#endif
int linklocal = 1;
+ int sentok;
if(error)
*error = MINISSDPC_UNKNOWN_ERROR;
@@ -607,14 +614,27 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
return NULL;
}
+ if(ipv6) {
#ifdef _WIN32
- if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
+ DWORD mcastHops = ttl;
+ if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0)
#else /* _WIN32 */
- if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
+ int mcastHops = ttl;
+ if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0)
#endif /* _WIN32 */
- {
- /* not a fatal error */
- PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
+ {
+ PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)");
+ }
+ } else {
+#ifdef _WIN32
+ if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
+#else /* _WIN32 */
+ if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
+#endif /* _WIN32 */
+ {
+ /* not a fatal error */
+ PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
+ }
}
if(multicastif)
@@ -627,7 +647,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
{
- PRINT_SOCKET_ERROR("setsockopt");
+ PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF");
}
#else
#ifdef DEBUG
@@ -642,7 +662,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
{
- PRINT_SOCKET_ERROR("setsockopt");
+ PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
}
} else {
#ifdef HAS_IP_MREQN
@@ -652,7 +672,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
reqn.imr_ifindex = if_nametoindex(multicastif);
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
{
- PRINT_SOCKET_ERROR("setsockopt");
+ PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
}
#elif !defined(_WIN32)
struct ifreq ifr;
@@ -666,7 +686,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
{
- PRINT_SOCKET_ERROR("setsockopt");
+ PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
}
#else /* _WIN32 */
#ifdef DEBUG
@@ -699,6 +719,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
}
/* receiving SSDP response packet */
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
+ sentok = 0;
/* sending the SSDP M-SEARCH packet */
n = snprintf(bufr, sizeof(bufr),
MSearchMsgFmt,
@@ -742,7 +763,8 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
if(error)
*error = MINISSDPC_SOCKET_ERROR;
PRINT_SOCKET_ERROR("sendto");
- break;
+ } else {
+ sentok = 1;
}
#else /* #ifdef NO_GETADDRINFO */
memset(&hints, 0, sizeof(hints));
@@ -774,19 +796,20 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
#endif
PRINT_SOCKET_ERROR("sendto");
continue;
+ } else {
+ sentok = 1;
}
}
freeaddrinfo(servinfo);
- if(n < 0) {
+ if(!sentok) {
if(error)
*error = MINISSDPC_SOCKET_ERROR;
- break;
}
#endif /* #ifdef NO_GETADDRINFO */
/* Waiting for SSDP REPLY packet to M-SEARCH
* if searchalltypes is set, enter the loop only
* when the last deviceType is reached */
- if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do {
+ if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do {
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
if (n < 0) {
/* error */
diff --git a/ext/miniupnpc/miniupnpc.c b/ext/miniupnpc/miniupnpc.c
index 68d562fa..2dc5c95c 100644
--- a/ext/miniupnpc/miniupnpc.c
+++ b/ext/miniupnpc/miniupnpc.c
@@ -1,5 +1,3 @@
-#define _CRT_SECURE_NO_WARNINGS
-
/* $Id: miniupnpc.c,v 1.149 2016/02/09 09:50:46 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
diff --git a/ext/miniupnpc/miniupnpc.h b/ext/miniupnpc/miniupnpc.h
index 0b5b4732..4a805b11 100644
--- a/ext/miniupnpc/miniupnpc.h
+++ b/ext/miniupnpc/miniupnpc.h
@@ -19,7 +19,7 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
-#define MINIUPNPC_VERSION "2.0"
+#define MINIUPNPC_VERSION "2.0.20171212"
#define MINIUPNPC_API_VERSION 16
/* Source port:
diff --git a/ext/miniupnpc/miniupnpcmodule.c b/ext/miniupnpc/miniupnpcmodule.c
index a5bdce44..bbff0738 100644
--- a/ext/miniupnpc/miniupnpcmodule.c
+++ b/ext/miniupnpc/miniupnpcmodule.c
@@ -1,8 +1,8 @@
-/* $Id: miniupnpcmodule.c,v 1.29 2015/10/26 17:01:30 nanard Exp $*/
+/* $Id: miniupnpcmodule.c,v 1.31 2017/11/02 15:37:28 nanard Exp $*/
/* Project : miniupnp
* Author : Thomas BERNARD
* website : http://miniupnp.tuxfamily.org/
- * copyright (c) 2007-2014 Thomas Bernard
+ * copyright (c) 2007-2016 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <Python.h>
@@ -12,6 +12,10 @@
#include "upnpcommands.h"
#include "upnperrors.h"
+#ifdef _WIN32
+#include <winsock2.h>
+#endif
+
/* for compatibility with Python < 2.4 */
#ifndef Py_RETURN_NONE
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
@@ -303,7 +307,7 @@ UPnP_addportmapping(UPnPObject *self, PyObject *args)
const char * remoteHost;
const char * leaseDuration = "0";
int r;
- if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
+ if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto,
&host, &iPort, &desc, &remoteHost))
return NULL;
Py_BEGIN_ALLOW_THREADS
@@ -345,7 +349,7 @@ UPnP_addanyportmapping(UPnPObject *self, PyObject *args)
const char * remoteHost;
const char * leaseDuration = "0";
int r;
- if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
+ if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
return NULL;
Py_BEGIN_ALLOW_THREADS
sprintf(extPort, "%hu", ePort);
@@ -669,6 +673,10 @@ initminiupnpc(void)
PyObject* m;
#ifdef _WIN32
+ /* initialize Winsock. */
+ WSADATA wsaData;
+ int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+
UPnPType.tp_new = PyType_GenericNew;
#endif
if (PyType_Ready(&UPnPType) < 0)
diff --git a/ext/miniupnpc/miniwget.c b/ext/miniupnpc/miniwget.c
index 1af106d0..e23f11e3 100644
--- a/ext/miniupnpc/miniwget.c
+++ b/ext/miniupnpc/miniwget.c
@@ -1,10 +1,8 @@
-#define _CRT_SECURE_NO_WARNINGS
-
-/* $Id: miniwget.c,v 1.75 2016/01/24 17:24:36 nanard Exp $ */
+/* $Id: miniwget.c,v 1.77 2017/05/09 10:04:57 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
- * Copyright (c) 2005-2016 Thomas Bernard
+ * Copyright (c) 2005-2017 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -56,6 +54,12 @@
#define UPNP_VERSION_STRING "UPnP/1.1"
#endif
+#ifdef __ANDROID__
+#define OS_STRING "Android"
+#define MINIUPNPC_VERSION_STRING "2.0"
+#define UPNP_VERSION_STRING "UPnP/1.1"
+#endif
+
#include "miniwget.h"
#include "connecthostport.h"
#include "receivedata.h"
@@ -89,8 +93,10 @@ getHTTPResponse(int s, int * size, int * status_code)
unsigned int content_buf_used = 0;
char chunksize_buf[32];
unsigned int chunksize_buf_index;
+#ifdef DEBUG
char * reason_phrase = NULL;
int reason_phrase_len = 0;
+#endif
if(status_code) *status_code = -1;
header_buf = malloc(header_buf_len);
@@ -115,7 +121,7 @@ getHTTPResponse(int s, int * size, int * status_code)
chunksize_buf[0] = '\0';
chunksize_buf_index = 0;
- while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
+ while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0)
{
if(endofheaders == 0)
{
@@ -187,8 +193,10 @@ getHTTPResponse(int s, int * size, int * status_code)
*status_code = atoi(header_buf + sp + 1);
else
{
+#ifdef DEBUG
reason_phrase = header_buf + sp + 1;
reason_phrase_len = i - sp - 1;
+#endif
break;
}
}
@@ -286,11 +294,12 @@ getHTTPResponse(int s, int * size, int * status_code)
goto end_of_stream;
}
}
- bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
+ /* it is guaranteed that (n >= i) */
+ bytestocopy = (chunksize < (unsigned int)(n - i))?chunksize:(unsigned int)(n - i);
if((content_buf_used + bytestocopy) > content_buf_len)
{
char * tmp;
- if(content_length >= (int)(content_buf_used + bytestocopy)) {
+ if((content_length >= 0) && ((unsigned int)content_length >= (content_buf_used + bytestocopy))) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + bytestocopy;
@@ -315,14 +324,15 @@ getHTTPResponse(int s, int * size, int * status_code)
{
/* not chunked */
if(content_length > 0
- && (int)(content_buf_used + n) > content_length) {
+ && (content_buf_used + n) > (unsigned int)content_length) {
/* skipping additional bytes */
n = content_length - content_buf_used;
}
if(content_buf_used + n > content_buf_len)
{
char * tmp;
- if(content_length >= (int)(content_buf_used + n)) {
+ if(content_length >= 0
+ && (unsigned int)content_length >= (content_buf_used + n)) {
content_buf_len = content_length;
} else {
content_buf_len = content_buf_used + n;
@@ -342,7 +352,7 @@ getHTTPResponse(int s, int * size, int * status_code)
}
}
/* use the Content-Length header value if available */
- if(content_length > 0 && (int)content_buf_used >= content_length)
+ if(content_length > 0 && content_buf_used >= (unsigned int)content_length)
{
#ifdef DEBUG
printf("End of HTTP content\n");
diff --git a/ext/miniupnpc/minixml.c b/ext/miniupnpc/minixml.c
index 5c79b3c9..935ec443 100644
--- a/ext/miniupnpc/minixml.c
+++ b/ext/miniupnpc/minixml.c
@@ -1,11 +1,11 @@
-#define _CRT_SECURE_NO_WARNINGS
-/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */
-/* minixml.c : the minimum size a xml parser can be ! */
+/* $Id: minixml.c,v 1.12 2017/12/12 11:17:40 nanard Exp $ */
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * minixml.c : the minimum size a xml parser can be ! */
/* Project : miniupnp
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
-Copyright (c) 2005-2014, Thomas BERNARD
+Copyright (c) 2005-2017, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -162,7 +162,8 @@ static void parseelt(struct xmlparser * p)
if (p->xml >= p->xmlend)
return;
}
- if(memcmp(p->xml, "<![CDATA[", 9) == 0)
+ /* CDATA are at least 9 + 3 characters long : <![CDATA[ ]]> */
+ if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "<![CDATA[", 9) == 0))
{
/* CDATA handling */
p->xml += 9;
diff --git a/ext/miniupnpc/minixmlvalid.c b/ext/miniupnpc/minixmlvalid.c
index a86beba8..dad14881 100644
--- a/ext/miniupnpc/minixmlvalid.c
+++ b/ext/miniupnpc/minixmlvalid.c
@@ -1,4 +1,3 @@
-#define _CRT_SECURE_NO_WARNINGS
/* $Id: minixmlvalid.c,v 1.7 2015/07/15 12:41:15 nanard Exp $ */
/* MiniUPnP Project
* http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
diff --git a/ext/miniupnpc/portlistingparse.c b/ext/miniupnpc/portlistingparse.c
index 0e092780..d1954f59 100644
--- a/ext/miniupnpc/portlistingparse.c
+++ b/ext/miniupnpc/portlistingparse.c
@@ -1,7 +1,7 @@
-/* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */
+/* $Id: portlistingparse.c,v 1.10 2016/12/16 08:53:21 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2011-2015 Thomas Bernard
+ * (c) 2011-2016 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <string.h>
@@ -55,7 +55,7 @@ startelt(void * d, const char * name, int l)
pdata->curelt = PortMappingEltNone;
for(i = 0; elements[i].str; i++)
{
- if(memcmp(name, elements[i].str, l) == 0)
+ if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0)
{
pdata->curelt = elements[i].code;
break;
diff --git a/ext/miniupnpc/pymoduletest.py b/ext/miniupnpc/pymoduletest.py
deleted file mode 100644
index 9fddd9c2..00000000
--- a/ext/miniupnpc/pymoduletest.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#! /usr/bin/python
-# vim: tabstop=2 shiftwidth=2 expandtab
-# MiniUPnP project
-# Author : Thomas Bernard
-# This Sample code is public domain.
-# website : http://miniupnp.tuxfamily.org/
-
-# import the python miniupnpc module
-import miniupnpc
-import sys
-
-try:
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument('-m', '--multicastif')
- parser.add_argument('-p', '--minissdpdsocket')
- parser.add_argument('-d', '--discoverdelay', type=int, default=200)
- parser.add_argument('-z', '--localport', type=int, default=0)
- # create the object
- u = miniupnpc.UPnP(**vars(parser.parse_args()))
-except:
- print 'argparse not available'
- i = 1
- multicastif = None
- minissdpdsocket = None
- discoverdelay = 200
- localport = 0
- while i < len(sys.argv):
- print sys.argv[i]
- if sys.argv[i] == '-m' or sys.argv[i] == '--multicastif':
- multicastif = sys.argv[i+1]
- elif sys.argv[i] == '-p' or sys.argv[i] == '--minissdpdsocket':
- minissdpdsocket = sys.argv[i+1]
- elif sys.argv[i] == '-d' or sys.argv[i] == '--discoverdelay':
- discoverdelay = int(sys.argv[i+1])
- elif sys.argv[i] == '-z' or sys.argv[i] == '--localport':
- localport = int(sys.argv[i+1])
- else:
- raise Exception('invalid argument %s' % sys.argv[i])
- i += 2
- # create the object
- u = miniupnpc.UPnP(multicastif, minissdpdsocket, discoverdelay, localport)
-
-print 'inital(default) values :'
-print ' discoverdelay', u.discoverdelay
-print ' lanaddr', u.lanaddr
-print ' multicastif', u.multicastif
-print ' minissdpdsocket', u.minissdpdsocket
-#u.minissdpdsocket = '../minissdpd/minissdpd.sock'
-# discovery process, it usualy takes several seconds (2 seconds or more)
-print 'Discovering... delay=%ums' % u.discoverdelay
-print u.discover(), 'device(s) detected'
-# select an igd
-try:
- u.selectigd()
-except Exception, e:
- print 'Exception :', e
- sys.exit(1)
-# display information about the IGD and the internet connection
-print 'local ip address :', u.lanaddr
-print 'external ip address :', u.externalipaddress()
-print u.statusinfo(), u.connectiontype()
-print 'total bytes : sent', u.totalbytesent(), 'received', u.totalbytereceived()
-print 'total packets : sent', u.totalpacketsent(), 'received', u.totalpacketreceived()
-
-#print u.addportmapping(64000, 'TCP',
-# '192.168.1.166', 63000, 'port mapping test', '')
-#print u.deleteportmapping(64000, 'TCP')
-
-port = 0
-proto = 'UDP'
-# list the redirections :
-i = 0
-while True:
- p = u.getgenericportmapping(i)
- if p==None:
- break
- print i, p
- (port, proto, (ihost,iport), desc, c, d, e) = p
- #print port, desc
- i = i + 1
-
-print u.getspecificportmapping(port, proto)
-try:
- print u.getportmappingnumberofentries()
-except Exception, e:
- print 'GetPortMappingNumberOfEntries() is not supported :', e
-
diff --git a/ext/miniupnpc/receivedata.c b/ext/miniupnpc/receivedata.c
index ef85a3db..5dbd227b 100644
--- a/ext/miniupnpc/receivedata.c
+++ b/ext/miniupnpc/receivedata.c
@@ -1,4 +1,4 @@
-/* $Id: receivedata.c,v 1.7 2015/11/09 21:51:41 nanard Exp $ */
+/* $Id: receivedata.c,v 1.8 2017/04/21 10:16:45 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
@@ -28,7 +28,7 @@
#endif /* _WIN32 */
#ifdef _WIN32
-#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError());
#else
#define PRINT_SOCKET_ERROR(x) perror(x)
#endif
diff --git a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values
deleted file mode 100644
index cf422218..00000000
--- a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.values
+++ /dev/null
@@ -1,14 +0,0 @@
-# values for linksys_WAG200G_desc.xml
-
-CIF:
- servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
- controlurl = /upnp/control/WANCommonIFC1
- eventsuburl = /upnp/event/WANCommonIFC1
- scpdurl = /cmnicfg.xml
-
-first:
- servicetype = urn:schemas-upnp-org:service:WANPPPConnection:1
- controlurl = /upnp/control/WANPPPConn1
- eventsuburl = /upnp/event/WANPPPConn1
- scpdurl = /pppcfg.xml
-
diff --git a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml b/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml
deleted file mode 100644
index d428d73b..00000000
--- a/ext/miniupnpc/testdesc/linksys_WAG200G_desc.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0"?>
-<root xmlns="urn:schemas-upnp-org:device-1-0">
-<specVersion>
-<major>1</major>
-<minor>0</minor>
-</specVersion>
-<URLBase>http://192.168.1.1:49152</URLBase>
-<device>
-<deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType>
-<friendlyName>LINKSYS WAG200G Gateway</friendlyName>
-<manufacturer>LINKSYS</manufacturer>
-<manufacturerURL>http://www.linksys.com</manufacturerURL>
-<modelDescription>LINKSYS WAG200G Gateway</modelDescription>
-<modelName>Wireless-G ADSL Home Gateway</modelName>
-<modelNumber>WAG200G</modelNumber>
-<modelURL>http://www.linksys.com</modelURL>
-<serialNumber>123456789</serialNumber>
-<UDN>uuid:8ca2eb37-1dd2-11b2-86f1-001a709b5aa8</UDN>
-<UPC>WAG200G</UPC>
-<serviceList>
-<service>
-<serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>
-<controlURL>/upnp/control/L3Forwarding1</controlURL>
-<eventSubURL>/upnp/event/L3Forwarding1</eventSubURL>
-<SCPDURL>/l3frwd.xml</SCPDURL>
-</service>
-</serviceList>
-<deviceList>
-<device>
-<deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>
-<friendlyName>WANDevice</friendlyName>
-<manufacturer>LINKSYS</manufacturer>
-<manufacturerURL>http://www.linksys.com/</manufacturerURL>
-<modelDescription>Residential Gateway</modelDescription>
-<modelName>Internet Connection Sharing</modelName>
-<modelNumber>1</modelNumber>
-<modelURL>http://www.linksys.com/</modelURL>
-<serialNumber>0000001</serialNumber>
-<UDN>uuid:8ca2eb36-1dd2-11b2-86f1-001a709b5aa8</UDN>
-<UPC>WAG200G</UPC>
-<serviceList>
-<service>
-<serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
-<controlURL>/upnp/control/WANCommonIFC1</controlURL>
-<eventSubURL>/upnp/event/WANCommonIFC1</eventSubURL>
-<SCPDURL>/cmnicfg.xml</SCPDURL>
-</service>
-</serviceList>
-<deviceList>
-<device>
-<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
-<friendlyName>WANConnectionDevice</friendlyName>
-<manufacturer>LINKSYS</manufacturer>
-<manufacturerURL>http://www.linksys.com/</manufacturerURL>
-<modelDescription>Residential Gateway</modelDescription>
-<modelName>Internet Connection Sharing</modelName>
-<modelNumber>1</modelNumber>
-<modelURL>http://www.linksys.com/</modelURL>
-<serialNumber>0000001</serialNumber>
-<UDN>uuid:8ca2eb37-1dd2-11b2-86f0-001a709b5aa8</UDN>
-<UPC>WAG200G</UPC>
-<serviceList>
-<service>
-<serviceType>urn:schemas-upnp-org:service:WANEthernetLinkConfig:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:WANEthLinkC1</serviceId>
-<controlURL>/upnp/control/WANEthLinkC1</controlURL>
-<eventSubURL>/upnp/event/WANEthLinkC1</eventSubURL>
-<SCPDURL>/wanelcfg.xml</SCPDURL>
-</service>
-<service>
-<serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:WANPPPConn1</serviceId>
-<controlURL>/upnp/control/WANPPPConn1</controlURL>
-<eventSubURL>/upnp/event/WANPPPConn1</eventSubURL>
-<SCPDURL>/pppcfg.xml</SCPDURL>
-</service>
-</serviceList>
-</device>
-</deviceList>
-</device>
-<device>
-<deviceType>urn:schemas-upnp-org:device:LANDevice:1</deviceType>
-<friendlyName>LANDevice</friendlyName>
-<manufacturer>LINKSYS</manufacturer>
-<manufacturerURL>http://www.linksys.com/</manufacturerURL>
-<modelDescription>Residential Gateway</modelDescription>
-<modelName>Residential Gateway</modelName>
-<modelNumber>1</modelNumber>
-<modelURL>http://www.linksys.com/</modelURL>
-<serialNumber>0000001</serialNumber>
-<UDN>uuid:8ca2eb36-1dd2-11b2-86f0-001a709b5aa
-8</UDN>
-<UPC>WAG200G</UPC>
-<serviceList>
-<service>
-<serviceType>urn:schemas-upnp-org:service:LANHostConfigManagement:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:LANHostCfg1</serviceId>
-<controlURL>/upnp/control/LANHostCfg1</controlURL>
-<eventSubURL>/upnp/event/LANHostCfg1</eventSubURL>
-<SCPDURL>/lanhostc.xml</SCPDURL>
-</service>
-</serviceList>
-</device>
-</deviceList>
-<presentationURL>http://192.168.1.1/index.htm</presentationURL>
-</device>
-</root>
-
diff --git a/ext/miniupnpc/testdesc/new_LiveBox_desc.values b/ext/miniupnpc/testdesc/new_LiveBox_desc.values
deleted file mode 100644
index c55552e5..00000000
--- a/ext/miniupnpc/testdesc/new_LiveBox_desc.values
+++ /dev/null
@@ -1,20 +0,0 @@
-# values for new_LiveBox_desc.xml
-
-CIF:
- servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
- controlurl = /87895a19/upnp/control/WANCommonIFC1
- eventsuburl = /87895a19/upnp/control/WANCommonIFC1
- scpdurl = /87895a19/gateicfgSCPD.xml
-
-first:
- servicetype = urn:schemas-upnp-org:service:WANPPPConnection:2
- controlurl = /87895a19/upnp/control/WANIPConn1
- eventsuburl = /87895a19/upnp/control/WANIPConn1
- scpdurl = /87895a19/gateconnSCPD_PPP.xml
-
-IPv6FC:
- servicetype = urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
- controlurl = /87895a19/upnp/control/WANIPv6FwCtrl1
- eventsuburl = /87895a19/upnp/control/WANIPv6FwCtrl1
- scpdurl = /87895a19/wanipv6fwctrlSCPD.xml
-
diff --git a/ext/miniupnpc/testdesc/new_LiveBox_desc.xml b/ext/miniupnpc/testdesc/new_LiveBox_desc.xml
deleted file mode 100644
index 620eb55a..00000000
--- a/ext/miniupnpc/testdesc/new_LiveBox_desc.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0"?>
-<root xmlns="urn:schemas-upnp-org:device-1-0">
- <specVersion>
- <major>1</major>
- <minor>0</minor>
- </specVersion>
- <device>
- <pnpx:X_hardwareId xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11">VEN_0129&amp;DEV_0000&amp;SUBSYS_03&amp;REV_250417</pnpx:X_hardwareId>
- <pnpx:X_compatibleId xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11">GenericUmPass</pnpx:X_compatibleId>
- <pnpx:X_deviceCategory xmlns:pnpx="http://schemas.microsoft.com/windows/pnpx/2005/11">NetworkInfrastructure.Gateway</pnpx:X_deviceCategory>
- <df:X_deviceCategory xmlns:df="http://schemas.microsoft.com/windows/2008/09/devicefoundation">Network.Gateway</df:X_deviceCategory>
- <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:2</deviceType>
- <friendlyName>Orange Livebox</friendlyName>
- <manufacturer>Sagemcom</manufacturer>
- <manufacturerURL>http://www.sagemcom.com/</manufacturerURL>
- <modelName>Residential Livebox,(DSL,WAN Ethernet)</modelName>
- <UDN>uuid:87895a19-50f9-3736-a87f-115c230155f8</UDN>
- <modelDescription>Sagemcom,fr,SG30_sip-fr-4.28.35.1</modelDescription>
- <modelNumber>3</modelNumber>
- <serialNumber>LK14129DP441489</serialNumber>
- <presentationURL>http://192.168.1.1</presentationURL>
- <UPC></UPC>
- <iconList>
- <icon>
- <mimetype>image/png</mimetype>
- <width>16</width>
- <height>16</height>
- <depth>8</depth>
- <url>/87895a19/ligd.png</url>
- </icon>
- </iconList>
- <deviceList>
- <device>
- <deviceType>urn:schemas-upnp-org:device:WANDevice:2</deviceType>
- <friendlyName>WANDevice</friendlyName>
- <manufacturer>Sagemcom</manufacturer>
- <manufacturerURL>http://www.sagemcom.com/</manufacturerURL>
- <modelDescription>WAN Device on Sagemcom,fr,SG30_sip-fr-4.28.35.1</modelDescription>
- <modelName>Residential Livebox,(DSL,WAN Ethernet)</modelName>
- <modelNumber>3</modelNumber>
- <modelURL>http://www.sagemcom.com/</modelURL>
- <serialNumber>LK14129DP441489</serialNumber>
- <presentationURL>http://192.168.1.1</presentationURL>
- <UDN>uuid:e2397374-53d8-3fc6-8306-593ba1a34625</UDN>
- <UPC></UPC>
- <serviceList>
- <service>
- <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
- <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
- <controlURL>/87895a19/upnp/control/WANCommonIFC1</controlURL>
- <eventSubURL>/87895a19/upnp/control/WANCommonIFC1</eventSubURL>
- <SCPDURL>/87895a19/gateicfgSCPD.xml</SCPDURL>
- </service>
- </serviceList>
- <deviceList>
- <device>
- <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:2</deviceType>
- <friendlyName>WANConnectionDevice</friendlyName>
- <manufacturer>Sagemcom</manufacturer>
- <manufacturerURL>http://www.sagemcom.com/</manufacturerURL>
- <modelDescription>WanConnectionDevice on Sagemcom,fr,SG30_sip-fr-4.28.35.1</modelDescription>
- <modelName>Residential Livebox,(DSL,WAN Ethernet)</modelName>
- <modelNumber>3</modelNumber>
- <modelURL>http://www.sagemcom.com/</modelURL>
- <serialNumber>LK14129DP441489</serialNumber>
- <presentationURL>http://192.168.1.1</presentationURL>
- <UDN>uuid:44598a08-288e-32c9-8a4d-d3c008ede331</UDN>
- <UPC></UPC>
- <serviceList>
- <service>
- <serviceType>urn:schemas-upnp-org:service:WANPPPConnection:2</serviceType>
- <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId>
- <controlURL>/87895a19/upnp/control/WANIPConn1</controlURL>
- <eventSubURL>/87895a19/upnp/control/WANIPConn1</eventSubURL>
- <SCPDURL>/87895a19/gateconnSCPD_PPP.xml</SCPDURL>
- </service>
- <service>
- <serviceType>urn:schemas-upnp-org:service:WANIPv6FirewallControl:1</serviceType>
- <serviceId>urn:upnp-org:serviceId:WANIPv6FwCtrl1</serviceId>
- <controlURL>/87895a19/upnp/control/WANIPv6FwCtrl1</controlURL>
- <eventSubURL>/87895a19/upnp/control/WANIPv6FwCtrl1</eventSubURL>
- <SCPDURL>/87895a19/wanipv6fwctrlSCPD.xml</SCPDURL>
- </service>
- </serviceList>
- </device>
- </deviceList>
- </device>
- </deviceList>
- </device>
-</root> \ No newline at end of file
diff --git a/ext/miniupnpc/testigddescparse.c b/ext/miniupnpc/testigddescparse.c
deleted file mode 100644
index c1907fd0..00000000
--- a/ext/miniupnpc/testigddescparse.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* $Id: testigddescparse.c,v 1.10 2015/08/06 09:55:24 nanard Exp $ */
-/* Project : miniupnp
- * http://miniupnp.free.fr/
- * Author : Thomas Bernard
- * Copyright (c) 2008-2015 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "igd_desc_parse.h"
-#include "minixml.h"
-#include "miniupnpc.h"
-
-/* count number of differences */
-int compare_service(struct IGDdatas_service * s, FILE * f)
-{
- int n = 0;
- char line[1024];
-
- while(fgets(line, sizeof(line), f)) {
- char * value;
- char * equal;
- char * name;
- char * parsedvalue;
- int l;
- l = strlen(line);
- while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n') || (line[l-1] == ' ')))
- line[--l] = '\0';
- if(l == 0)
- break; /* end on blank line */
- if(line[0] == '#')
- continue; /* skip comments */
- equal = strchr(line, '=');
- if(equal == NULL) {
- fprintf(stderr, "Warning, line does not contain '=' : %s\n", line);
- continue;
- }
- *equal = '\0';
- name = line;
- while(*name == ' ' || *name == '\t')
- name++;
- l = strlen(name);
- while((l > 0) && (name[l-1] == ' ' || name[l-1] == '\t'))
- name[--l] = '\0';
- value = equal + 1;
- while(*value == ' ' || *value == '\t')
- value++;
- if(strcmp(name, "controlurl") == 0)
- parsedvalue = s->controlurl;
- else if(strcmp(name, "eventsuburl") == 0)
- parsedvalue = s->eventsuburl;
- else if(strcmp(name, "scpdurl") == 0)
- parsedvalue = s->scpdurl;
- else if(strcmp(name, "servicetype") == 0)
- parsedvalue = s->servicetype;
- else {
- fprintf(stderr, "unknown field '%s'\n", name);
- continue;
- }
- if(0 != strcmp(parsedvalue, value)) {
- fprintf(stderr, "difference : '%s' != '%s'\n", parsedvalue, value);
- n++;
- }
- }
- return n;
-}
-
-int compare_igd(struct IGDdatas * p, FILE * f)
-{
- int n = 0;
- char line[1024];
- struct IGDdatas_service * s;
-
- while(fgets(line, sizeof(line), f)) {
- char * colon;
- int l = (int)strlen(line);
- while((l > 0) && (line[l-1] == '\r' || (line[l-1] == '\n')))
- line[--l] = '\0';
- if(l == 0 || line[0] == '#')
- continue; /* skip blank lines and comments */
- colon = strchr(line, ':');
- if(colon == NULL) {
- fprintf(stderr, "Warning, no ':' : %s\n", line);
- continue;
- }
- s = NULL;
- *colon = '\0';
- if(strcmp(line, "CIF") == 0)
- s = &p->CIF;
- else if(strcmp(line, "first") == 0)
- s = &p->first;
- else if(strcmp(line, "second") == 0)
- s = &p->second;
- else if(strcmp(line, "IPv6FC") == 0)
- s = &p->IPv6FC;
- else {
- s = NULL;
- fprintf(stderr, "*** unknown service '%s' ***\n", line);
- n++;
- continue;
- }
- n += compare_service(s, f);
- }
- if(n > 0)
- fprintf(stderr, "*** %d difference%s ***\n", n, (n > 1) ? "s" : "");
- return n;
-}
-
-int test_igd_desc_parse(char * buffer, int len, FILE * f)
-{
- int n;
- struct IGDdatas igd;
- struct xmlparser parser;
- struct UPNPUrls urls;
-
- memset(&igd, 0, sizeof(struct IGDdatas));
- memset(&parser, 0, sizeof(struct xmlparser));
- parser.xmlstart = buffer;
- parser.xmlsize = len;
- parser.data = &igd;
- parser.starteltfunc = IGDstartelt;
- parser.endeltfunc = IGDendelt;
- parser.datafunc = IGDdata;
- parsexml(&parser);
-#ifdef DEBUG
- printIGD(&igd);
-#endif /* DEBUG */
- GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0);
- printf("ipcondescURL='%s'\n", urls.ipcondescURL);
- printf("controlURL='%s'\n", urls.controlURL);
- printf("controlURL_CIF='%s'\n", urls.controlURL_CIF);
- n = f ? compare_igd(&igd, f) : 0;
- FreeUPNPUrls(&urls);
- return n;
-}
-
-int main(int argc, char * * argv)
-{
- FILE * f;
- char * buffer;
- int len;
- int r;
- if(argc<2) {
- fprintf(stderr, "Usage: %s file.xml [file.values]\n", argv[0]);
- return 1;
- }
- f = fopen(argv[1], "r");
- if(!f) {
- fprintf(stderr, "Cannot open %s for reading.\n", argv[1]);
- return 1;
- }
- fseek(f, 0, SEEK_END);
- len = ftell(f);
- fseek(f, 0, SEEK_SET);
- buffer = malloc(len);
- if(!buffer) {
- fprintf(stderr, "Memory allocation error.\n");
- fclose(f);
- return 1;
- }
- r = (int)fread(buffer, 1, len, f);
- if(r != len) {
- fprintf(stderr, "Failed to read file %s. %d out of %d bytes.\n",
- argv[1], r, len);
- fclose(f);
- free(buffer);
- return 1;
- }
- fclose(f);
- f = NULL;
- if(argc > 2) {
- f = fopen(argv[2], "r");
- if(!f) {
- fprintf(stderr, "Cannot open %s for reading.\n", argv[2]);
- free(buffer);
- return 1;
- }
- }
- r = test_igd_desc_parse(buffer, len, f);
- free(buffer);
- if(f)
- fclose(f);
- return r;
-}
-
diff --git a/ext/miniupnpc/testminiwget.c b/ext/miniupnpc/testminiwget.c
deleted file mode 100644
index 5eb49ec1..00000000
--- a/ext/miniupnpc/testminiwget.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id: testminiwget.c,v 1.5 2016/01/24 17:24:36 nanard Exp $ */
-/* Project : miniupnp
- * Author : Thomas Bernard
- * Copyright (c) 2005-2016 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-#include <stdio.h>
-#include <stdlib.h>
-#include "miniwget.h"
-
-/**
- * This program uses the miniwget / miniwget_getaddr function
- * from miniwget.c in order to retreive a web ressource using
- * a GET HTTP method, and store it in a file.
- */
-int main(int argc, char * * argv)
-{
- void * data;
- int size, writtensize;
- FILE *f;
- char addr[64];
- int status_code = -1;
-
- if(argc < 3) {
- fprintf(stderr, "Usage:\t%s url file\n", argv[0]);
- fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]);
- return 1;
- }
- data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0, &status_code);
- if(!data || (status_code != 200)) {
- if(data) free(data);
- fprintf(stderr, "Error %d fetching %s\n", status_code, argv[1]);
- return 1;
- }
- printf("local address : %s\n", addr);
- printf("got %d bytes\n", size);
- f = fopen(argv[2], "wb");
- if(!f) {
- fprintf(stderr, "Cannot open file %s for writing\n", argv[2]);
- free(data);
- return 1;
- }
- writtensize = fwrite(data, 1, size, f);
- if(writtensize != size) {
- fprintf(stderr, "Could only write %d bytes out of %d to %s\n",
- writtensize, size, argv[2]);
- } else {
- printf("%d bytes written to %s\n", writtensize, argv[2]);
- }
- fclose(f);
- free(data);
- return 0;
-}
-
diff --git a/ext/miniupnpc/testminiwget.sh b/ext/miniupnpc/testminiwget.sh
deleted file mode 100755
index 690b4056..00000000
--- a/ext/miniupnpc/testminiwget.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-# $Id: testminiwget.sh,v 1.13 2015/09/03 17:57:44 nanard Exp $
-# project miniupnp : http://miniupnp.free.fr/
-# (c) 2011-2015 Thomas Bernard
-#
-# test program for miniwget.c
-# is usually invoked by "make check"
-#
-# This test program :
-# 1 - launches a local HTTP server (minihttptestserver)
-# 2 - uses testminiwget to retreive data from this server
-# 3 - compares served and received data
-# 4 - kills the local HTTP server and exits
-#
-# The script was tested and works with ksh, bash
-# it should now also run with dash
-
-TMPD=`mktemp -d -t miniwgetXXXXXXXXXX`
-HTTPSERVEROUT="${TMPD}/httpserverout"
-EXPECTEDFILE="${TMPD}/expectedfile"
-DOWNLOADEDFILE="${TMPD}/downloadedfile"
-PORT=
-RET=0
-
-case "$HAVE_IPV6" in
- n|no|0)
- ADDR=localhost
- SERVERARGS=""
- ;;
- *)
- ADDR="[::1]"
- SERVERARGS="-6"
- ;;
-
-esac
-
-#make minihttptestserver
-#make testminiwget
-
-# launching the test HTTP server
-./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT &
-SERVERPID=$!
-while [ -z "$PORT" ]; do
- sleep 1
- PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' `
-done
-echo "Test HTTP server is listening on $PORT"
-
-URL1="http://$ADDR:$PORT/index.html"
-URL2="http://$ADDR:$PORT/chunked"
-URL3="http://$ADDR:$PORT/addcrap"
-
-echo "standard test ..."
-./testminiwget $URL1 "${DOWNLOADEDFILE}.1"
-if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then
- echo "ok"
-else
- echo "standard test FAILED"
- RET=1
-fi
-
-echo "chunked transfert encoding test ..."
-./testminiwget $URL2 "${DOWNLOADEDFILE}.2"
-if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then
- echo "ok"
-else
- echo "chunked transfert encoding test FAILED"
- RET=1
-fi
-
-echo "response too long test ..."
-./testminiwget $URL3 "${DOWNLOADEDFILE}.3"
-if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then
- echo "ok"
-else
- echo "response too long test FAILED"
- RET=1
-fi
-
-# kill the test HTTP server
-kill $SERVERPID
-wait $SERVERPID
-
-# remove temporary files (for success cases)
-if [ $RET -eq 0 ]; then
- rm -f "${DOWNLOADEDFILE}.1"
- rm -f "${DOWNLOADEDFILE}.2"
- rm -f "${DOWNLOADEDFILE}.3"
- rm -f $EXPECTEDFILE $HTTPSERVEROUT
- rmdir ${TMPD}
-else
- echo "at least one of the test FAILED"
- echo "directory ${TMPD} is left intact"
-fi
-exit $RET
-
diff --git a/ext/miniupnpc/testminixml.c b/ext/miniupnpc/testminixml.c
deleted file mode 100644
index 57c4a85e..00000000
--- a/ext/miniupnpc/testminixml.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* $Id: testminixml.c,v 1.10 2014/11/17 17:19:13 nanard Exp $
- * MiniUPnP project
- * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * Author : Thomas Bernard.
- * Copyright (c) 2005-2014 Thomas Bernard
- *
- * testminixml.c
- * test program for the "minixml" functions.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "minixml.h"
-#include "igd_desc_parse.h"
-
-/* ---------------------------------------------------------------------- */
-void printeltname1(void * d, const char * name, int l)
-{
- int i;
- (void)d;
- printf("element ");
- for(i=0;i<l;i++)
- putchar(name[i]);
-}
-void printeltname2(void * d, const char * name, int l)
-{
- int i;
- (void)d;
- putchar('/');
- for(i=0;i<l;i++)
- putchar(name[i]);
- putchar('\n');
-}
-void printdata(void *d, const char * data, int l)
-{
- int i;
- (void)d;
- printf("data : ");
- for(i=0;i<l;i++)
- putchar(data[i]);
- putchar('\n');
-}
-
-void burptest(const char * buffer, int bufsize)
-{
- struct IGDdatas data;
- struct xmlparser parser;
- /*objet IGDdatas */
- memset(&data, 0, sizeof(struct IGDdatas));
- /* objet xmlparser */
- parser.xmlstart = buffer;
- parser.xmlsize = bufsize;
- parser.data = &data;
- /*parser.starteltfunc = printeltname1;
- parser.endeltfunc = printeltname2;
- parser.datafunc = printdata; */
- parser.starteltfunc = IGDstartelt;
- parser.endeltfunc = IGDendelt;
- parser.datafunc = IGDdata;
- parsexml(&parser);
-#ifdef DEBUG
- printIGD(&data);
-#endif /* DEBUG */
-}
-
-/* ----- main ---- */
-#define XML_MAX_SIZE (8192)
-int main(int argc, char * * argv)
-{
- FILE * f;
- char buffer[XML_MAX_SIZE];
- int bufsize;
- if(argc<2)
- {
- printf("usage:\t%s file.xml\n", argv[0]);
- return 1;
- }
- f = fopen(argv[1], "r");
- if(!f)
- {
- printf("cannot open file %s\n", argv[1]);
- return 1;
- }
- bufsize = (int)fread(buffer, 1, XML_MAX_SIZE, f);
- fclose(f);
- burptest(buffer, bufsize);
- return 0;
-}
-
diff --git a/ext/miniupnpc/testportlistingparse.c b/ext/miniupnpc/testportlistingparse.c
deleted file mode 100644
index bd9247dc..00000000
--- a/ext/miniupnpc/testportlistingparse.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* $Id: testportlistingparse.c,v 1.2 2014/11/01 10:37:32 nanard Exp $ */
-/* Project : miniupnp
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * Author : Thomas Bernard
- * Copyright (c) 2014 Thomas Bernard
- * This software is subject to the conditions detailed in the
- * LICENCE file provided in this distribution.
- * */
-
-#include <string.h>
-#include <stdio.h>
-#include "portlistingparse.h"
-
-struct port_mapping {
- unsigned int leasetime;
- unsigned short externalport;
- unsigned short internalport;
- const char * remotehost;
- const char * client;
- const char * proto;
- const char * desc;
- unsigned char enabled;
-};
-
-/* return the number of differences */
-int test(const char * portListingXml, int portListingXmlLen,
- const struct port_mapping * ref, int count)
-{
- int i;
- int r = 0;
- struct PortMappingParserData data;
- struct PortMapping * pm;
-
- memset(&data, 0, sizeof(data));
- ParsePortListing(portListingXml, portListingXmlLen, &data);
- for(i = 0, pm = data.l_head;
- (pm != NULL) && (i < count);
- i++, pm = pm->l_next) {
- printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
- i, pm->protocol, pm->externalPort, pm->internalClient,
- pm->internalPort,
- pm->description, pm->remoteHost,
- (unsigned)pm->leaseTime);
- if(0 != strcmp(pm->protocol, ref[i].proto)) {
- printf("protocol : '%s' != '%s'\n", pm->protocol, ref[i].proto);
- r++;
- }
- if(pm->externalPort != ref[i].externalport) {
- printf("externalPort : %hu != %hu\n",
- pm->externalPort, ref[i].externalport);
- r++;
- }
- if(0 != strcmp(pm->internalClient, ref[i].client)) {
- printf("client : '%s' != '%s'\n",
- pm->internalClient, ref[i].client);
- r++;
- }
- if(pm->internalPort != ref[i].internalport) {
- printf("internalPort : %hu != %hu\n",
- pm->internalPort, ref[i].internalport);
- r++;
- }
- if(0 != strcmp(pm->description, ref[i].desc)) {
- printf("description : '%s' != '%s'\n",
- pm->description, ref[i].desc);
- r++;
- }
- if(0 != strcmp(pm->remoteHost, ref[i].remotehost)) {
- printf("remoteHost : '%s' != '%s'\n",
- pm->remoteHost, ref[i].remotehost);
- r++;
- }
- if((unsigned)pm->leaseTime != ref[i].leasetime) {
- printf("leaseTime : %u != %u\n",
- (unsigned)pm->leaseTime, ref[i].leasetime);
- r++;
- }
- if(pm->enabled != ref[i].enabled) {
- printf("enabled : %d != %d\n",
- (int)pm->enabled, (int)ref[i].enabled);
- r++;
- }
- }
- if((i != count) || (pm != NULL)) {
- printf("count mismatch : i=%d count=%d pm=%p\n", i, count, pm);
- r++;
- }
- FreePortListing(&data);
- return r;
-}
-
-const char test_document[] =
-"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-"<p:PortMappingList xmlns:p=\"urn:schemas-upnp-org:gw:WANIPConnection\"\n"
-"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n"
-"xsi:schemaLocation=\"urn:schemas-upnp-org:gw:WANIPConnection "
-"http://www.upnp.org/schemas/gw/WANIPConnection-v2.xsd\">\n"
-" <p:PortMappingEntry>\n"
-" <p:NewRemoteHost></p:NewRemoteHost>\n"
-" <p:NewExternalPort>5002</p:NewExternalPort>\n"
-" <p:NewProtocol>UDP</p:NewProtocol>\n"
-" <p:NewInternalPort>4001</p:NewInternalPort>\n"
-" <p:NewInternalClient>192.168.1.123</p:NewInternalClient>\n"
-" <p:NewEnabled>1</p:NewEnabled>\n"
-" <p:NewDescription>xxx</p:NewDescription>\n"
-" <p:NewLeaseTime>0</p:NewLeaseTime>\n"
-" </p:PortMappingEntry>\n"
-" <p:PortMappingEntry>\n"
-" <p:NewRemoteHost>202.233.2.1</p:NewRemoteHost>\n"
-" <p:NewExternalPort>2345</p:NewExternalPort>\n"
-" <p:NewProtocol>TCP</p:NewProtocol>\n"
-" <p:NewInternalPort>2349</p:NewInternalPort>\n"
-" <p:NewInternalClient>192.168.1.137</p:NewInternalClient>\n"
-" <p:NewEnabled>1</p:NewEnabled>\n"
-" <p:NewDescription>dooom</p:NewDescription>\n"
-" <p:NewLeaseTime>346</p:NewLeaseTime>\n"
-" </p:PortMappingEntry>\n"
-" <p:PortMappingEntry>\n"
-" <p:NewRemoteHost>134.231.2.11</p:NewRemoteHost>\n"
-" <p:NewExternalPort>12345</p:NewExternalPort>\n"
-" <p:NewProtocol>TCP</p:NewProtocol>\n"
-" <p:NewInternalPort>12345</p:NewInternalPort>\n"
-" <p:NewInternalClient>192.168.1.137</p:NewInternalClient>\n"
-" <p:NewEnabled>1</p:NewEnabled>\n"
-" <p:NewDescription>dooom A</p:NewDescription>\n"
-" <p:NewLeaseTime>347</p:NewLeaseTime>\n"
-" </p:PortMappingEntry>\n"
-"</p:PortMappingList>";
-
-#define PORT_MAPPINGS_COUNT 3
-const struct port_mapping port_mappings[PORT_MAPPINGS_COUNT] = {
-{347, 12345, 12345, "134.231.2.11", "192.168.1.137", "TCP", "dooom A", 1},
-{346, 2345, 2349, "202.233.2.1", "192.168.1.137", "TCP", "dooom", 1},
-{0, 5002, 4001, "", "192.168.1.123", "UDP", "xxx", 1}
-};
-
-/* --- main --- */
-int main(void)
-{
- int r;
- r = test(test_document, sizeof(test_document) - 1,
- port_mappings, PORT_MAPPINGS_COUNT);
- if(r == 0) {
- printf("test of portlistingparse OK\n");
- return 0;
- } else {
- printf("test FAILED (%d differences counted)\n", r);
- return 1;
- }
-}
-
diff --git a/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue b/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue
deleted file mode 100644
index 48ca0ccc..00000000
--- a/ext/miniupnpc/testreplyparse/DeletePortMapping.namevalue
+++ /dev/null
@@ -1,3 +0,0 @@
-NewRemoteHost=
-NewExternalPort=123
-NewProtocol=TCP
diff --git a/ext/miniupnpc/testreplyparse/DeletePortMapping.xml b/ext/miniupnpc/testreplyparse/DeletePortMapping.xml
deleted file mode 100644
index a955c53f..00000000
--- a/ext/miniupnpc/testreplyparse/DeletePortMapping.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0"?>
-<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>123</NewExternalPort>
-<NewProtocol>TCP</NewProtocol></u:DeletePortMapping></s:Body>
-
-</s:Envelope>
-
diff --git a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue
deleted file mode 100644
index 5aa75f88..00000000
--- a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue
+++ /dev/null
@@ -1,2 +0,0 @@
-NewExternalIPAddress=1.2.3.4
-
diff --git a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml b/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml
deleted file mode 100644
index db7ec1f9..00000000
--- a/ext/miniupnpc/testreplyparse/GetExternalIPAddress.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewExternalIPAddress>1.2.3.4</NewExternalIPAddress></u:GetExternalIPAddressResponse></s:Body></s:Envelope>
-
diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue
deleted file mode 100644
index 26b169c3..00000000
--- a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue
+++ /dev/null
@@ -1,3 +0,0 @@
-NewProtocol=UDP
-NewExternalPort=12345
-NewRemoteHost=
diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml
deleted file mode 100644
index bbb540ea..00000000
--- a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0"?>
-<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetSpecificPortMappingEntry xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>12345</NewExternalPort><NewProtocol>UDP</NewProtocol></u:GetSpecificPortMappingEntry></s:Body></s:Envelope>
-
diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue
deleted file mode 100644
index 2189789b..00000000
--- a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue
+++ /dev/null
@@ -1,5 +0,0 @@
-NewInternalPort=12345
-NewInternalClient=192.168.10.110
-NewEnabled=1
-NewPortMappingDescription=libminiupnpc
-NewLeaseDuration=0
diff --git a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml b/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml
deleted file mode 100644
index 77e8d9c7..00000000
--- a/ext/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetSpecificPortMappingEntryResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewInternalPort>12345</NewInternalPort><NewInternalClient>192.168.10.110</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>libminiupnpc</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:GetSpecificPortMappingEntryResponse></s:Body></s:Envelope>
-
diff --git a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue
deleted file mode 100644
index f78c7e2a..00000000
--- a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue
+++ /dev/null
@@ -1 +0,0 @@
-NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID
diff --git a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml b/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml
deleted file mode 100644
index ac04c07a..00000000
--- a/ext/miniupnpc/testreplyparse/SetDefaultConnectionService.xml
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:SetDefaultConnectionService xmlns:u="urn:schemas-upnp-org:service:Layer3Forwarding:1"><NewDefaultConnectionService>uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID</NewDefaultConnectionService></u:SetDefaultConnectionService></s:Body></s:Envelope>
diff --git a/ext/miniupnpc/testreplyparse/readme.txt b/ext/miniupnpc/testreplyparse/readme.txt
deleted file mode 100644
index 3eb1f015..00000000
--- a/ext/miniupnpc/testreplyparse/readme.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory contains files used for validation of upnpreplyparse.c code.
-
-Each .xml file to parse should give the results which are in the .namevalue
-file.
-
-A .namevalue file contain name=value lines.
-
diff --git a/ext/miniupnpc/testupnpigd.py b/ext/miniupnpc/testupnpigd.py
deleted file mode 100755
index 6d167a4c..00000000
--- a/ext/miniupnpc/testupnpigd.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#! /usr/bin/python
-# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $
-# MiniUPnP project
-# Author : Thomas Bernard
-# This Sample code is public domain.
-# website : http://miniupnp.tuxfamily.org/
-
-# import the python miniupnpc module
-import miniupnpc
-import socket
-import BaseHTTPServer
-
-# function definition
-def list_redirections():
- i = 0
- while True:
- p = u.getgenericportmapping(i)
- if p==None:
- break
- print i, p
- i = i + 1
-
-#define the handler class for HTTP connections
-class handler_class(BaseHTTPServer.BaseHTTPRequestHandler):
- def do_GET(self):
- self.send_response(200)
- self.end_headers()
- self.wfile.write("OK MON GARS")
-
-# create the object
-u = miniupnpc.UPnP()
-#print 'inital(default) values :'
-#print ' discoverdelay', u.discoverdelay
-#print ' lanaddr', u.lanaddr
-#print ' multicastif', u.multicastif
-#print ' minissdpdsocket', u.minissdpdsocket
-u.discoverdelay = 200;
-
-try:
- print 'Discovering... delay=%ums' % u.discoverdelay
- ndevices = u.discover()
- print ndevices, 'device(s) detected'
-
- # select an igd
- u.selectigd()
- # display information about the IGD and the internet connection
- print 'local ip address :', u.lanaddr
- externalipaddress = u.externalipaddress()
- print 'external ip address :', externalipaddress
- print u.statusinfo(), u.connectiontype()
-
- #instanciate a HTTPd object. The port is assigned by the system.
- httpd = BaseHTTPServer.HTTPServer((u.lanaddr, 0), handler_class)
- eport = httpd.server_port
-
- # find a free port for the redirection
- r = u.getspecificportmapping(eport, 'TCP')
- while r != None and eport < 65536:
- eport = eport + 1
- r = u.getspecificportmapping(eport, 'TCP')
-
- print 'trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port)
-
- b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port,
- 'UPnP IGD Tester port %u' % eport, '')
- if b:
- print 'Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport)
- try:
- httpd.handle_request()
- httpd.server_close()
- except KeyboardInterrupt, details:
- print "CTRL-C exception!", details
- b = u.deleteportmapping(eport, 'TCP')
- if b:
- print 'Successfully deleted port mapping'
- else:
- print 'Failed to remove port mapping'
- else:
- print 'Failed'
-
- httpd.server_close()
-
-except Exception, e:
- print 'Exception :', e
diff --git a/ext/miniupnpc/testupnpreplyparse.c b/ext/miniupnpc/testupnpreplyparse.c
deleted file mode 100644
index 7ba7131e..00000000
--- a/ext/miniupnpc/testupnpreplyparse.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */
-/* MiniUPnP project
- * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2006-2014 Thomas Bernard
- * This software is subject to the conditions detailed
- * in the LICENCE file provided within the distribution */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "upnpreplyparse.h"
-
-int
-test_parsing(const char * buf, int len, FILE * f)
-{
- char line[1024];
- struct NameValueParserData pdata;
- int ok = 1;
- ParseNameValue(buf, len, &pdata);
- /* check result */
- if(f != NULL)
- {
- while(fgets(line, sizeof(line), f))
- {
- char * value;
- char * equal;
- char * parsedvalue;
- int l;
- l = strlen(line);
- while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n')))
- line[--l] = '\0';
- /* skip empty lines */
- if(l == 0)
- continue;
- equal = strchr(line, '=');
- if(equal == NULL)
- {
- fprintf(stderr, "Warning, line does not contain '=' : %s\n", line);
- continue;
- }
- *equal = '\0';
- value = equal + 1;
- parsedvalue = GetValueFromNameValueList(&pdata, line);
- if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0))
- {
- fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n",
- line, value, parsedvalue ? parsedvalue : "<null string>");
- ok = 0;
- }
- }
- }
- ClearNameValueList(&pdata);
- return ok;
-}
-
-int main(int argc, char * * argv)
-{
- FILE * f;
- char buffer[4096];
- int l;
- int ok;
-
- if(argc<2)
- {
- fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]);
- return 1;
- }
- f = fopen(argv[1], "r");
- if(!f)
- {
- fprintf(stderr, "Error : can not open file %s\n", argv[1]);
- return 2;
- }
- l = fread(buffer, 1, sizeof(buffer)-1, f);
- fclose(f);
- f = NULL;
- buffer[l] = '\0';
- if(argc > 2)
- {
- f = fopen(argv[2], "r");
- if(!f)
- {
- fprintf(stderr, "Error : can not open file %s\n", argv[2]);
- return 2;
- }
- }
-#ifdef DEBUG
- DisplayNameValueList(buffer, l);
-#endif
- ok = test_parsing(buffer, l, f);
- if(f)
- {
- fclose(f);
- }
- return ok ? 0 : 3;
-}
-
diff --git a/ext/miniupnpc/testupnpreplyparse.sh b/ext/miniupnpc/testupnpreplyparse.sh
deleted file mode 100755
index 992930b7..00000000
--- a/ext/miniupnpc/testupnpreplyparse.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-for f in testreplyparse/*.xml ; do
- bf="`dirname $f`/`basename $f .xml`"
- if ./testupnpreplyparse $f $bf.namevalue ; then
- echo "$f : passed"
- else
- echo "$f : FAILED"
- exit 1
- fi
-done
-
-exit 0
-
diff --git a/ext/miniupnpc/upnpc.c b/ext/miniupnpc/upnpc.c
index 94f131c8..e719ecec 100644
--- a/ext/miniupnpc/upnpc.c
+++ b/ext/miniupnpc/upnpc.c
@@ -1,7 +1,7 @@
-/* $Id: upnpc.c,v 1.114 2016/01/22 15:04:23 nanard Exp $ */
+/* $Id: upnpc.c,v 1.117 2017/05/26 15:26:55 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2005-2016 Thomas Bernard
+ * Copyright (c) 2005-2017 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -242,7 +242,7 @@ static void NewListRedirections(struct UPNPUrls * urls,
* 2 - get extenal ip address
* 3 - Add port mapping
* 4 - get this port mapping from the IGD */
-static void SetRedirectAndTest(struct UPNPUrls * urls,
+static int SetRedirectAndTest(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * iaddr,
const char * iport,
@@ -262,13 +262,13 @@ static void SetRedirectAndTest(struct UPNPUrls * urls,
if(!iaddr || !iport || !eport || !proto)
{
fprintf(stderr, "Wrong arguments\n");
- return;
+ return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "invalid protocol\n");
- return;
+ return -1;
}
r = UPNP_GetExternalIPAddress(urls->controlURL,
@@ -292,9 +292,11 @@ static void SetRedirectAndTest(struct UPNPUrls * urls,
r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
eport, iport, iaddr, description,
proto, 0, leaseDuration);
- if(r!=UPNPCOMMAND_SUCCESS)
+ if(r!=UPNPCOMMAND_SUCCESS) {
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
eport, iport, iaddr, r, strupnperror(r));
+ return -2;
+ }
}
r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
@@ -302,17 +304,19 @@ static void SetRedirectAndTest(struct UPNPUrls * urls,
eport, proto, NULL/*remoteHost*/,
intClient, intPort, NULL/*desc*/,
NULL/*enabled*/, duration);
- if(r!=UPNPCOMMAND_SUCCESS)
+ if(r!=UPNPCOMMAND_SUCCESS) {
printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
r, strupnperror(r));
- else {
+ return -2;
+ } else {
printf("InternalIP:Port = %s:%s\n", intClient, intPort);
printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
externalIPAddress, eport, proto, intClient, intPort, duration);
}
+ return 0;
}
-static void
+static int
RemoveRedirect(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * eport,
@@ -323,19 +327,25 @@ RemoveRedirect(struct UPNPUrls * urls,
if(!proto || !eport)
{
fprintf(stderr, "invalid arguments\n");
- return;
+ return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "protocol invalid\n");
- return;
+ return -1;
}
r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
- printf("UPNP_DeletePortMapping() returned : %d\n", r);
+ if(r!=UPNPCOMMAND_SUCCESS) {
+ printf("UPNP_DeletePortMapping() failed with code : %d\n", r);
+ return -2;
+ }else {
+ printf("UPNP_DeletePortMapping() returned : %d\n", r);
+ }
+ return 0;
}
-static void
+static int
RemoveRedirectRange(struct UPNPUrls * urls,
struct IGDdatas * data,
const char * ePortStart, char const * ePortEnd,
@@ -349,16 +359,22 @@ RemoveRedirectRange(struct UPNPUrls * urls,
if(!proto || !ePortStart || !ePortEnd)
{
fprintf(stderr, "invalid arguments\n");
- return;
+ return -1;
}
proto = protofix(proto);
if(!proto)
{
fprintf(stderr, "protocol invalid\n");
- return;
+ return -1;
}
r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
- printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
+ if(r!=UPNPCOMMAND_SUCCESS) {
+ printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r);
+ return -2;
+ }else {
+ printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
+ }
+ return 0;
}
/* IGD:2, functions for service WANIPv6FirewallControl:1 */
@@ -562,8 +578,8 @@ int main(int argc, char ** argv)
}
#endif
printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
- printf(" (c) 2005-2016 Thomas Bernard.\n");
- printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
+ printf(" (c) 2005-2017 Thomas Bernard.\n");
+ printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
"for more information.\n");
/* command line processing */
for(i=1; i<argc; i++)
@@ -711,29 +727,33 @@ int main(int argc, char ** argv)
NewListRedirections(&urls, &data);
break;
case 'a':
- SetRedirectAndTest(&urls, &data,
+ if (SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
(commandargc > 4)?commandargv[4]:"0",
- description, 0);
+ description, 0) < 0)
+ retcode = 2;
break;
case 'd':
- RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
- commandargc > 2 ? commandargv[2] : NULL);
+ if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
+ commandargc > 2 ? commandargv[2] : NULL) < 0)
+ retcode = 2;
break;
case 'n': /* aNy */
- SetRedirectAndTest(&urls, &data,
+ if (SetRedirectAndTest(&urls, &data,
commandargv[0], commandargv[1],
commandargv[2], commandargv[3],
(commandargc > 4)?commandargv[4]:"0",
- description, 1);
+ description, 1) < 0)
+ retcode = 2;
break;
case 'N':
if (commandargc < 3)
fprintf(stderr, "too few arguments\n");
- RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
- commandargc > 3 ? commandargv[3] : NULL);
+ if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
+ commandargc > 3 ? commandargv[3] : NULL) < 0)
+ retcode = 2;
break;
case 's':
GetConnectionStatus(&urls, &data);
@@ -749,17 +769,19 @@ int main(int argc, char ** argv)
break;
} else if(is_int(commandargv[i+1])){
/* 2nd parameter is an integer : <port> <external_port> <protocol> */
- SetRedirectAndTest(&urls, &data,
+ if (SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i+1], commandargv[i+2], "0",
- description, 0);
+ description, 0) < 0)
+ retcode = 2;
i+=3; /* 3 parameters parsed */
} else {
/* 2nd parameter not an integer : <port> <protocol> */
- SetRedirectAndTest(&urls, &data,
+ if (SetRedirectAndTest(&urls, &data,
lanaddr, commandargv[i],
commandargv[i], commandargv[i+1], "0",
- description, 0);
+ description, 0) < 0)
+ retcode = 2;
i+=2; /* 2 parameters parsed */
}
}
diff --git a/ext/miniupnpc/upnpcommands.c b/ext/miniupnpc/upnpcommands.c
index 2b65651b..d786e533 100644
--- a/ext/miniupnpc/upnpcommands.c
+++ b/ext/miniupnpc/upnpcommands.c
@@ -1,9 +1,8 @@
-#define _CRT_SECURE_NO_WARNINGS
-
-/* $Id: upnpcommands.c,v 1.47 2016/03/07 12:26:48 nanard Exp $ */
-/* Project : miniupnp
+/* $Id: upnpcommands.c,v 1.48 2017/04/21 10:22:40 nanard Exp $ */
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2005-2015 Thomas Bernard
+ * Copyright (c) 2005-2017 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@@ -374,10 +373,11 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "AddPortMapping", AddPortMappingArgs,
- &bufsize))) {
- free(AddPortMappingArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "AddPortMapping", AddPortMappingArgs,
+ &bufsize);
+ free(AddPortMappingArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
@@ -394,7 +394,6 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
- free(AddPortMappingArgs);
return ret;
}
@@ -438,10 +437,11 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
AddPortMappingArgs[7].elt = "NewLeaseDuration";
AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0";
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "AddAnyPortMapping", AddPortMappingArgs,
- &bufsize))) {
- free(AddPortMappingArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "AddAnyPortMapping", AddPortMappingArgs,
+ &bufsize);
+ free(AddPortMappingArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
@@ -463,7 +463,6 @@ UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype,
}
}
ClearNameValueList(&pdata);
- free(AddPortMappingArgs);
return ret;
}
@@ -492,10 +491,11 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
DeletePortMappingArgs[1].val = extPort;
DeletePortMappingArgs[2].elt = "NewProtocol";
DeletePortMappingArgs[2].val = proto;
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "DeletePortMapping",
- DeletePortMappingArgs, &bufsize))) {
- free(DeletePortMappingArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "DeletePortMapping",
+ DeletePortMappingArgs, &bufsize);
+ free(DeletePortMappingArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
@@ -509,7 +509,6 @@ UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
- free(DeletePortMappingArgs);
return ret;
}
@@ -541,10 +540,11 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
DeletePortMappingArgs[3].elt = "NewManage";
DeletePortMappingArgs[3].val = manage;
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "DeletePortMappingRange",
- DeletePortMappingArgs, &bufsize))) {
- free(DeletePortMappingArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "DeletePortMappingRange",
+ DeletePortMappingArgs, &bufsize);
+ free(DeletePortMappingArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
@@ -557,7 +557,6 @@ UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
- free(DeletePortMappingArgs);
return ret;
}
@@ -589,10 +588,11 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
return UPNPCOMMAND_MEM_ALLOC_ERROR;
GetPortMappingArgs[0].elt = "NewPortMappingIndex";
GetPortMappingArgs[0].val = index;
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "GetGenericPortMappingEntry",
- GetPortMappingArgs, &bufsize))) {
- free(GetPortMappingArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "GetGenericPortMappingEntry",
+ GetPortMappingArgs, &bufsize);
+ free(GetPortMappingArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
ParseNameValue(buffer, bufsize, &pdata);
@@ -654,7 +654,6 @@ UPNP_GetGenericPortMappingEntry(const char * controlURL,
sscanf(p, "%d", &r);
}
ClearNameValueList(&pdata);
- free(GetPortMappingArgs);
return r;
}
@@ -730,10 +729,11 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
GetPortMappingArgs[1].val = extPort;
GetPortMappingArgs[2].elt = "NewProtocol";
GetPortMappingArgs[2].val = proto;
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "GetSpecificPortMappingEntry",
- GetPortMappingArgs, &bufsize))) {
- free(GetPortMappingArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "GetSpecificPortMappingEntry",
+ GetPortMappingArgs, &bufsize);
+ free(GetPortMappingArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
/*DisplayNameValueList(buffer, bufsize);*/
@@ -781,7 +781,6 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL,
}
ClearNameValueList(&pdata);
- free(GetPortMappingArgs);
return ret;
}
@@ -826,13 +825,13 @@ UPNP_GetListOfPortMappings(const char * controlURL,
GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts";
GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000";
- if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype,
- "GetListOfPortMappings",
- GetListOfPortMappingsArgs, &bufsize))) {
- free(GetListOfPortMappingsArgs);
+ buffer = simpleUPnPcommand(-1, controlURL, servicetype,
+ "GetListOfPortMappings",
+ GetListOfPortMappingsArgs, &bufsize);
+ free(GetListOfPortMappingsArgs);
+ if(!buffer) {
return UPNPCOMMAND_HTTP_ERROR;
}
- free(GetListOfPortMappingsArgs);
/*DisplayNameValueList(buffer, bufsize);*/
ParseNameValue(buffer, bufsize, &pdata);
@@ -956,6 +955,7 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
GetOutboundPinholeTimeoutArgs[4].val = intClient;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize);
+ free(GetOutboundPinholeTimeoutArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
@@ -974,7 +974,6 @@ UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype
*opTimeout = my_atoui(p);
}
ClearNameValueList(&pdata);
- free(GetOutboundPinholeTimeoutArgs);
return ret;
}
@@ -1033,6 +1032,7 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
AddPinholeArgs[5].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"AddPinhole", AddPinholeArgs, &bufsize);
+ free(AddPinholeArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
@@ -1055,7 +1055,6 @@ UPNP_AddPinhole(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
- free(AddPinholeArgs);
return ret;
}
@@ -1083,6 +1082,7 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
UpdatePinholeArgs[1].val = leaseTime;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"UpdatePinhole", UpdatePinholeArgs, &bufsize);
+ free(UpdatePinholeArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
@@ -1099,7 +1099,6 @@ UPNP_UpdatePinhole(const char * controlURL, const char * servicetype,
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
- free(UpdatePinholeArgs);
return ret;
}
@@ -1124,6 +1123,7 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char
DeletePinholeArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"DeletePinhole", DeletePinholeArgs, &bufsize);
+ free(DeletePinholeArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
/*DisplayNameValueList(buffer, bufsize);*/
@@ -1140,7 +1140,6 @@ UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char
ret = UPNPCOMMAND_SUCCESS;
}
ClearNameValueList(&pdata);
- free(DeletePinholeArgs);
return ret;
}
@@ -1165,8 +1164,11 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
CheckPinholeWorkingArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize);
+ free(CheckPinholeWorkingArgs);
if(!buffer)
+ {
return UPNPCOMMAND_HTTP_ERROR;
+ }
ParseNameValue(buffer, bufsize, &pdata);
free(buffer); buffer = NULL;
@@ -1187,7 +1189,6 @@ UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype,
}
ClearNameValueList(&pdata);
- free(CheckPinholeWorkingArgs);
return ret;
}
@@ -1212,6 +1213,7 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
GetPinholePacketsArgs[0].val = uniqueID;
buffer = simpleUPnPcommand(-1, controlURL, servicetype,
"GetPinholePackets", GetPinholePacketsArgs, &bufsize);
+ free(GetPinholePacketsArgs);
if(!buffer)
return UPNPCOMMAND_HTTP_ERROR;
ParseNameValue(buffer, bufsize, &pdata);
@@ -1232,7 +1234,6 @@ UPNP_GetPinholePackets(const char * controlURL, const char * servicetype,
}
ClearNameValueList(&pdata);
- free(GetPinholePacketsArgs);
return ret;
}
diff --git a/ext/miniupnpc/upnpreplyparse.c b/ext/miniupnpc/upnpreplyparse.c
index 88d77a66..5921349d 100644
--- a/ext/miniupnpc/upnpreplyparse.c
+++ b/ext/miniupnpc/upnpreplyparse.c
@@ -1,8 +1,8 @@
-#define _CRT_SECURE_NO_WARNINGS
-/* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */
-/* MiniUPnP project
+/* $Id: upnpreplyparse.c,v 1.20 2017/12/12 11:26:25 nanard Exp $ */
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
- * (c) 2006-2015 Thomas Bernard
+ * (c) 2006-2017 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@@ -27,12 +27,12 @@ NameValueParserStartElt(void * d, const char * name, int l)
}
static void
-NameValueParserEndElt(void * d, const char * name, int l)
+NameValueParserEndElt(void * d, const char * name, int namelen)
{
struct NameValueParserData * data = (struct NameValueParserData *)d;
struct NameValue * nv;
(void)name;
- (void)l;
+ (void)namelen;
if(!data->topelt)
return;
if(strcmp(data->curelt, "NewPortListing") != 0)
@@ -105,9 +105,7 @@ ParseNameValue(const char * buffer, int bufsize,
struct NameValueParserData * data)
{
struct xmlparser parser;
- data->l_head = NULL;
- data->portListing = NULL;
- data->portListingLength = 0;
+ memset(data, 0, sizeof(struct NameValueParserData));
/* init xmlparser object */
parser.xmlstart = buffer;
parser.xmlsize = bufsize;
diff --git a/ext/misc/linux-old-glibc-compat.c b/ext/misc/linux-old-glibc-compat.c
new file mode 100644
index 00000000..6d793a2d
--- /dev/null
+++ b/ext/misc/linux-old-glibc-compat.c
@@ -0,0 +1,18 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void *__wrap_memcpy(void *dest,const void *src,size_t n)
+{
+ return memcpy(dest,src,n);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/ext/x64-salsa2012-asm/README.md b/ext/x64-salsa2012-asm/README.md
new file mode 100644
index 00000000..a69a1a67
--- /dev/null
+++ b/ext/x64-salsa2012-asm/README.md
@@ -0,0 +1,6 @@
+Blazingly fast X64 ASM implementation of Salsa20/12
+======
+
+This is ripped from the [cnacl](https://github.com/cjdelisle/cnacl) source. The actual code is by Danial J. Bernstein and is in the public domain.
+
+This is included on Linux and Mac 64-bit builds and is significantly faster than the SSE intrinsics or C versions. It's used for packet encode/decode only since its use differs a bit from the regular Salsa20 C++ class. Specifically it lacks the ability to be called on multiple blocks, preferring instead to take a key and a single stream to encrypt and that's it.
diff --git a/ext/x64-salsa2012-asm/salsa2012.h b/ext/x64-salsa2012-asm/salsa2012.h
new file mode 100644
index 00000000..73e375eb
--- /dev/null
+++ b/ext/x64-salsa2012-asm/salsa2012.h
@@ -0,0 +1,16 @@
+#ifndef ZT_X64_SALSA2012_ASM
+#define ZT_X64_SALSA2012_ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Generates Salsa20/12 key stream
+// output, outlen, nonce, key (256-bit / 32-byte)
+extern int zt_salsa2012_amd64_xmm6(unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/x64-salsa2012-asm/salsa2012.s b/ext/x64-salsa2012-asm/salsa2012.s
new file mode 100644
index 00000000..699c89ac
--- /dev/null
+++ b/ext/x64-salsa2012-asm/salsa2012.s
@@ -0,0 +1,4488 @@
+# qhasm: enter zt_salsa2012_amd64_xmm6
+.text
+.p2align 5
+.globl _zt_salsa2012_amd64_xmm6
+.globl zt_salsa2012_amd64_xmm6
+_zt_salsa2012_amd64_xmm6:
+zt_salsa2012_amd64_xmm6:
+mov %rsp,%r11
+and $31,%r11
+add $480,%r11
+sub %r11,%rsp
+
+# qhasm: r11_stack = r11_caller
+# asm 1: movq <r11_caller=int64#9,>r11_stack=stack64#1
+# asm 2: movq <r11_caller=%r11,>r11_stack=352(%rsp)
+movq %r11,352(%rsp)
+
+# qhasm: r12_stack = r12_caller
+# asm 1: movq <r12_caller=int64#10,>r12_stack=stack64#2
+# asm 2: movq <r12_caller=%r12,>r12_stack=360(%rsp)
+movq %r12,360(%rsp)
+
+# qhasm: r13_stack = r13_caller
+# asm 1: movq <r13_caller=int64#11,>r13_stack=stack64#3
+# asm 2: movq <r13_caller=%r13,>r13_stack=368(%rsp)
+movq %r13,368(%rsp)
+
+# qhasm: r14_stack = r14_caller
+# asm 1: movq <r14_caller=int64#12,>r14_stack=stack64#4
+# asm 2: movq <r14_caller=%r14,>r14_stack=376(%rsp)
+movq %r14,376(%rsp)
+
+# qhasm: r15_stack = r15_caller
+# asm 1: movq <r15_caller=int64#13,>r15_stack=stack64#5
+# asm 2: movq <r15_caller=%r15,>r15_stack=384(%rsp)
+movq %r15,384(%rsp)
+
+# qhasm: rbx_stack = rbx_caller
+# asm 1: movq <rbx_caller=int64#14,>rbx_stack=stack64#6
+# asm 2: movq <rbx_caller=%rbx,>rbx_stack=392(%rsp)
+movq %rbx,392(%rsp)
+
+# qhasm: rbp_stack = rbp_caller
+# asm 1: movq <rbp_caller=int64#15,>rbp_stack=stack64#7
+# asm 2: movq <rbp_caller=%rbp,>rbp_stack=400(%rsp)
+movq %rbp,400(%rsp)
+
+# qhasm: bytes = arg2
+# asm 1: mov <arg2=int64#2,>bytes=int64#6
+# asm 2: mov <arg2=%rsi,>bytes=%r9
+mov %rsi,%r9
+
+# qhasm: out = arg1
+# asm 1: mov <arg1=int64#1,>out=int64#1
+# asm 2: mov <arg1=%rdi,>out=%rdi
+mov %rdi,%rdi
+
+# qhasm: m = out
+# asm 1: mov <out=int64#1,>m=int64#2
+# asm 2: mov <out=%rdi,>m=%rsi
+mov %rdi,%rsi
+
+# qhasm: iv = arg3
+# asm 1: mov <arg3=int64#3,>iv=int64#3
+# asm 2: mov <arg3=%rdx,>iv=%rdx
+mov %rdx,%rdx
+
+# qhasm: k = arg4
+# asm 1: mov <arg4=int64#4,>k=int64#8
+# asm 2: mov <arg4=%rcx,>k=%r10
+mov %rcx,%r10
+
+# qhasm: unsigned>? bytes - 0
+# asm 1: cmp $0,<bytes=int64#6
+# asm 2: cmp $0,<bytes=%r9
+cmp $0,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto done if !unsigned>
+jbe ._done
+
+# qhasm: a = 0
+# asm 1: mov $0,>a=int64#7
+# asm 2: mov $0,>a=%rax
+mov $0,%rax
+
+# qhasm: i = bytes
+# asm 1: mov <bytes=int64#6,>i=int64#4
+# asm 2: mov <bytes=%r9,>i=%rcx
+mov %r9,%rcx
+
+# qhasm: while (i) { *out++ = a; --i }
+rep stosb
+
+# qhasm: out -= bytes
+# asm 1: sub <bytes=int64#6,<out=int64#1
+# asm 2: sub <bytes=%r9,<out=%rdi
+sub %r9,%rdi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto start
+jmp ._start
+
+# qhasm: enter zt_salsa2012_amd64_xmm6_xor
+.text
+.p2align 5
+.globl _zt_salsa2012_amd64_xmm6_xor
+.globl zt_salsa2012_amd64_xmm6_xor
+_zt_salsa2012_amd64_xmm6_xor:
+zt_salsa2012_amd64_xmm6_xor:
+mov %rsp,%r11
+and $31,%r11
+add $480,%r11
+sub %r11,%rsp
+
+# qhasm: r11_stack = r11_caller
+# asm 1: movq <r11_caller=int64#9,>r11_stack=stack64#1
+# asm 2: movq <r11_caller=%r11,>r11_stack=352(%rsp)
+movq %r11,352(%rsp)
+
+# qhasm: r12_stack = r12_caller
+# asm 1: movq <r12_caller=int64#10,>r12_stack=stack64#2
+# asm 2: movq <r12_caller=%r12,>r12_stack=360(%rsp)
+movq %r12,360(%rsp)
+
+# qhasm: r13_stack = r13_caller
+# asm 1: movq <r13_caller=int64#11,>r13_stack=stack64#3
+# asm 2: movq <r13_caller=%r13,>r13_stack=368(%rsp)
+movq %r13,368(%rsp)
+
+# qhasm: r14_stack = r14_caller
+# asm 1: movq <r14_caller=int64#12,>r14_stack=stack64#4
+# asm 2: movq <r14_caller=%r14,>r14_stack=376(%rsp)
+movq %r14,376(%rsp)
+
+# qhasm: r15_stack = r15_caller
+# asm 1: movq <r15_caller=int64#13,>r15_stack=stack64#5
+# asm 2: movq <r15_caller=%r15,>r15_stack=384(%rsp)
+movq %r15,384(%rsp)
+
+# qhasm: rbx_stack = rbx_caller
+# asm 1: movq <rbx_caller=int64#14,>rbx_stack=stack64#6
+# asm 2: movq <rbx_caller=%rbx,>rbx_stack=392(%rsp)
+movq %rbx,392(%rsp)
+
+# qhasm: rbp_stack = rbp_caller
+# asm 1: movq <rbp_caller=int64#15,>rbp_stack=stack64#7
+# asm 2: movq <rbp_caller=%rbp,>rbp_stack=400(%rsp)
+movq %rbp,400(%rsp)
+
+# qhasm: out = arg1
+# asm 1: mov <arg1=int64#1,>out=int64#1
+# asm 2: mov <arg1=%rdi,>out=%rdi
+mov %rdi,%rdi
+
+# qhasm: m = arg2
+# asm 1: mov <arg2=int64#2,>m=int64#2
+# asm 2: mov <arg2=%rsi,>m=%rsi
+mov %rsi,%rsi
+
+# qhasm: bytes = arg3
+# asm 1: mov <arg3=int64#3,>bytes=int64#6
+# asm 2: mov <arg3=%rdx,>bytes=%r9
+mov %rdx,%r9
+
+# qhasm: iv = arg4
+# asm 1: mov <arg4=int64#4,>iv=int64#3
+# asm 2: mov <arg4=%rcx,>iv=%rdx
+mov %rcx,%rdx
+
+# qhasm: k = arg5
+# asm 1: mov <arg5=int64#5,>k=int64#8
+# asm 2: mov <arg5=%r8,>k=%r10
+mov %r8,%r10
+
+# qhasm: unsigned>? bytes - 0
+# asm 1: cmp $0,<bytes=int64#6
+# asm 2: cmp $0,<bytes=%r9
+cmp $0,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto done if !unsigned>
+jbe ._done
+# comment:fp stack unchanged by fallthrough
+
+# qhasm: start:
+._start:
+
+# qhasm: in12 = *(uint32 *) (k + 20)
+# asm 1: movl 20(<k=int64#8),>in12=int64#4d
+# asm 2: movl 20(<k=%r10),>in12=%ecx
+movl 20(%r10),%ecx
+
+# qhasm: in1 = *(uint32 *) (k + 0)
+# asm 1: movl 0(<k=int64#8),>in1=int64#5d
+# asm 2: movl 0(<k=%r10),>in1=%r8d
+movl 0(%r10),%r8d
+
+# qhasm: in6 = *(uint32 *) (iv + 0)
+# asm 1: movl 0(<iv=int64#3),>in6=int64#7d
+# asm 2: movl 0(<iv=%rdx),>in6=%eax
+movl 0(%rdx),%eax
+
+# qhasm: in11 = *(uint32 *) (k + 16)
+# asm 1: movl 16(<k=int64#8),>in11=int64#9d
+# asm 2: movl 16(<k=%r10),>in11=%r11d
+movl 16(%r10),%r11d
+
+# qhasm: ((uint32 *)&x1)[0] = in12
+# asm 1: movl <in12=int64#4d,>x1=stack128#1
+# asm 2: movl <in12=%ecx,>x1=0(%rsp)
+movl %ecx,0(%rsp)
+
+# qhasm: ((uint32 *)&x1)[1] = in1
+# asm 1: movl <in1=int64#5d,4+<x1=stack128#1
+# asm 2: movl <in1=%r8d,4+<x1=0(%rsp)
+movl %r8d,4+0(%rsp)
+
+# qhasm: ((uint32 *)&x1)[2] = in6
+# asm 1: movl <in6=int64#7d,8+<x1=stack128#1
+# asm 2: movl <in6=%eax,8+<x1=0(%rsp)
+movl %eax,8+0(%rsp)
+
+# qhasm: ((uint32 *)&x1)[3] = in11
+# asm 1: movl <in11=int64#9d,12+<x1=stack128#1
+# asm 2: movl <in11=%r11d,12+<x1=0(%rsp)
+movl %r11d,12+0(%rsp)
+
+# qhasm: in8 = 0
+# asm 1: mov $0,>in8=int64#4
+# asm 2: mov $0,>in8=%rcx
+mov $0,%rcx
+
+# qhasm: in13 = *(uint32 *) (k + 24)
+# asm 1: movl 24(<k=int64#8),>in13=int64#5d
+# asm 2: movl 24(<k=%r10),>in13=%r8d
+movl 24(%r10),%r8d
+
+# qhasm: in2 = *(uint32 *) (k + 4)
+# asm 1: movl 4(<k=int64#8),>in2=int64#7d
+# asm 2: movl 4(<k=%r10),>in2=%eax
+movl 4(%r10),%eax
+
+# qhasm: in7 = *(uint32 *) (iv + 4)
+# asm 1: movl 4(<iv=int64#3),>in7=int64#3d
+# asm 2: movl 4(<iv=%rdx),>in7=%edx
+movl 4(%rdx),%edx
+
+# qhasm: ((uint32 *)&x2)[0] = in8
+# asm 1: movl <in8=int64#4d,>x2=stack128#2
+# asm 2: movl <in8=%ecx,>x2=16(%rsp)
+movl %ecx,16(%rsp)
+
+# qhasm: ((uint32 *)&x2)[1] = in13
+# asm 1: movl <in13=int64#5d,4+<x2=stack128#2
+# asm 2: movl <in13=%r8d,4+<x2=16(%rsp)
+movl %r8d,4+16(%rsp)
+
+# qhasm: ((uint32 *)&x2)[2] = in2
+# asm 1: movl <in2=int64#7d,8+<x2=stack128#2
+# asm 2: movl <in2=%eax,8+<x2=16(%rsp)
+movl %eax,8+16(%rsp)
+
+# qhasm: ((uint32 *)&x2)[3] = in7
+# asm 1: movl <in7=int64#3d,12+<x2=stack128#2
+# asm 2: movl <in7=%edx,12+<x2=16(%rsp)
+movl %edx,12+16(%rsp)
+
+# qhasm: in4 = *(uint32 *) (k + 12)
+# asm 1: movl 12(<k=int64#8),>in4=int64#3d
+# asm 2: movl 12(<k=%r10),>in4=%edx
+movl 12(%r10),%edx
+
+# qhasm: in9 = 0
+# asm 1: mov $0,>in9=int64#4
+# asm 2: mov $0,>in9=%rcx
+mov $0,%rcx
+
+# qhasm: in14 = *(uint32 *) (k + 28)
+# asm 1: movl 28(<k=int64#8),>in14=int64#5d
+# asm 2: movl 28(<k=%r10),>in14=%r8d
+movl 28(%r10),%r8d
+
+# qhasm: in3 = *(uint32 *) (k + 8)
+# asm 1: movl 8(<k=int64#8),>in3=int64#7d
+# asm 2: movl 8(<k=%r10),>in3=%eax
+movl 8(%r10),%eax
+
+# qhasm: ((uint32 *)&x3)[0] = in4
+# asm 1: movl <in4=int64#3d,>x3=stack128#3
+# asm 2: movl <in4=%edx,>x3=32(%rsp)
+movl %edx,32(%rsp)
+
+# qhasm: ((uint32 *)&x3)[1] = in9
+# asm 1: movl <in9=int64#4d,4+<x3=stack128#3
+# asm 2: movl <in9=%ecx,4+<x3=32(%rsp)
+movl %ecx,4+32(%rsp)
+
+# qhasm: ((uint32 *)&x3)[2] = in14
+# asm 1: movl <in14=int64#5d,8+<x3=stack128#3
+# asm 2: movl <in14=%r8d,8+<x3=32(%rsp)
+movl %r8d,8+32(%rsp)
+
+# qhasm: ((uint32 *)&x3)[3] = in3
+# asm 1: movl <in3=int64#7d,12+<x3=stack128#3
+# asm 2: movl <in3=%eax,12+<x3=32(%rsp)
+movl %eax,12+32(%rsp)
+
+# qhasm: in0 = 1634760805
+# asm 1: mov $1634760805,>in0=int64#3
+# asm 2: mov $1634760805,>in0=%rdx
+mov $1634760805,%rdx
+
+# qhasm: in5 = 857760878
+# asm 1: mov $857760878,>in5=int64#4
+# asm 2: mov $857760878,>in5=%rcx
+mov $857760878,%rcx
+
+# qhasm: in10 = 2036477234
+# asm 1: mov $2036477234,>in10=int64#5
+# asm 2: mov $2036477234,>in10=%r8
+mov $2036477234,%r8
+
+# qhasm: in15 = 1797285236
+# asm 1: mov $1797285236,>in15=int64#7
+# asm 2: mov $1797285236,>in15=%rax
+mov $1797285236,%rax
+
+# qhasm: ((uint32 *)&x0)[0] = in0
+# asm 1: movl <in0=int64#3d,>x0=stack128#4
+# asm 2: movl <in0=%edx,>x0=48(%rsp)
+movl %edx,48(%rsp)
+
+# qhasm: ((uint32 *)&x0)[1] = in5
+# asm 1: movl <in5=int64#4d,4+<x0=stack128#4
+# asm 2: movl <in5=%ecx,4+<x0=48(%rsp)
+movl %ecx,4+48(%rsp)
+
+# qhasm: ((uint32 *)&x0)[2] = in10
+# asm 1: movl <in10=int64#5d,8+<x0=stack128#4
+# asm 2: movl <in10=%r8d,8+<x0=48(%rsp)
+movl %r8d,8+48(%rsp)
+
+# qhasm: ((uint32 *)&x0)[3] = in15
+# asm 1: movl <in15=int64#7d,12+<x0=stack128#4
+# asm 2: movl <in15=%eax,12+<x0=48(%rsp)
+movl %eax,12+48(%rsp)
+
+# qhasm: unsigned<? bytes - 256
+# asm 1: cmp $256,<bytes=int64#6
+# asm 2: cmp $256,<bytes=%r9
+cmp $256,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto bytesbetween1and255 if unsigned<
+jb ._bytesbetween1and255
+
+# qhasm: z0 = x0
+# asm 1: movdqa <x0=stack128#4,>z0=int6464#1
+# asm 2: movdqa <x0=48(%rsp),>z0=%xmm0
+movdqa 48(%rsp),%xmm0
+
+# qhasm: z5 = z0[1,1,1,1]
+# asm 1: pshufd $0x55,<z0=int6464#1,>z5=int6464#2
+# asm 2: pshufd $0x55,<z0=%xmm0,>z5=%xmm1
+pshufd $0x55,%xmm0,%xmm1
+
+# qhasm: z10 = z0[2,2,2,2]
+# asm 1: pshufd $0xaa,<z0=int6464#1,>z10=int6464#3
+# asm 2: pshufd $0xaa,<z0=%xmm0,>z10=%xmm2
+pshufd $0xaa,%xmm0,%xmm2
+
+# qhasm: z15 = z0[3,3,3,3]
+# asm 1: pshufd $0xff,<z0=int6464#1,>z15=int6464#4
+# asm 2: pshufd $0xff,<z0=%xmm0,>z15=%xmm3
+pshufd $0xff,%xmm0,%xmm3
+
+# qhasm: z0 = z0[0,0,0,0]
+# asm 1: pshufd $0x00,<z0=int6464#1,>z0=int6464#1
+# asm 2: pshufd $0x00,<z0=%xmm0,>z0=%xmm0
+pshufd $0x00,%xmm0,%xmm0
+
+# qhasm: orig5 = z5
+# asm 1: movdqa <z5=int6464#2,>orig5=stack128#5
+# asm 2: movdqa <z5=%xmm1,>orig5=64(%rsp)
+movdqa %xmm1,64(%rsp)
+
+# qhasm: orig10 = z10
+# asm 1: movdqa <z10=int6464#3,>orig10=stack128#6
+# asm 2: movdqa <z10=%xmm2,>orig10=80(%rsp)
+movdqa %xmm2,80(%rsp)
+
+# qhasm: orig15 = z15
+# asm 1: movdqa <z15=int6464#4,>orig15=stack128#7
+# asm 2: movdqa <z15=%xmm3,>orig15=96(%rsp)
+movdqa %xmm3,96(%rsp)
+
+# qhasm: orig0 = z0
+# asm 1: movdqa <z0=int6464#1,>orig0=stack128#8
+# asm 2: movdqa <z0=%xmm0,>orig0=112(%rsp)
+movdqa %xmm0,112(%rsp)
+
+# qhasm: z1 = x1
+# asm 1: movdqa <x1=stack128#1,>z1=int6464#1
+# asm 2: movdqa <x1=0(%rsp),>z1=%xmm0
+movdqa 0(%rsp),%xmm0
+
+# qhasm: z6 = z1[2,2,2,2]
+# asm 1: pshufd $0xaa,<z1=int6464#1,>z6=int6464#2
+# asm 2: pshufd $0xaa,<z1=%xmm0,>z6=%xmm1
+pshufd $0xaa,%xmm0,%xmm1
+
+# qhasm: z11 = z1[3,3,3,3]
+# asm 1: pshufd $0xff,<z1=int6464#1,>z11=int6464#3
+# asm 2: pshufd $0xff,<z1=%xmm0,>z11=%xmm2
+pshufd $0xff,%xmm0,%xmm2
+
+# qhasm: z12 = z1[0,0,0,0]
+# asm 1: pshufd $0x00,<z1=int6464#1,>z12=int6464#4
+# asm 2: pshufd $0x00,<z1=%xmm0,>z12=%xmm3
+pshufd $0x00,%xmm0,%xmm3
+
+# qhasm: z1 = z1[1,1,1,1]
+# asm 1: pshufd $0x55,<z1=int6464#1,>z1=int6464#1
+# asm 2: pshufd $0x55,<z1=%xmm0,>z1=%xmm0
+pshufd $0x55,%xmm0,%xmm0
+
+# qhasm: orig6 = z6
+# asm 1: movdqa <z6=int6464#2,>orig6=stack128#9
+# asm 2: movdqa <z6=%xmm1,>orig6=128(%rsp)
+movdqa %xmm1,128(%rsp)
+
+# qhasm: orig11 = z11
+# asm 1: movdqa <z11=int6464#3,>orig11=stack128#10
+# asm 2: movdqa <z11=%xmm2,>orig11=144(%rsp)
+movdqa %xmm2,144(%rsp)
+
+# qhasm: orig12 = z12
+# asm 1: movdqa <z12=int6464#4,>orig12=stack128#11
+# asm 2: movdqa <z12=%xmm3,>orig12=160(%rsp)
+movdqa %xmm3,160(%rsp)
+
+# qhasm: orig1 = z1
+# asm 1: movdqa <z1=int6464#1,>orig1=stack128#12
+# asm 2: movdqa <z1=%xmm0,>orig1=176(%rsp)
+movdqa %xmm0,176(%rsp)
+
+# qhasm: z2 = x2
+# asm 1: movdqa <x2=stack128#2,>z2=int6464#1
+# asm 2: movdqa <x2=16(%rsp),>z2=%xmm0
+movdqa 16(%rsp),%xmm0
+
+# qhasm: z7 = z2[3,3,3,3]
+# asm 1: pshufd $0xff,<z2=int6464#1,>z7=int6464#2
+# asm 2: pshufd $0xff,<z2=%xmm0,>z7=%xmm1
+pshufd $0xff,%xmm0,%xmm1
+
+# qhasm: z13 = z2[1,1,1,1]
+# asm 1: pshufd $0x55,<z2=int6464#1,>z13=int6464#3
+# asm 2: pshufd $0x55,<z2=%xmm0,>z13=%xmm2
+pshufd $0x55,%xmm0,%xmm2
+
+# qhasm: z2 = z2[2,2,2,2]
+# asm 1: pshufd $0xaa,<z2=int6464#1,>z2=int6464#1
+# asm 2: pshufd $0xaa,<z2=%xmm0,>z2=%xmm0
+pshufd $0xaa,%xmm0,%xmm0
+
+# qhasm: orig7 = z7
+# asm 1: movdqa <z7=int6464#2,>orig7=stack128#13
+# asm 2: movdqa <z7=%xmm1,>orig7=192(%rsp)
+movdqa %xmm1,192(%rsp)
+
+# qhasm: orig13 = z13
+# asm 1: movdqa <z13=int6464#3,>orig13=stack128#14
+# asm 2: movdqa <z13=%xmm2,>orig13=208(%rsp)
+movdqa %xmm2,208(%rsp)
+
+# qhasm: orig2 = z2
+# asm 1: movdqa <z2=int6464#1,>orig2=stack128#15
+# asm 2: movdqa <z2=%xmm0,>orig2=224(%rsp)
+movdqa %xmm0,224(%rsp)
+
+# qhasm: z3 = x3
+# asm 1: movdqa <x3=stack128#3,>z3=int6464#1
+# asm 2: movdqa <x3=32(%rsp),>z3=%xmm0
+movdqa 32(%rsp),%xmm0
+
+# qhasm: z4 = z3[0,0,0,0]
+# asm 1: pshufd $0x00,<z3=int6464#1,>z4=int6464#2
+# asm 2: pshufd $0x00,<z3=%xmm0,>z4=%xmm1
+pshufd $0x00,%xmm0,%xmm1
+
+# qhasm: z14 = z3[2,2,2,2]
+# asm 1: pshufd $0xaa,<z3=int6464#1,>z14=int6464#3
+# asm 2: pshufd $0xaa,<z3=%xmm0,>z14=%xmm2
+pshufd $0xaa,%xmm0,%xmm2
+
+# qhasm: z3 = z3[3,3,3,3]
+# asm 1: pshufd $0xff,<z3=int6464#1,>z3=int6464#1
+# asm 2: pshufd $0xff,<z3=%xmm0,>z3=%xmm0
+pshufd $0xff,%xmm0,%xmm0
+
+# qhasm: orig4 = z4
+# asm 1: movdqa <z4=int6464#2,>orig4=stack128#16
+# asm 2: movdqa <z4=%xmm1,>orig4=240(%rsp)
+movdqa %xmm1,240(%rsp)
+
+# qhasm: orig14 = z14
+# asm 1: movdqa <z14=int6464#3,>orig14=stack128#17
+# asm 2: movdqa <z14=%xmm2,>orig14=256(%rsp)
+movdqa %xmm2,256(%rsp)
+
+# qhasm: orig3 = z3
+# asm 1: movdqa <z3=int6464#1,>orig3=stack128#18
+# asm 2: movdqa <z3=%xmm0,>orig3=272(%rsp)
+movdqa %xmm0,272(%rsp)
+
+# qhasm: bytesatleast256:
+._bytesatleast256:
+
+# qhasm: in8 = ((uint32 *)&x2)[0]
+# asm 1: movl <x2=stack128#2,>in8=int64#3d
+# asm 2: movl <x2=16(%rsp),>in8=%edx
+movl 16(%rsp),%edx
+
+# qhasm: in9 = ((uint32 *)&x3)[1]
+# asm 1: movl 4+<x3=stack128#3,>in9=int64#4d
+# asm 2: movl 4+<x3=32(%rsp),>in9=%ecx
+movl 4+32(%rsp),%ecx
+
+# qhasm: ((uint32 *) &orig8)[0] = in8
+# asm 1: movl <in8=int64#3d,>orig8=stack128#19
+# asm 2: movl <in8=%edx,>orig8=288(%rsp)
+movl %edx,288(%rsp)
+
+# qhasm: ((uint32 *) &orig9)[0] = in9
+# asm 1: movl <in9=int64#4d,>orig9=stack128#20
+# asm 2: movl <in9=%ecx,>orig9=304(%rsp)
+movl %ecx,304(%rsp)
+
+# qhasm: in8 += 1
+# asm 1: add $1,<in8=int64#3
+# asm 2: add $1,<in8=%rdx
+add $1,%rdx
+
+# qhasm: in9 <<= 32
+# asm 1: shl $32,<in9=int64#4
+# asm 2: shl $32,<in9=%rcx
+shl $32,%rcx
+
+# qhasm: in8 += in9
+# asm 1: add <in9=int64#4,<in8=int64#3
+# asm 2: add <in9=%rcx,<in8=%rdx
+add %rcx,%rdx
+
+# qhasm: in9 = in8
+# asm 1: mov <in8=int64#3,>in9=int64#4
+# asm 2: mov <in8=%rdx,>in9=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint64) in9 >>= 32
+# asm 1: shr $32,<in9=int64#4
+# asm 2: shr $32,<in9=%rcx
+shr $32,%rcx
+
+# qhasm: ((uint32 *) &orig8)[1] = in8
+# asm 1: movl <in8=int64#3d,4+<orig8=stack128#19
+# asm 2: movl <in8=%edx,4+<orig8=288(%rsp)
+movl %edx,4+288(%rsp)
+
+# qhasm: ((uint32 *) &orig9)[1] = in9
+# asm 1: movl <in9=int64#4d,4+<orig9=stack128#20
+# asm 2: movl <in9=%ecx,4+<orig9=304(%rsp)
+movl %ecx,4+304(%rsp)
+
+# qhasm: in8 += 1
+# asm 1: add $1,<in8=int64#3
+# asm 2: add $1,<in8=%rdx
+add $1,%rdx
+
+# qhasm: in9 <<= 32
+# asm 1: shl $32,<in9=int64#4
+# asm 2: shl $32,<in9=%rcx
+shl $32,%rcx
+
+# qhasm: in8 += in9
+# asm 1: add <in9=int64#4,<in8=int64#3
+# asm 2: add <in9=%rcx,<in8=%rdx
+add %rcx,%rdx
+
+# qhasm: in9 = in8
+# asm 1: mov <in8=int64#3,>in9=int64#4
+# asm 2: mov <in8=%rdx,>in9=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint64) in9 >>= 32
+# asm 1: shr $32,<in9=int64#4
+# asm 2: shr $32,<in9=%rcx
+shr $32,%rcx
+
+# qhasm: ((uint32 *) &orig8)[2] = in8
+# asm 1: movl <in8=int64#3d,8+<orig8=stack128#19
+# asm 2: movl <in8=%edx,8+<orig8=288(%rsp)
+movl %edx,8+288(%rsp)
+
+# qhasm: ((uint32 *) &orig9)[2] = in9
+# asm 1: movl <in9=int64#4d,8+<orig9=stack128#20
+# asm 2: movl <in9=%ecx,8+<orig9=304(%rsp)
+movl %ecx,8+304(%rsp)
+
+# qhasm: in8 += 1
+# asm 1: add $1,<in8=int64#3
+# asm 2: add $1,<in8=%rdx
+add $1,%rdx
+
+# qhasm: in9 <<= 32
+# asm 1: shl $32,<in9=int64#4
+# asm 2: shl $32,<in9=%rcx
+shl $32,%rcx
+
+# qhasm: in8 += in9
+# asm 1: add <in9=int64#4,<in8=int64#3
+# asm 2: add <in9=%rcx,<in8=%rdx
+add %rcx,%rdx
+
+# qhasm: in9 = in8
+# asm 1: mov <in8=int64#3,>in9=int64#4
+# asm 2: mov <in8=%rdx,>in9=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint64) in9 >>= 32
+# asm 1: shr $32,<in9=int64#4
+# asm 2: shr $32,<in9=%rcx
+shr $32,%rcx
+
+# qhasm: ((uint32 *) &orig8)[3] = in8
+# asm 1: movl <in8=int64#3d,12+<orig8=stack128#19
+# asm 2: movl <in8=%edx,12+<orig8=288(%rsp)
+movl %edx,12+288(%rsp)
+
+# qhasm: ((uint32 *) &orig9)[3] = in9
+# asm 1: movl <in9=int64#4d,12+<orig9=stack128#20
+# asm 2: movl <in9=%ecx,12+<orig9=304(%rsp)
+movl %ecx,12+304(%rsp)
+
+# qhasm: in8 += 1
+# asm 1: add $1,<in8=int64#3
+# asm 2: add $1,<in8=%rdx
+add $1,%rdx
+
+# qhasm: in9 <<= 32
+# asm 1: shl $32,<in9=int64#4
+# asm 2: shl $32,<in9=%rcx
+shl $32,%rcx
+
+# qhasm: in8 += in9
+# asm 1: add <in9=int64#4,<in8=int64#3
+# asm 2: add <in9=%rcx,<in8=%rdx
+add %rcx,%rdx
+
+# qhasm: in9 = in8
+# asm 1: mov <in8=int64#3,>in9=int64#4
+# asm 2: mov <in8=%rdx,>in9=%rcx
+mov %rdx,%rcx
+
+# qhasm: (uint64) in9 >>= 32
+# asm 1: shr $32,<in9=int64#4
+# asm 2: shr $32,<in9=%rcx
+shr $32,%rcx
+
+# qhasm: ((uint32 *)&x2)[0] = in8
+# asm 1: movl <in8=int64#3d,>x2=stack128#2
+# asm 2: movl <in8=%edx,>x2=16(%rsp)
+movl %edx,16(%rsp)
+
+# qhasm: ((uint32 *)&x3)[1] = in9
+# asm 1: movl <in9=int64#4d,4+<x3=stack128#3
+# asm 2: movl <in9=%ecx,4+<x3=32(%rsp)
+movl %ecx,4+32(%rsp)
+
+# qhasm: bytes_backup = bytes
+# asm 1: movq <bytes=int64#6,>bytes_backup=stack64#8
+# asm 2: movq <bytes=%r9,>bytes_backup=408(%rsp)
+movq %r9,408(%rsp)
+
+# qhasm: i = 12
+# asm 1: mov $12,>i=int64#3
+# asm 2: mov $12,>i=%rdx
+mov $12,%rdx
+
+# qhasm: z5 = orig5
+# asm 1: movdqa <orig5=stack128#5,>z5=int6464#1
+# asm 2: movdqa <orig5=64(%rsp),>z5=%xmm0
+movdqa 64(%rsp),%xmm0
+
+# qhasm: z10 = orig10
+# asm 1: movdqa <orig10=stack128#6,>z10=int6464#2
+# asm 2: movdqa <orig10=80(%rsp),>z10=%xmm1
+movdqa 80(%rsp),%xmm1
+
+# qhasm: z15 = orig15
+# asm 1: movdqa <orig15=stack128#7,>z15=int6464#3
+# asm 2: movdqa <orig15=96(%rsp),>z15=%xmm2
+movdqa 96(%rsp),%xmm2
+
+# qhasm: z14 = orig14
+# asm 1: movdqa <orig14=stack128#17,>z14=int6464#4
+# asm 2: movdqa <orig14=256(%rsp),>z14=%xmm3
+movdqa 256(%rsp),%xmm3
+
+# qhasm: z3 = orig3
+# asm 1: movdqa <orig3=stack128#18,>z3=int6464#5
+# asm 2: movdqa <orig3=272(%rsp),>z3=%xmm4
+movdqa 272(%rsp),%xmm4
+
+# qhasm: z6 = orig6
+# asm 1: movdqa <orig6=stack128#9,>z6=int6464#6
+# asm 2: movdqa <orig6=128(%rsp),>z6=%xmm5
+movdqa 128(%rsp),%xmm5
+
+# qhasm: z11 = orig11
+# asm 1: movdqa <orig11=stack128#10,>z11=int6464#7
+# asm 2: movdqa <orig11=144(%rsp),>z11=%xmm6
+movdqa 144(%rsp),%xmm6
+
+# qhasm: z1 = orig1
+# asm 1: movdqa <orig1=stack128#12,>z1=int6464#8
+# asm 2: movdqa <orig1=176(%rsp),>z1=%xmm7
+movdqa 176(%rsp),%xmm7
+
+# qhasm: z7 = orig7
+# asm 1: movdqa <orig7=stack128#13,>z7=int6464#9
+# asm 2: movdqa <orig7=192(%rsp),>z7=%xmm8
+movdqa 192(%rsp),%xmm8
+
+# qhasm: z13 = orig13
+# asm 1: movdqa <orig13=stack128#14,>z13=int6464#10
+# asm 2: movdqa <orig13=208(%rsp),>z13=%xmm9
+movdqa 208(%rsp),%xmm9
+
+# qhasm: z2 = orig2
+# asm 1: movdqa <orig2=stack128#15,>z2=int6464#11
+# asm 2: movdqa <orig2=224(%rsp),>z2=%xmm10
+movdqa 224(%rsp),%xmm10
+
+# qhasm: z9 = orig9
+# asm 1: movdqa <orig9=stack128#20,>z9=int6464#12
+# asm 2: movdqa <orig9=304(%rsp),>z9=%xmm11
+movdqa 304(%rsp),%xmm11
+
+# qhasm: z0 = orig0
+# asm 1: movdqa <orig0=stack128#8,>z0=int6464#13
+# asm 2: movdqa <orig0=112(%rsp),>z0=%xmm12
+movdqa 112(%rsp),%xmm12
+
+# qhasm: z12 = orig12
+# asm 1: movdqa <orig12=stack128#11,>z12=int6464#14
+# asm 2: movdqa <orig12=160(%rsp),>z12=%xmm13
+movdqa 160(%rsp),%xmm13
+
+# qhasm: z4 = orig4
+# asm 1: movdqa <orig4=stack128#16,>z4=int6464#15
+# asm 2: movdqa <orig4=240(%rsp),>z4=%xmm14
+movdqa 240(%rsp),%xmm14
+
+# qhasm: z8 = orig8
+# asm 1: movdqa <orig8=stack128#19,>z8=int6464#16
+# asm 2: movdqa <orig8=288(%rsp),>z8=%xmm15
+movdqa 288(%rsp),%xmm15
+
+# qhasm: mainloop1:
+._mainloop1:
+
+# qhasm: z10_stack = z10
+# asm 1: movdqa <z10=int6464#2,>z10_stack=stack128#21
+# asm 2: movdqa <z10=%xmm1,>z10_stack=320(%rsp)
+movdqa %xmm1,320(%rsp)
+
+# qhasm: z15_stack = z15
+# asm 1: movdqa <z15=int6464#3,>z15_stack=stack128#22
+# asm 2: movdqa <z15=%xmm2,>z15_stack=336(%rsp)
+movdqa %xmm2,336(%rsp)
+
+# qhasm: y4 = z12
+# asm 1: movdqa <z12=int6464#14,>y4=int6464#2
+# asm 2: movdqa <z12=%xmm13,>y4=%xmm1
+movdqa %xmm13,%xmm1
+
+# qhasm: uint32323232 y4 += z0
+# asm 1: paddd <z0=int6464#13,<y4=int6464#2
+# asm 2: paddd <z0=%xmm12,<y4=%xmm1
+paddd %xmm12,%xmm1
+
+# qhasm: r4 = y4
+# asm 1: movdqa <y4=int6464#2,>r4=int6464#3
+# asm 2: movdqa <y4=%xmm1,>r4=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y4 <<= 7
+# asm 1: pslld $7,<y4=int6464#2
+# asm 2: pslld $7,<y4=%xmm1
+pslld $7,%xmm1
+
+# qhasm: z4 ^= y4
+# asm 1: pxor <y4=int6464#2,<z4=int6464#15
+# asm 2: pxor <y4=%xmm1,<z4=%xmm14
+pxor %xmm1,%xmm14
+
+# qhasm: uint32323232 r4 >>= 25
+# asm 1: psrld $25,<r4=int6464#3
+# asm 2: psrld $25,<r4=%xmm2
+psrld $25,%xmm2
+
+# qhasm: z4 ^= r4
+# asm 1: pxor <r4=int6464#3,<z4=int6464#15
+# asm 2: pxor <r4=%xmm2,<z4=%xmm14
+pxor %xmm2,%xmm14
+
+# qhasm: y9 = z1
+# asm 1: movdqa <z1=int6464#8,>y9=int6464#2
+# asm 2: movdqa <z1=%xmm7,>y9=%xmm1
+movdqa %xmm7,%xmm1
+
+# qhasm: uint32323232 y9 += z5
+# asm 1: paddd <z5=int6464#1,<y9=int6464#2
+# asm 2: paddd <z5=%xmm0,<y9=%xmm1
+paddd %xmm0,%xmm1
+
+# qhasm: r9 = y9
+# asm 1: movdqa <y9=int6464#2,>r9=int6464#3
+# asm 2: movdqa <y9=%xmm1,>r9=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y9 <<= 7
+# asm 1: pslld $7,<y9=int6464#2
+# asm 2: pslld $7,<y9=%xmm1
+pslld $7,%xmm1
+
+# qhasm: z9 ^= y9
+# asm 1: pxor <y9=int6464#2,<z9=int6464#12
+# asm 2: pxor <y9=%xmm1,<z9=%xmm11
+pxor %xmm1,%xmm11
+
+# qhasm: uint32323232 r9 >>= 25
+# asm 1: psrld $25,<r9=int6464#3
+# asm 2: psrld $25,<r9=%xmm2
+psrld $25,%xmm2
+
+# qhasm: z9 ^= r9
+# asm 1: pxor <r9=int6464#3,<z9=int6464#12
+# asm 2: pxor <r9=%xmm2,<z9=%xmm11
+pxor %xmm2,%xmm11
+
+# qhasm: y8 = z0
+# asm 1: movdqa <z0=int6464#13,>y8=int6464#2
+# asm 2: movdqa <z0=%xmm12,>y8=%xmm1
+movdqa %xmm12,%xmm1
+
+# qhasm: uint32323232 y8 += z4
+# asm 1: paddd <z4=int6464#15,<y8=int6464#2
+# asm 2: paddd <z4=%xmm14,<y8=%xmm1
+paddd %xmm14,%xmm1
+
+# qhasm: r8 = y8
+# asm 1: movdqa <y8=int6464#2,>r8=int6464#3
+# asm 2: movdqa <y8=%xmm1,>r8=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y8 <<= 9
+# asm 1: pslld $9,<y8=int6464#2
+# asm 2: pslld $9,<y8=%xmm1
+pslld $9,%xmm1
+
+# qhasm: z8 ^= y8
+# asm 1: pxor <y8=int6464#2,<z8=int6464#16
+# asm 2: pxor <y8=%xmm1,<z8=%xmm15
+pxor %xmm1,%xmm15
+
+# qhasm: uint32323232 r8 >>= 23
+# asm 1: psrld $23,<r8=int6464#3
+# asm 2: psrld $23,<r8=%xmm2
+psrld $23,%xmm2
+
+# qhasm: z8 ^= r8
+# asm 1: pxor <r8=int6464#3,<z8=int6464#16
+# asm 2: pxor <r8=%xmm2,<z8=%xmm15
+pxor %xmm2,%xmm15
+
+# qhasm: y13 = z5
+# asm 1: movdqa <z5=int6464#1,>y13=int6464#2
+# asm 2: movdqa <z5=%xmm0,>y13=%xmm1
+movdqa %xmm0,%xmm1
+
+# qhasm: uint32323232 y13 += z9
+# asm 1: paddd <z9=int6464#12,<y13=int6464#2
+# asm 2: paddd <z9=%xmm11,<y13=%xmm1
+paddd %xmm11,%xmm1
+
+# qhasm: r13 = y13
+# asm 1: movdqa <y13=int6464#2,>r13=int6464#3
+# asm 2: movdqa <y13=%xmm1,>r13=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y13 <<= 9
+# asm 1: pslld $9,<y13=int6464#2
+# asm 2: pslld $9,<y13=%xmm1
+pslld $9,%xmm1
+
+# qhasm: z13 ^= y13
+# asm 1: pxor <y13=int6464#2,<z13=int6464#10
+# asm 2: pxor <y13=%xmm1,<z13=%xmm9
+pxor %xmm1,%xmm9
+
+# qhasm: uint32323232 r13 >>= 23
+# asm 1: psrld $23,<r13=int6464#3
+# asm 2: psrld $23,<r13=%xmm2
+psrld $23,%xmm2
+
+# qhasm: z13 ^= r13
+# asm 1: pxor <r13=int6464#3,<z13=int6464#10
+# asm 2: pxor <r13=%xmm2,<z13=%xmm9
+pxor %xmm2,%xmm9
+
+# qhasm: y12 = z4
+# asm 1: movdqa <z4=int6464#15,>y12=int6464#2
+# asm 2: movdqa <z4=%xmm14,>y12=%xmm1
+movdqa %xmm14,%xmm1
+
+# qhasm: uint32323232 y12 += z8
+# asm 1: paddd <z8=int6464#16,<y12=int6464#2
+# asm 2: paddd <z8=%xmm15,<y12=%xmm1
+paddd %xmm15,%xmm1
+
+# qhasm: r12 = y12
+# asm 1: movdqa <y12=int6464#2,>r12=int6464#3
+# asm 2: movdqa <y12=%xmm1,>r12=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y12 <<= 13
+# asm 1: pslld $13,<y12=int6464#2
+# asm 2: pslld $13,<y12=%xmm1
+pslld $13,%xmm1
+
+# qhasm: z12 ^= y12
+# asm 1: pxor <y12=int6464#2,<z12=int6464#14
+# asm 2: pxor <y12=%xmm1,<z12=%xmm13
+pxor %xmm1,%xmm13
+
+# qhasm: uint32323232 r12 >>= 19
+# asm 1: psrld $19,<r12=int6464#3
+# asm 2: psrld $19,<r12=%xmm2
+psrld $19,%xmm2
+
+# qhasm: z12 ^= r12
+# asm 1: pxor <r12=int6464#3,<z12=int6464#14
+# asm 2: pxor <r12=%xmm2,<z12=%xmm13
+pxor %xmm2,%xmm13
+
+# qhasm: y1 = z9
+# asm 1: movdqa <z9=int6464#12,>y1=int6464#2
+# asm 2: movdqa <z9=%xmm11,>y1=%xmm1
+movdqa %xmm11,%xmm1
+
+# qhasm: uint32323232 y1 += z13
+# asm 1: paddd <z13=int6464#10,<y1=int6464#2
+# asm 2: paddd <z13=%xmm9,<y1=%xmm1
+paddd %xmm9,%xmm1
+
+# qhasm: r1 = y1
+# asm 1: movdqa <y1=int6464#2,>r1=int6464#3
+# asm 2: movdqa <y1=%xmm1,>r1=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y1 <<= 13
+# asm 1: pslld $13,<y1=int6464#2
+# asm 2: pslld $13,<y1=%xmm1
+pslld $13,%xmm1
+
+# qhasm: z1 ^= y1
+# asm 1: pxor <y1=int6464#2,<z1=int6464#8
+# asm 2: pxor <y1=%xmm1,<z1=%xmm7
+pxor %xmm1,%xmm7
+
+# qhasm: uint32323232 r1 >>= 19
+# asm 1: psrld $19,<r1=int6464#3
+# asm 2: psrld $19,<r1=%xmm2
+psrld $19,%xmm2
+
+# qhasm: z1 ^= r1
+# asm 1: pxor <r1=int6464#3,<z1=int6464#8
+# asm 2: pxor <r1=%xmm2,<z1=%xmm7
+pxor %xmm2,%xmm7
+
+# qhasm: y0 = z8
+# asm 1: movdqa <z8=int6464#16,>y0=int6464#2
+# asm 2: movdqa <z8=%xmm15,>y0=%xmm1
+movdqa %xmm15,%xmm1
+
+# qhasm: uint32323232 y0 += z12
+# asm 1: paddd <z12=int6464#14,<y0=int6464#2
+# asm 2: paddd <z12=%xmm13,<y0=%xmm1
+paddd %xmm13,%xmm1
+
+# qhasm: r0 = y0
+# asm 1: movdqa <y0=int6464#2,>r0=int6464#3
+# asm 2: movdqa <y0=%xmm1,>r0=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y0 <<= 18
+# asm 1: pslld $18,<y0=int6464#2
+# asm 2: pslld $18,<y0=%xmm1
+pslld $18,%xmm1
+
+# qhasm: z0 ^= y0
+# asm 1: pxor <y0=int6464#2,<z0=int6464#13
+# asm 2: pxor <y0=%xmm1,<z0=%xmm12
+pxor %xmm1,%xmm12
+
+# qhasm: uint32323232 r0 >>= 14
+# asm 1: psrld $14,<r0=int6464#3
+# asm 2: psrld $14,<r0=%xmm2
+psrld $14,%xmm2
+
+# qhasm: z0 ^= r0
+# asm 1: pxor <r0=int6464#3,<z0=int6464#13
+# asm 2: pxor <r0=%xmm2,<z0=%xmm12
+pxor %xmm2,%xmm12
+
+# qhasm: z10 = z10_stack
+# asm 1: movdqa <z10_stack=stack128#21,>z10=int6464#2
+# asm 2: movdqa <z10_stack=320(%rsp),>z10=%xmm1
+movdqa 320(%rsp),%xmm1
+
+# qhasm: z0_stack = z0
+# asm 1: movdqa <z0=int6464#13,>z0_stack=stack128#21
+# asm 2: movdqa <z0=%xmm12,>z0_stack=320(%rsp)
+movdqa %xmm12,320(%rsp)
+
+# qhasm: y5 = z13
+# asm 1: movdqa <z13=int6464#10,>y5=int6464#3
+# asm 2: movdqa <z13=%xmm9,>y5=%xmm2
+movdqa %xmm9,%xmm2
+
+# qhasm: uint32323232 y5 += z1
+# asm 1: paddd <z1=int6464#8,<y5=int6464#3
+# asm 2: paddd <z1=%xmm7,<y5=%xmm2
+paddd %xmm7,%xmm2
+
+# qhasm: r5 = y5
+# asm 1: movdqa <y5=int6464#3,>r5=int6464#13
+# asm 2: movdqa <y5=%xmm2,>r5=%xmm12
+movdqa %xmm2,%xmm12
+
+# qhasm: uint32323232 y5 <<= 18
+# asm 1: pslld $18,<y5=int6464#3
+# asm 2: pslld $18,<y5=%xmm2
+pslld $18,%xmm2
+
+# qhasm: z5 ^= y5
+# asm 1: pxor <y5=int6464#3,<z5=int6464#1
+# asm 2: pxor <y5=%xmm2,<z5=%xmm0
+pxor %xmm2,%xmm0
+
+# qhasm: uint32323232 r5 >>= 14
+# asm 1: psrld $14,<r5=int6464#13
+# asm 2: psrld $14,<r5=%xmm12
+psrld $14,%xmm12
+
+# qhasm: z5 ^= r5
+# asm 1: pxor <r5=int6464#13,<z5=int6464#1
+# asm 2: pxor <r5=%xmm12,<z5=%xmm0
+pxor %xmm12,%xmm0
+
+# qhasm: y14 = z6
+# asm 1: movdqa <z6=int6464#6,>y14=int6464#3
+# asm 2: movdqa <z6=%xmm5,>y14=%xmm2
+movdqa %xmm5,%xmm2
+
+# qhasm: uint32323232 y14 += z10
+# asm 1: paddd <z10=int6464#2,<y14=int6464#3
+# asm 2: paddd <z10=%xmm1,<y14=%xmm2
+paddd %xmm1,%xmm2
+
+# qhasm: r14 = y14
+# asm 1: movdqa <y14=int6464#3,>r14=int6464#13
+# asm 2: movdqa <y14=%xmm2,>r14=%xmm12
+movdqa %xmm2,%xmm12
+
+# qhasm: uint32323232 y14 <<= 7
+# asm 1: pslld $7,<y14=int6464#3
+# asm 2: pslld $7,<y14=%xmm2
+pslld $7,%xmm2
+
+# qhasm: z14 ^= y14
+# asm 1: pxor <y14=int6464#3,<z14=int6464#4
+# asm 2: pxor <y14=%xmm2,<z14=%xmm3
+pxor %xmm2,%xmm3
+
+# qhasm: uint32323232 r14 >>= 25
+# asm 1: psrld $25,<r14=int6464#13
+# asm 2: psrld $25,<r14=%xmm12
+psrld $25,%xmm12
+
+# qhasm: z14 ^= r14
+# asm 1: pxor <r14=int6464#13,<z14=int6464#4
+# asm 2: pxor <r14=%xmm12,<z14=%xmm3
+pxor %xmm12,%xmm3
+
+# qhasm: z15 = z15_stack
+# asm 1: movdqa <z15_stack=stack128#22,>z15=int6464#3
+# asm 2: movdqa <z15_stack=336(%rsp),>z15=%xmm2
+movdqa 336(%rsp),%xmm2
+
+# qhasm: z5_stack = z5
+# asm 1: movdqa <z5=int6464#1,>z5_stack=stack128#22
+# asm 2: movdqa <z5=%xmm0,>z5_stack=336(%rsp)
+movdqa %xmm0,336(%rsp)
+
+# qhasm: y3 = z11
+# asm 1: movdqa <z11=int6464#7,>y3=int6464#1
+# asm 2: movdqa <z11=%xmm6,>y3=%xmm0
+movdqa %xmm6,%xmm0
+
+# qhasm: uint32323232 y3 += z15
+# asm 1: paddd <z15=int6464#3,<y3=int6464#1
+# asm 2: paddd <z15=%xmm2,<y3=%xmm0
+paddd %xmm2,%xmm0
+
+# qhasm: r3 = y3
+# asm 1: movdqa <y3=int6464#1,>r3=int6464#13
+# asm 2: movdqa <y3=%xmm0,>r3=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y3 <<= 7
+# asm 1: pslld $7,<y3=int6464#1
+# asm 2: pslld $7,<y3=%xmm0
+pslld $7,%xmm0
+
+# qhasm: z3 ^= y3
+# asm 1: pxor <y3=int6464#1,<z3=int6464#5
+# asm 2: pxor <y3=%xmm0,<z3=%xmm4
+pxor %xmm0,%xmm4
+
+# qhasm: uint32323232 r3 >>= 25
+# asm 1: psrld $25,<r3=int6464#13
+# asm 2: psrld $25,<r3=%xmm12
+psrld $25,%xmm12
+
+# qhasm: z3 ^= r3
+# asm 1: pxor <r3=int6464#13,<z3=int6464#5
+# asm 2: pxor <r3=%xmm12,<z3=%xmm4
+pxor %xmm12,%xmm4
+
+# qhasm: y2 = z10
+# asm 1: movdqa <z10=int6464#2,>y2=int6464#1
+# asm 2: movdqa <z10=%xmm1,>y2=%xmm0
+movdqa %xmm1,%xmm0
+
+# qhasm: uint32323232 y2 += z14
+# asm 1: paddd <z14=int6464#4,<y2=int6464#1
+# asm 2: paddd <z14=%xmm3,<y2=%xmm0
+paddd %xmm3,%xmm0
+
+# qhasm: r2 = y2
+# asm 1: movdqa <y2=int6464#1,>r2=int6464#13
+# asm 2: movdqa <y2=%xmm0,>r2=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y2 <<= 9
+# asm 1: pslld $9,<y2=int6464#1
+# asm 2: pslld $9,<y2=%xmm0
+pslld $9,%xmm0
+
+# qhasm: z2 ^= y2
+# asm 1: pxor <y2=int6464#1,<z2=int6464#11
+# asm 2: pxor <y2=%xmm0,<z2=%xmm10
+pxor %xmm0,%xmm10
+
+# qhasm: uint32323232 r2 >>= 23
+# asm 1: psrld $23,<r2=int6464#13
+# asm 2: psrld $23,<r2=%xmm12
+psrld $23,%xmm12
+
+# qhasm: z2 ^= r2
+# asm 1: pxor <r2=int6464#13,<z2=int6464#11
+# asm 2: pxor <r2=%xmm12,<z2=%xmm10
+pxor %xmm12,%xmm10
+
+# qhasm: y7 = z15
+# asm 1: movdqa <z15=int6464#3,>y7=int6464#1
+# asm 2: movdqa <z15=%xmm2,>y7=%xmm0
+movdqa %xmm2,%xmm0
+
+# qhasm: uint32323232 y7 += z3
+# asm 1: paddd <z3=int6464#5,<y7=int6464#1
+# asm 2: paddd <z3=%xmm4,<y7=%xmm0
+paddd %xmm4,%xmm0
+
+# qhasm: r7 = y7
+# asm 1: movdqa <y7=int6464#1,>r7=int6464#13
+# asm 2: movdqa <y7=%xmm0,>r7=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y7 <<= 9
+# asm 1: pslld $9,<y7=int6464#1
+# asm 2: pslld $9,<y7=%xmm0
+pslld $9,%xmm0
+
+# qhasm: z7 ^= y7
+# asm 1: pxor <y7=int6464#1,<z7=int6464#9
+# asm 2: pxor <y7=%xmm0,<z7=%xmm8
+pxor %xmm0,%xmm8
+
+# qhasm: uint32323232 r7 >>= 23
+# asm 1: psrld $23,<r7=int6464#13
+# asm 2: psrld $23,<r7=%xmm12
+psrld $23,%xmm12
+
+# qhasm: z7 ^= r7
+# asm 1: pxor <r7=int6464#13,<z7=int6464#9
+# asm 2: pxor <r7=%xmm12,<z7=%xmm8
+pxor %xmm12,%xmm8
+
+# qhasm: y6 = z14
+# asm 1: movdqa <z14=int6464#4,>y6=int6464#1
+# asm 2: movdqa <z14=%xmm3,>y6=%xmm0
+movdqa %xmm3,%xmm0
+
+# qhasm: uint32323232 y6 += z2
+# asm 1: paddd <z2=int6464#11,<y6=int6464#1
+# asm 2: paddd <z2=%xmm10,<y6=%xmm0
+paddd %xmm10,%xmm0
+
+# qhasm: r6 = y6
+# asm 1: movdqa <y6=int6464#1,>r6=int6464#13
+# asm 2: movdqa <y6=%xmm0,>r6=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y6 <<= 13
+# asm 1: pslld $13,<y6=int6464#1
+# asm 2: pslld $13,<y6=%xmm0
+pslld $13,%xmm0
+
+# qhasm: z6 ^= y6
+# asm 1: pxor <y6=int6464#1,<z6=int6464#6
+# asm 2: pxor <y6=%xmm0,<z6=%xmm5
+pxor %xmm0,%xmm5
+
+# qhasm: uint32323232 r6 >>= 19
+# asm 1: psrld $19,<r6=int6464#13
+# asm 2: psrld $19,<r6=%xmm12
+psrld $19,%xmm12
+
+# qhasm: z6 ^= r6
+# asm 1: pxor <r6=int6464#13,<z6=int6464#6
+# asm 2: pxor <r6=%xmm12,<z6=%xmm5
+pxor %xmm12,%xmm5
+
+# qhasm: y11 = z3
+# asm 1: movdqa <z3=int6464#5,>y11=int6464#1
+# asm 2: movdqa <z3=%xmm4,>y11=%xmm0
+movdqa %xmm4,%xmm0
+
+# qhasm: uint32323232 y11 += z7
+# asm 1: paddd <z7=int6464#9,<y11=int6464#1
+# asm 2: paddd <z7=%xmm8,<y11=%xmm0
+paddd %xmm8,%xmm0
+
+# qhasm: r11 = y11
+# asm 1: movdqa <y11=int6464#1,>r11=int6464#13
+# asm 2: movdqa <y11=%xmm0,>r11=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y11 <<= 13
+# asm 1: pslld $13,<y11=int6464#1
+# asm 2: pslld $13,<y11=%xmm0
+pslld $13,%xmm0
+
+# qhasm: z11 ^= y11
+# asm 1: pxor <y11=int6464#1,<z11=int6464#7
+# asm 2: pxor <y11=%xmm0,<z11=%xmm6
+pxor %xmm0,%xmm6
+
+# qhasm: uint32323232 r11 >>= 19
+# asm 1: psrld $19,<r11=int6464#13
+# asm 2: psrld $19,<r11=%xmm12
+psrld $19,%xmm12
+
+# qhasm: z11 ^= r11
+# asm 1: pxor <r11=int6464#13,<z11=int6464#7
+# asm 2: pxor <r11=%xmm12,<z11=%xmm6
+pxor %xmm12,%xmm6
+
+# qhasm: y10 = z2
+# asm 1: movdqa <z2=int6464#11,>y10=int6464#1
+# asm 2: movdqa <z2=%xmm10,>y10=%xmm0
+movdqa %xmm10,%xmm0
+
+# qhasm: uint32323232 y10 += z6
+# asm 1: paddd <z6=int6464#6,<y10=int6464#1
+# asm 2: paddd <z6=%xmm5,<y10=%xmm0
+paddd %xmm5,%xmm0
+
+# qhasm: r10 = y10
+# asm 1: movdqa <y10=int6464#1,>r10=int6464#13
+# asm 2: movdqa <y10=%xmm0,>r10=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y10 <<= 18
+# asm 1: pslld $18,<y10=int6464#1
+# asm 2: pslld $18,<y10=%xmm0
+pslld $18,%xmm0
+
+# qhasm: z10 ^= y10
+# asm 1: pxor <y10=int6464#1,<z10=int6464#2
+# asm 2: pxor <y10=%xmm0,<z10=%xmm1
+pxor %xmm0,%xmm1
+
+# qhasm: uint32323232 r10 >>= 14
+# asm 1: psrld $14,<r10=int6464#13
+# asm 2: psrld $14,<r10=%xmm12
+psrld $14,%xmm12
+
+# qhasm: z10 ^= r10
+# asm 1: pxor <r10=int6464#13,<z10=int6464#2
+# asm 2: pxor <r10=%xmm12,<z10=%xmm1
+pxor %xmm12,%xmm1
+
+# qhasm: z0 = z0_stack
+# asm 1: movdqa <z0_stack=stack128#21,>z0=int6464#1
+# asm 2: movdqa <z0_stack=320(%rsp),>z0=%xmm0
+movdqa 320(%rsp),%xmm0
+
+# qhasm: z10_stack = z10
+# asm 1: movdqa <z10=int6464#2,>z10_stack=stack128#21
+# asm 2: movdqa <z10=%xmm1,>z10_stack=320(%rsp)
+movdqa %xmm1,320(%rsp)
+
+# qhasm: y1 = z3
+# asm 1: movdqa <z3=int6464#5,>y1=int6464#2
+# asm 2: movdqa <z3=%xmm4,>y1=%xmm1
+movdqa %xmm4,%xmm1
+
+# qhasm: uint32323232 y1 += z0
+# asm 1: paddd <z0=int6464#1,<y1=int6464#2
+# asm 2: paddd <z0=%xmm0,<y1=%xmm1
+paddd %xmm0,%xmm1
+
+# qhasm: r1 = y1
+# asm 1: movdqa <y1=int6464#2,>r1=int6464#13
+# asm 2: movdqa <y1=%xmm1,>r1=%xmm12
+movdqa %xmm1,%xmm12
+
+# qhasm: uint32323232 y1 <<= 7
+# asm 1: pslld $7,<y1=int6464#2
+# asm 2: pslld $7,<y1=%xmm1
+pslld $7,%xmm1
+
+# qhasm: z1 ^= y1
+# asm 1: pxor <y1=int6464#2,<z1=int6464#8
+# asm 2: pxor <y1=%xmm1,<z1=%xmm7
+pxor %xmm1,%xmm7
+
+# qhasm: uint32323232 r1 >>= 25
+# asm 1: psrld $25,<r1=int6464#13
+# asm 2: psrld $25,<r1=%xmm12
+psrld $25,%xmm12
+
+# qhasm: z1 ^= r1
+# asm 1: pxor <r1=int6464#13,<z1=int6464#8
+# asm 2: pxor <r1=%xmm12,<z1=%xmm7
+pxor %xmm12,%xmm7
+
+# qhasm: y15 = z7
+# asm 1: movdqa <z7=int6464#9,>y15=int6464#2
+# asm 2: movdqa <z7=%xmm8,>y15=%xmm1
+movdqa %xmm8,%xmm1
+
+# qhasm: uint32323232 y15 += z11
+# asm 1: paddd <z11=int6464#7,<y15=int6464#2
+# asm 2: paddd <z11=%xmm6,<y15=%xmm1
+paddd %xmm6,%xmm1
+
+# qhasm: r15 = y15
+# asm 1: movdqa <y15=int6464#2,>r15=int6464#13
+# asm 2: movdqa <y15=%xmm1,>r15=%xmm12
+movdqa %xmm1,%xmm12
+
+# qhasm: uint32323232 y15 <<= 18
+# asm 1: pslld $18,<y15=int6464#2
+# asm 2: pslld $18,<y15=%xmm1
+pslld $18,%xmm1
+
+# qhasm: z15 ^= y15
+# asm 1: pxor <y15=int6464#2,<z15=int6464#3
+# asm 2: pxor <y15=%xmm1,<z15=%xmm2
+pxor %xmm1,%xmm2
+
+# qhasm: uint32323232 r15 >>= 14
+# asm 1: psrld $14,<r15=int6464#13
+# asm 2: psrld $14,<r15=%xmm12
+psrld $14,%xmm12
+
+# qhasm: z15 ^= r15
+# asm 1: pxor <r15=int6464#13,<z15=int6464#3
+# asm 2: pxor <r15=%xmm12,<z15=%xmm2
+pxor %xmm12,%xmm2
+
+# qhasm: z5 = z5_stack
+# asm 1: movdqa <z5_stack=stack128#22,>z5=int6464#13
+# asm 2: movdqa <z5_stack=336(%rsp),>z5=%xmm12
+movdqa 336(%rsp),%xmm12
+
+# qhasm: z15_stack = z15
+# asm 1: movdqa <z15=int6464#3,>z15_stack=stack128#22
+# asm 2: movdqa <z15=%xmm2,>z15_stack=336(%rsp)
+movdqa %xmm2,336(%rsp)
+
+# qhasm: y6 = z4
+# asm 1: movdqa <z4=int6464#15,>y6=int6464#2
+# asm 2: movdqa <z4=%xmm14,>y6=%xmm1
+movdqa %xmm14,%xmm1
+
+# qhasm: uint32323232 y6 += z5
+# asm 1: paddd <z5=int6464#13,<y6=int6464#2
+# asm 2: paddd <z5=%xmm12,<y6=%xmm1
+paddd %xmm12,%xmm1
+
+# qhasm: r6 = y6
+# asm 1: movdqa <y6=int6464#2,>r6=int6464#3
+# asm 2: movdqa <y6=%xmm1,>r6=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y6 <<= 7
+# asm 1: pslld $7,<y6=int6464#2
+# asm 2: pslld $7,<y6=%xmm1
+pslld $7,%xmm1
+
+# qhasm: z6 ^= y6
+# asm 1: pxor <y6=int6464#2,<z6=int6464#6
+# asm 2: pxor <y6=%xmm1,<z6=%xmm5
+pxor %xmm1,%xmm5
+
+# qhasm: uint32323232 r6 >>= 25
+# asm 1: psrld $25,<r6=int6464#3
+# asm 2: psrld $25,<r6=%xmm2
+psrld $25,%xmm2
+
+# qhasm: z6 ^= r6
+# asm 1: pxor <r6=int6464#3,<z6=int6464#6
+# asm 2: pxor <r6=%xmm2,<z6=%xmm5
+pxor %xmm2,%xmm5
+
+# qhasm: y2 = z0
+# asm 1: movdqa <z0=int6464#1,>y2=int6464#2
+# asm 2: movdqa <z0=%xmm0,>y2=%xmm1
+movdqa %xmm0,%xmm1
+
+# qhasm: uint32323232 y2 += z1
+# asm 1: paddd <z1=int6464#8,<y2=int6464#2
+# asm 2: paddd <z1=%xmm7,<y2=%xmm1
+paddd %xmm7,%xmm1
+
+# qhasm: r2 = y2
+# asm 1: movdqa <y2=int6464#2,>r2=int6464#3
+# asm 2: movdqa <y2=%xmm1,>r2=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y2 <<= 9
+# asm 1: pslld $9,<y2=int6464#2
+# asm 2: pslld $9,<y2=%xmm1
+pslld $9,%xmm1
+
+# qhasm: z2 ^= y2
+# asm 1: pxor <y2=int6464#2,<z2=int6464#11
+# asm 2: pxor <y2=%xmm1,<z2=%xmm10
+pxor %xmm1,%xmm10
+
+# qhasm: uint32323232 r2 >>= 23
+# asm 1: psrld $23,<r2=int6464#3
+# asm 2: psrld $23,<r2=%xmm2
+psrld $23,%xmm2
+
+# qhasm: z2 ^= r2
+# asm 1: pxor <r2=int6464#3,<z2=int6464#11
+# asm 2: pxor <r2=%xmm2,<z2=%xmm10
+pxor %xmm2,%xmm10
+
+# qhasm: y7 = z5
+# asm 1: movdqa <z5=int6464#13,>y7=int6464#2
+# asm 2: movdqa <z5=%xmm12,>y7=%xmm1
+movdqa %xmm12,%xmm1
+
+# qhasm: uint32323232 y7 += z6
+# asm 1: paddd <z6=int6464#6,<y7=int6464#2
+# asm 2: paddd <z6=%xmm5,<y7=%xmm1
+paddd %xmm5,%xmm1
+
+# qhasm: r7 = y7
+# asm 1: movdqa <y7=int6464#2,>r7=int6464#3
+# asm 2: movdqa <y7=%xmm1,>r7=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y7 <<= 9
+# asm 1: pslld $9,<y7=int6464#2
+# asm 2: pslld $9,<y7=%xmm1
+pslld $9,%xmm1
+
+# qhasm: z7 ^= y7
+# asm 1: pxor <y7=int6464#2,<z7=int6464#9
+# asm 2: pxor <y7=%xmm1,<z7=%xmm8
+pxor %xmm1,%xmm8
+
+# qhasm: uint32323232 r7 >>= 23
+# asm 1: psrld $23,<r7=int6464#3
+# asm 2: psrld $23,<r7=%xmm2
+psrld $23,%xmm2
+
+# qhasm: z7 ^= r7
+# asm 1: pxor <r7=int6464#3,<z7=int6464#9
+# asm 2: pxor <r7=%xmm2,<z7=%xmm8
+pxor %xmm2,%xmm8
+
+# qhasm: y3 = z1
+# asm 1: movdqa <z1=int6464#8,>y3=int6464#2
+# asm 2: movdqa <z1=%xmm7,>y3=%xmm1
+movdqa %xmm7,%xmm1
+
+# qhasm: uint32323232 y3 += z2
+# asm 1: paddd <z2=int6464#11,<y3=int6464#2
+# asm 2: paddd <z2=%xmm10,<y3=%xmm1
+paddd %xmm10,%xmm1
+
+# qhasm: r3 = y3
+# asm 1: movdqa <y3=int6464#2,>r3=int6464#3
+# asm 2: movdqa <y3=%xmm1,>r3=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y3 <<= 13
+# asm 1: pslld $13,<y3=int6464#2
+# asm 2: pslld $13,<y3=%xmm1
+pslld $13,%xmm1
+
+# qhasm: z3 ^= y3
+# asm 1: pxor <y3=int6464#2,<z3=int6464#5
+# asm 2: pxor <y3=%xmm1,<z3=%xmm4
+pxor %xmm1,%xmm4
+
+# qhasm: uint32323232 r3 >>= 19
+# asm 1: psrld $19,<r3=int6464#3
+# asm 2: psrld $19,<r3=%xmm2
+psrld $19,%xmm2
+
+# qhasm: z3 ^= r3
+# asm 1: pxor <r3=int6464#3,<z3=int6464#5
+# asm 2: pxor <r3=%xmm2,<z3=%xmm4
+pxor %xmm2,%xmm4
+
+# qhasm: y4 = z6
+# asm 1: movdqa <z6=int6464#6,>y4=int6464#2
+# asm 2: movdqa <z6=%xmm5,>y4=%xmm1
+movdqa %xmm5,%xmm1
+
+# qhasm: uint32323232 y4 += z7
+# asm 1: paddd <z7=int6464#9,<y4=int6464#2
+# asm 2: paddd <z7=%xmm8,<y4=%xmm1
+paddd %xmm8,%xmm1
+
+# qhasm: r4 = y4
+# asm 1: movdqa <y4=int6464#2,>r4=int6464#3
+# asm 2: movdqa <y4=%xmm1,>r4=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y4 <<= 13
+# asm 1: pslld $13,<y4=int6464#2
+# asm 2: pslld $13,<y4=%xmm1
+pslld $13,%xmm1
+
+# qhasm: z4 ^= y4
+# asm 1: pxor <y4=int6464#2,<z4=int6464#15
+# asm 2: pxor <y4=%xmm1,<z4=%xmm14
+pxor %xmm1,%xmm14
+
+# qhasm: uint32323232 r4 >>= 19
+# asm 1: psrld $19,<r4=int6464#3
+# asm 2: psrld $19,<r4=%xmm2
+psrld $19,%xmm2
+
+# qhasm: z4 ^= r4
+# asm 1: pxor <r4=int6464#3,<z4=int6464#15
+# asm 2: pxor <r4=%xmm2,<z4=%xmm14
+pxor %xmm2,%xmm14
+
+# qhasm: y0 = z2
+# asm 1: movdqa <z2=int6464#11,>y0=int6464#2
+# asm 2: movdqa <z2=%xmm10,>y0=%xmm1
+movdqa %xmm10,%xmm1
+
+# qhasm: uint32323232 y0 += z3
+# asm 1: paddd <z3=int6464#5,<y0=int6464#2
+# asm 2: paddd <z3=%xmm4,<y0=%xmm1
+paddd %xmm4,%xmm1
+
+# qhasm: r0 = y0
+# asm 1: movdqa <y0=int6464#2,>r0=int6464#3
+# asm 2: movdqa <y0=%xmm1,>r0=%xmm2
+movdqa %xmm1,%xmm2
+
+# qhasm: uint32323232 y0 <<= 18
+# asm 1: pslld $18,<y0=int6464#2
+# asm 2: pslld $18,<y0=%xmm1
+pslld $18,%xmm1
+
+# qhasm: z0 ^= y0
+# asm 1: pxor <y0=int6464#2,<z0=int6464#1
+# asm 2: pxor <y0=%xmm1,<z0=%xmm0
+pxor %xmm1,%xmm0
+
+# qhasm: uint32323232 r0 >>= 14
+# asm 1: psrld $14,<r0=int6464#3
+# asm 2: psrld $14,<r0=%xmm2
+psrld $14,%xmm2
+
+# qhasm: z0 ^= r0
+# asm 1: pxor <r0=int6464#3,<z0=int6464#1
+# asm 2: pxor <r0=%xmm2,<z0=%xmm0
+pxor %xmm2,%xmm0
+
+# qhasm: z10 = z10_stack
+# asm 1: movdqa <z10_stack=stack128#21,>z10=int6464#2
+# asm 2: movdqa <z10_stack=320(%rsp),>z10=%xmm1
+movdqa 320(%rsp),%xmm1
+
+# qhasm: z0_stack = z0
+# asm 1: movdqa <z0=int6464#1,>z0_stack=stack128#21
+# asm 2: movdqa <z0=%xmm0,>z0_stack=320(%rsp)
+movdqa %xmm0,320(%rsp)
+
+# qhasm: y5 = z7
+# asm 1: movdqa <z7=int6464#9,>y5=int6464#1
+# asm 2: movdqa <z7=%xmm8,>y5=%xmm0
+movdqa %xmm8,%xmm0
+
+# qhasm: uint32323232 y5 += z4
+# asm 1: paddd <z4=int6464#15,<y5=int6464#1
+# asm 2: paddd <z4=%xmm14,<y5=%xmm0
+paddd %xmm14,%xmm0
+
+# qhasm: r5 = y5
+# asm 1: movdqa <y5=int6464#1,>r5=int6464#3
+# asm 2: movdqa <y5=%xmm0,>r5=%xmm2
+movdqa %xmm0,%xmm2
+
+# qhasm: uint32323232 y5 <<= 18
+# asm 1: pslld $18,<y5=int6464#1
+# asm 2: pslld $18,<y5=%xmm0
+pslld $18,%xmm0
+
+# qhasm: z5 ^= y5
+# asm 1: pxor <y5=int6464#1,<z5=int6464#13
+# asm 2: pxor <y5=%xmm0,<z5=%xmm12
+pxor %xmm0,%xmm12
+
+# qhasm: uint32323232 r5 >>= 14
+# asm 1: psrld $14,<r5=int6464#3
+# asm 2: psrld $14,<r5=%xmm2
+psrld $14,%xmm2
+
+# qhasm: z5 ^= r5
+# asm 1: pxor <r5=int6464#3,<z5=int6464#13
+# asm 2: pxor <r5=%xmm2,<z5=%xmm12
+pxor %xmm2,%xmm12
+
+# qhasm: y11 = z9
+# asm 1: movdqa <z9=int6464#12,>y11=int6464#1
+# asm 2: movdqa <z9=%xmm11,>y11=%xmm0
+movdqa %xmm11,%xmm0
+
+# qhasm: uint32323232 y11 += z10
+# asm 1: paddd <z10=int6464#2,<y11=int6464#1
+# asm 2: paddd <z10=%xmm1,<y11=%xmm0
+paddd %xmm1,%xmm0
+
+# qhasm: r11 = y11
+# asm 1: movdqa <y11=int6464#1,>r11=int6464#3
+# asm 2: movdqa <y11=%xmm0,>r11=%xmm2
+movdqa %xmm0,%xmm2
+
+# qhasm: uint32323232 y11 <<= 7
+# asm 1: pslld $7,<y11=int6464#1
+# asm 2: pslld $7,<y11=%xmm0
+pslld $7,%xmm0
+
+# qhasm: z11 ^= y11
+# asm 1: pxor <y11=int6464#1,<z11=int6464#7
+# asm 2: pxor <y11=%xmm0,<z11=%xmm6
+pxor %xmm0,%xmm6
+
+# qhasm: uint32323232 r11 >>= 25
+# asm 1: psrld $25,<r11=int6464#3
+# asm 2: psrld $25,<r11=%xmm2
+psrld $25,%xmm2
+
+# qhasm: z11 ^= r11
+# asm 1: pxor <r11=int6464#3,<z11=int6464#7
+# asm 2: pxor <r11=%xmm2,<z11=%xmm6
+pxor %xmm2,%xmm6
+
+# qhasm: z15 = z15_stack
+# asm 1: movdqa <z15_stack=stack128#22,>z15=int6464#3
+# asm 2: movdqa <z15_stack=336(%rsp),>z15=%xmm2
+movdqa 336(%rsp),%xmm2
+
+# qhasm: z5_stack = z5
+# asm 1: movdqa <z5=int6464#13,>z5_stack=stack128#22
+# asm 2: movdqa <z5=%xmm12,>z5_stack=336(%rsp)
+movdqa %xmm12,336(%rsp)
+
+# qhasm: y12 = z14
+# asm 1: movdqa <z14=int6464#4,>y12=int6464#1
+# asm 2: movdqa <z14=%xmm3,>y12=%xmm0
+movdqa %xmm3,%xmm0
+
+# qhasm: uint32323232 y12 += z15
+# asm 1: paddd <z15=int6464#3,<y12=int6464#1
+# asm 2: paddd <z15=%xmm2,<y12=%xmm0
+paddd %xmm2,%xmm0
+
+# qhasm: r12 = y12
+# asm 1: movdqa <y12=int6464#1,>r12=int6464#13
+# asm 2: movdqa <y12=%xmm0,>r12=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y12 <<= 7
+# asm 1: pslld $7,<y12=int6464#1
+# asm 2: pslld $7,<y12=%xmm0
+pslld $7,%xmm0
+
+# qhasm: z12 ^= y12
+# asm 1: pxor <y12=int6464#1,<z12=int6464#14
+# asm 2: pxor <y12=%xmm0,<z12=%xmm13
+pxor %xmm0,%xmm13
+
+# qhasm: uint32323232 r12 >>= 25
+# asm 1: psrld $25,<r12=int6464#13
+# asm 2: psrld $25,<r12=%xmm12
+psrld $25,%xmm12
+
+# qhasm: z12 ^= r12
+# asm 1: pxor <r12=int6464#13,<z12=int6464#14
+# asm 2: pxor <r12=%xmm12,<z12=%xmm13
+pxor %xmm12,%xmm13
+
+# qhasm: y8 = z10
+# asm 1: movdqa <z10=int6464#2,>y8=int6464#1
+# asm 2: movdqa <z10=%xmm1,>y8=%xmm0
+movdqa %xmm1,%xmm0
+
+# qhasm: uint32323232 y8 += z11
+# asm 1: paddd <z11=int6464#7,<y8=int6464#1
+# asm 2: paddd <z11=%xmm6,<y8=%xmm0
+paddd %xmm6,%xmm0
+
+# qhasm: r8 = y8
+# asm 1: movdqa <y8=int6464#1,>r8=int6464#13
+# asm 2: movdqa <y8=%xmm0,>r8=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y8 <<= 9
+# asm 1: pslld $9,<y8=int6464#1
+# asm 2: pslld $9,<y8=%xmm0
+pslld $9,%xmm0
+
+# qhasm: z8 ^= y8
+# asm 1: pxor <y8=int6464#1,<z8=int6464#16
+# asm 2: pxor <y8=%xmm0,<z8=%xmm15
+pxor %xmm0,%xmm15
+
+# qhasm: uint32323232 r8 >>= 23
+# asm 1: psrld $23,<r8=int6464#13
+# asm 2: psrld $23,<r8=%xmm12
+psrld $23,%xmm12
+
+# qhasm: z8 ^= r8
+# asm 1: pxor <r8=int6464#13,<z8=int6464#16
+# asm 2: pxor <r8=%xmm12,<z8=%xmm15
+pxor %xmm12,%xmm15
+
+# qhasm: y13 = z15
+# asm 1: movdqa <z15=int6464#3,>y13=int6464#1
+# asm 2: movdqa <z15=%xmm2,>y13=%xmm0
+movdqa %xmm2,%xmm0
+
+# qhasm: uint32323232 y13 += z12
+# asm 1: paddd <z12=int6464#14,<y13=int6464#1
+# asm 2: paddd <z12=%xmm13,<y13=%xmm0
+paddd %xmm13,%xmm0
+
+# qhasm: r13 = y13
+# asm 1: movdqa <y13=int6464#1,>r13=int6464#13
+# asm 2: movdqa <y13=%xmm0,>r13=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y13 <<= 9
+# asm 1: pslld $9,<y13=int6464#1
+# asm 2: pslld $9,<y13=%xmm0
+pslld $9,%xmm0
+
+# qhasm: z13 ^= y13
+# asm 1: pxor <y13=int6464#1,<z13=int6464#10
+# asm 2: pxor <y13=%xmm0,<z13=%xmm9
+pxor %xmm0,%xmm9
+
+# qhasm: uint32323232 r13 >>= 23
+# asm 1: psrld $23,<r13=int6464#13
+# asm 2: psrld $23,<r13=%xmm12
+psrld $23,%xmm12
+
+# qhasm: z13 ^= r13
+# asm 1: pxor <r13=int6464#13,<z13=int6464#10
+# asm 2: pxor <r13=%xmm12,<z13=%xmm9
+pxor %xmm12,%xmm9
+
+# qhasm: y9 = z11
+# asm 1: movdqa <z11=int6464#7,>y9=int6464#1
+# asm 2: movdqa <z11=%xmm6,>y9=%xmm0
+movdqa %xmm6,%xmm0
+
+# qhasm: uint32323232 y9 += z8
+# asm 1: paddd <z8=int6464#16,<y9=int6464#1
+# asm 2: paddd <z8=%xmm15,<y9=%xmm0
+paddd %xmm15,%xmm0
+
+# qhasm: r9 = y9
+# asm 1: movdqa <y9=int6464#1,>r9=int6464#13
+# asm 2: movdqa <y9=%xmm0,>r9=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y9 <<= 13
+# asm 1: pslld $13,<y9=int6464#1
+# asm 2: pslld $13,<y9=%xmm0
+pslld $13,%xmm0
+
+# qhasm: z9 ^= y9
+# asm 1: pxor <y9=int6464#1,<z9=int6464#12
+# asm 2: pxor <y9=%xmm0,<z9=%xmm11
+pxor %xmm0,%xmm11
+
+# qhasm: uint32323232 r9 >>= 19
+# asm 1: psrld $19,<r9=int6464#13
+# asm 2: psrld $19,<r9=%xmm12
+psrld $19,%xmm12
+
+# qhasm: z9 ^= r9
+# asm 1: pxor <r9=int6464#13,<z9=int6464#12
+# asm 2: pxor <r9=%xmm12,<z9=%xmm11
+pxor %xmm12,%xmm11
+
+# qhasm: y14 = z12
+# asm 1: movdqa <z12=int6464#14,>y14=int6464#1
+# asm 2: movdqa <z12=%xmm13,>y14=%xmm0
+movdqa %xmm13,%xmm0
+
+# qhasm: uint32323232 y14 += z13
+# asm 1: paddd <z13=int6464#10,<y14=int6464#1
+# asm 2: paddd <z13=%xmm9,<y14=%xmm0
+paddd %xmm9,%xmm0
+
+# qhasm: r14 = y14
+# asm 1: movdqa <y14=int6464#1,>r14=int6464#13
+# asm 2: movdqa <y14=%xmm0,>r14=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y14 <<= 13
+# asm 1: pslld $13,<y14=int6464#1
+# asm 2: pslld $13,<y14=%xmm0
+pslld $13,%xmm0
+
+# qhasm: z14 ^= y14
+# asm 1: pxor <y14=int6464#1,<z14=int6464#4
+# asm 2: pxor <y14=%xmm0,<z14=%xmm3
+pxor %xmm0,%xmm3
+
+# qhasm: uint32323232 r14 >>= 19
+# asm 1: psrld $19,<r14=int6464#13
+# asm 2: psrld $19,<r14=%xmm12
+psrld $19,%xmm12
+
+# qhasm: z14 ^= r14
+# asm 1: pxor <r14=int6464#13,<z14=int6464#4
+# asm 2: pxor <r14=%xmm12,<z14=%xmm3
+pxor %xmm12,%xmm3
+
+# qhasm: y10 = z8
+# asm 1: movdqa <z8=int6464#16,>y10=int6464#1
+# asm 2: movdqa <z8=%xmm15,>y10=%xmm0
+movdqa %xmm15,%xmm0
+
+# qhasm: uint32323232 y10 += z9
+# asm 1: paddd <z9=int6464#12,<y10=int6464#1
+# asm 2: paddd <z9=%xmm11,<y10=%xmm0
+paddd %xmm11,%xmm0
+
+# qhasm: r10 = y10
+# asm 1: movdqa <y10=int6464#1,>r10=int6464#13
+# asm 2: movdqa <y10=%xmm0,>r10=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y10 <<= 18
+# asm 1: pslld $18,<y10=int6464#1
+# asm 2: pslld $18,<y10=%xmm0
+pslld $18,%xmm0
+
+# qhasm: z10 ^= y10
+# asm 1: pxor <y10=int6464#1,<z10=int6464#2
+# asm 2: pxor <y10=%xmm0,<z10=%xmm1
+pxor %xmm0,%xmm1
+
+# qhasm: uint32323232 r10 >>= 14
+# asm 1: psrld $14,<r10=int6464#13
+# asm 2: psrld $14,<r10=%xmm12
+psrld $14,%xmm12
+
+# qhasm: z10 ^= r10
+# asm 1: pxor <r10=int6464#13,<z10=int6464#2
+# asm 2: pxor <r10=%xmm12,<z10=%xmm1
+pxor %xmm12,%xmm1
+
+# qhasm: y15 = z13
+# asm 1: movdqa <z13=int6464#10,>y15=int6464#1
+# asm 2: movdqa <z13=%xmm9,>y15=%xmm0
+movdqa %xmm9,%xmm0
+
+# qhasm: uint32323232 y15 += z14
+# asm 1: paddd <z14=int6464#4,<y15=int6464#1
+# asm 2: paddd <z14=%xmm3,<y15=%xmm0
+paddd %xmm3,%xmm0
+
+# qhasm: r15 = y15
+# asm 1: movdqa <y15=int6464#1,>r15=int6464#13
+# asm 2: movdqa <y15=%xmm0,>r15=%xmm12
+movdqa %xmm0,%xmm12
+
+# qhasm: uint32323232 y15 <<= 18
+# asm 1: pslld $18,<y15=int6464#1
+# asm 2: pslld $18,<y15=%xmm0
+pslld $18,%xmm0
+
+# qhasm: z15 ^= y15
+# asm 1: pxor <y15=int6464#1,<z15=int6464#3
+# asm 2: pxor <y15=%xmm0,<z15=%xmm2
+pxor %xmm0,%xmm2
+
+# qhasm: uint32323232 r15 >>= 14
+# asm 1: psrld $14,<r15=int6464#13
+# asm 2: psrld $14,<r15=%xmm12
+psrld $14,%xmm12
+
+# qhasm: z15 ^= r15
+# asm 1: pxor <r15=int6464#13,<z15=int6464#3
+# asm 2: pxor <r15=%xmm12,<z15=%xmm2
+pxor %xmm12,%xmm2
+
+# qhasm: z0 = z0_stack
+# asm 1: movdqa <z0_stack=stack128#21,>z0=int6464#13
+# asm 2: movdqa <z0_stack=320(%rsp),>z0=%xmm12
+movdqa 320(%rsp),%xmm12
+
+# qhasm: z5 = z5_stack
+# asm 1: movdqa <z5_stack=stack128#22,>z5=int6464#1
+# asm 2: movdqa <z5_stack=336(%rsp),>z5=%xmm0
+movdqa 336(%rsp),%xmm0
+
+# qhasm: unsigned>? i -= 2
+# asm 1: sub $2,<i=int64#3
+# asm 2: sub $2,<i=%rdx
+sub $2,%rdx
+# comment:fp stack unchanged by jump
+
+# qhasm: goto mainloop1 if unsigned>
+ja ._mainloop1
+
+# qhasm: uint32323232 z0 += orig0
+# asm 1: paddd <orig0=stack128#8,<z0=int6464#13
+# asm 2: paddd <orig0=112(%rsp),<z0=%xmm12
+paddd 112(%rsp),%xmm12
+
+# qhasm: uint32323232 z1 += orig1
+# asm 1: paddd <orig1=stack128#12,<z1=int6464#8
+# asm 2: paddd <orig1=176(%rsp),<z1=%xmm7
+paddd 176(%rsp),%xmm7
+
+# qhasm: uint32323232 z2 += orig2
+# asm 1: paddd <orig2=stack128#15,<z2=int6464#11
+# asm 2: paddd <orig2=224(%rsp),<z2=%xmm10
+paddd 224(%rsp),%xmm10
+
+# qhasm: uint32323232 z3 += orig3
+# asm 1: paddd <orig3=stack128#18,<z3=int6464#5
+# asm 2: paddd <orig3=272(%rsp),<z3=%xmm4
+paddd 272(%rsp),%xmm4
+
+# qhasm: in0 = z0
+# asm 1: movd <z0=int6464#13,>in0=int64#3
+# asm 2: movd <z0=%xmm12,>in0=%rdx
+movd %xmm12,%rdx
+
+# qhasm: in1 = z1
+# asm 1: movd <z1=int6464#8,>in1=int64#4
+# asm 2: movd <z1=%xmm7,>in1=%rcx
+movd %xmm7,%rcx
+
+# qhasm: in2 = z2
+# asm 1: movd <z2=int6464#11,>in2=int64#5
+# asm 2: movd <z2=%xmm10,>in2=%r8
+movd %xmm10,%r8
+
+# qhasm: in3 = z3
+# asm 1: movd <z3=int6464#5,>in3=int64#6
+# asm 2: movd <z3=%xmm4,>in3=%r9
+movd %xmm4,%r9
+
+# qhasm: z0 <<<= 96
+# asm 1: pshufd $0x39,<z0=int6464#13,<z0=int6464#13
+# asm 2: pshufd $0x39,<z0=%xmm12,<z0=%xmm12
+pshufd $0x39,%xmm12,%xmm12
+
+# qhasm: z1 <<<= 96
+# asm 1: pshufd $0x39,<z1=int6464#8,<z1=int6464#8
+# asm 2: pshufd $0x39,<z1=%xmm7,<z1=%xmm7
+pshufd $0x39,%xmm7,%xmm7
+
+# qhasm: z2 <<<= 96
+# asm 1: pshufd $0x39,<z2=int6464#11,<z2=int6464#11
+# asm 2: pshufd $0x39,<z2=%xmm10,<z2=%xmm10
+pshufd $0x39,%xmm10,%xmm10
+
+# qhasm: z3 <<<= 96
+# asm 1: pshufd $0x39,<z3=int6464#5,<z3=int6464#5
+# asm 2: pshufd $0x39,<z3=%xmm4,<z3=%xmm4
+pshufd $0x39,%xmm4,%xmm4
+
+# qhasm: (uint32) in0 ^= *(uint32 *) (m + 0)
+# asm 1: xorl 0(<m=int64#2),<in0=int64#3d
+# asm 2: xorl 0(<m=%rsi),<in0=%edx
+xorl 0(%rsi),%edx
+
+# qhasm: (uint32) in1 ^= *(uint32 *) (m + 4)
+# asm 1: xorl 4(<m=int64#2),<in1=int64#4d
+# asm 2: xorl 4(<m=%rsi),<in1=%ecx
+xorl 4(%rsi),%ecx
+
+# qhasm: (uint32) in2 ^= *(uint32 *) (m + 8)
+# asm 1: xorl 8(<m=int64#2),<in2=int64#5d
+# asm 2: xorl 8(<m=%rsi),<in2=%r8d
+xorl 8(%rsi),%r8d
+
+# qhasm: (uint32) in3 ^= *(uint32 *) (m + 12)
+# asm 1: xorl 12(<m=int64#2),<in3=int64#6d
+# asm 2: xorl 12(<m=%rsi),<in3=%r9d
+xorl 12(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 0) = in0
+# asm 1: movl <in0=int64#3d,0(<out=int64#1)
+# asm 2: movl <in0=%edx,0(<out=%rdi)
+movl %edx,0(%rdi)
+
+# qhasm: *(uint32 *) (out + 4) = in1
+# asm 1: movl <in1=int64#4d,4(<out=int64#1)
+# asm 2: movl <in1=%ecx,4(<out=%rdi)
+movl %ecx,4(%rdi)
+
+# qhasm: *(uint32 *) (out + 8) = in2
+# asm 1: movl <in2=int64#5d,8(<out=int64#1)
+# asm 2: movl <in2=%r8d,8(<out=%rdi)
+movl %r8d,8(%rdi)
+
+# qhasm: *(uint32 *) (out + 12) = in3
+# asm 1: movl <in3=int64#6d,12(<out=int64#1)
+# asm 2: movl <in3=%r9d,12(<out=%rdi)
+movl %r9d,12(%rdi)
+
+# qhasm: in0 = z0
+# asm 1: movd <z0=int6464#13,>in0=int64#3
+# asm 2: movd <z0=%xmm12,>in0=%rdx
+movd %xmm12,%rdx
+
+# qhasm: in1 = z1
+# asm 1: movd <z1=int6464#8,>in1=int64#4
+# asm 2: movd <z1=%xmm7,>in1=%rcx
+movd %xmm7,%rcx
+
+# qhasm: in2 = z2
+# asm 1: movd <z2=int6464#11,>in2=int64#5
+# asm 2: movd <z2=%xmm10,>in2=%r8
+movd %xmm10,%r8
+
+# qhasm: in3 = z3
+# asm 1: movd <z3=int6464#5,>in3=int64#6
+# asm 2: movd <z3=%xmm4,>in3=%r9
+movd %xmm4,%r9
+
+# qhasm: z0 <<<= 96
+# asm 1: pshufd $0x39,<z0=int6464#13,<z0=int6464#13
+# asm 2: pshufd $0x39,<z0=%xmm12,<z0=%xmm12
+pshufd $0x39,%xmm12,%xmm12
+
+# qhasm: z1 <<<= 96
+# asm 1: pshufd $0x39,<z1=int6464#8,<z1=int6464#8
+# asm 2: pshufd $0x39,<z1=%xmm7,<z1=%xmm7
+pshufd $0x39,%xmm7,%xmm7
+
+# qhasm: z2 <<<= 96
+# asm 1: pshufd $0x39,<z2=int6464#11,<z2=int6464#11
+# asm 2: pshufd $0x39,<z2=%xmm10,<z2=%xmm10
+pshufd $0x39,%xmm10,%xmm10
+
+# qhasm: z3 <<<= 96
+# asm 1: pshufd $0x39,<z3=int6464#5,<z3=int6464#5
+# asm 2: pshufd $0x39,<z3=%xmm4,<z3=%xmm4
+pshufd $0x39,%xmm4,%xmm4
+
+# qhasm: (uint32) in0 ^= *(uint32 *) (m + 64)
+# asm 1: xorl 64(<m=int64#2),<in0=int64#3d
+# asm 2: xorl 64(<m=%rsi),<in0=%edx
+xorl 64(%rsi),%edx
+
+# qhasm: (uint32) in1 ^= *(uint32 *) (m + 68)
+# asm 1: xorl 68(<m=int64#2),<in1=int64#4d
+# asm 2: xorl 68(<m=%rsi),<in1=%ecx
+xorl 68(%rsi),%ecx
+
+# qhasm: (uint32) in2 ^= *(uint32 *) (m + 72)
+# asm 1: xorl 72(<m=int64#2),<in2=int64#5d
+# asm 2: xorl 72(<m=%rsi),<in2=%r8d
+xorl 72(%rsi),%r8d
+
+# qhasm: (uint32) in3 ^= *(uint32 *) (m + 76)
+# asm 1: xorl 76(<m=int64#2),<in3=int64#6d
+# asm 2: xorl 76(<m=%rsi),<in3=%r9d
+xorl 76(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 64) = in0
+# asm 1: movl <in0=int64#3d,64(<out=int64#1)
+# asm 2: movl <in0=%edx,64(<out=%rdi)
+movl %edx,64(%rdi)
+
+# qhasm: *(uint32 *) (out + 68) = in1
+# asm 1: movl <in1=int64#4d,68(<out=int64#1)
+# asm 2: movl <in1=%ecx,68(<out=%rdi)
+movl %ecx,68(%rdi)
+
+# qhasm: *(uint32 *) (out + 72) = in2
+# asm 1: movl <in2=int64#5d,72(<out=int64#1)
+# asm 2: movl <in2=%r8d,72(<out=%rdi)
+movl %r8d,72(%rdi)
+
+# qhasm: *(uint32 *) (out + 76) = in3
+# asm 1: movl <in3=int64#6d,76(<out=int64#1)
+# asm 2: movl <in3=%r9d,76(<out=%rdi)
+movl %r9d,76(%rdi)
+
+# qhasm: in0 = z0
+# asm 1: movd <z0=int6464#13,>in0=int64#3
+# asm 2: movd <z0=%xmm12,>in0=%rdx
+movd %xmm12,%rdx
+
+# qhasm: in1 = z1
+# asm 1: movd <z1=int6464#8,>in1=int64#4
+# asm 2: movd <z1=%xmm7,>in1=%rcx
+movd %xmm7,%rcx
+
+# qhasm: in2 = z2
+# asm 1: movd <z2=int6464#11,>in2=int64#5
+# asm 2: movd <z2=%xmm10,>in2=%r8
+movd %xmm10,%r8
+
+# qhasm: in3 = z3
+# asm 1: movd <z3=int6464#5,>in3=int64#6
+# asm 2: movd <z3=%xmm4,>in3=%r9
+movd %xmm4,%r9
+
+# qhasm: z0 <<<= 96
+# asm 1: pshufd $0x39,<z0=int6464#13,<z0=int6464#13
+# asm 2: pshufd $0x39,<z0=%xmm12,<z0=%xmm12
+pshufd $0x39,%xmm12,%xmm12
+
+# qhasm: z1 <<<= 96
+# asm 1: pshufd $0x39,<z1=int6464#8,<z1=int6464#8
+# asm 2: pshufd $0x39,<z1=%xmm7,<z1=%xmm7
+pshufd $0x39,%xmm7,%xmm7
+
+# qhasm: z2 <<<= 96
+# asm 1: pshufd $0x39,<z2=int6464#11,<z2=int6464#11
+# asm 2: pshufd $0x39,<z2=%xmm10,<z2=%xmm10
+pshufd $0x39,%xmm10,%xmm10
+
+# qhasm: z3 <<<= 96
+# asm 1: pshufd $0x39,<z3=int6464#5,<z3=int6464#5
+# asm 2: pshufd $0x39,<z3=%xmm4,<z3=%xmm4
+pshufd $0x39,%xmm4,%xmm4
+
+# qhasm: (uint32) in0 ^= *(uint32 *) (m + 128)
+# asm 1: xorl 128(<m=int64#2),<in0=int64#3d
+# asm 2: xorl 128(<m=%rsi),<in0=%edx
+xorl 128(%rsi),%edx
+
+# qhasm: (uint32) in1 ^= *(uint32 *) (m + 132)
+# asm 1: xorl 132(<m=int64#2),<in1=int64#4d
+# asm 2: xorl 132(<m=%rsi),<in1=%ecx
+xorl 132(%rsi),%ecx
+
+# qhasm: (uint32) in2 ^= *(uint32 *) (m + 136)
+# asm 1: xorl 136(<m=int64#2),<in2=int64#5d
+# asm 2: xorl 136(<m=%rsi),<in2=%r8d
+xorl 136(%rsi),%r8d
+
+# qhasm: (uint32) in3 ^= *(uint32 *) (m + 140)
+# asm 1: xorl 140(<m=int64#2),<in3=int64#6d
+# asm 2: xorl 140(<m=%rsi),<in3=%r9d
+xorl 140(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 128) = in0
+# asm 1: movl <in0=int64#3d,128(<out=int64#1)
+# asm 2: movl <in0=%edx,128(<out=%rdi)
+movl %edx,128(%rdi)
+
+# qhasm: *(uint32 *) (out + 132) = in1
+# asm 1: movl <in1=int64#4d,132(<out=int64#1)
+# asm 2: movl <in1=%ecx,132(<out=%rdi)
+movl %ecx,132(%rdi)
+
+# qhasm: *(uint32 *) (out + 136) = in2
+# asm 1: movl <in2=int64#5d,136(<out=int64#1)
+# asm 2: movl <in2=%r8d,136(<out=%rdi)
+movl %r8d,136(%rdi)
+
+# qhasm: *(uint32 *) (out + 140) = in3
+# asm 1: movl <in3=int64#6d,140(<out=int64#1)
+# asm 2: movl <in3=%r9d,140(<out=%rdi)
+movl %r9d,140(%rdi)
+
+# qhasm: in0 = z0
+# asm 1: movd <z0=int6464#13,>in0=int64#3
+# asm 2: movd <z0=%xmm12,>in0=%rdx
+movd %xmm12,%rdx
+
+# qhasm: in1 = z1
+# asm 1: movd <z1=int6464#8,>in1=int64#4
+# asm 2: movd <z1=%xmm7,>in1=%rcx
+movd %xmm7,%rcx
+
+# qhasm: in2 = z2
+# asm 1: movd <z2=int6464#11,>in2=int64#5
+# asm 2: movd <z2=%xmm10,>in2=%r8
+movd %xmm10,%r8
+
+# qhasm: in3 = z3
+# asm 1: movd <z3=int6464#5,>in3=int64#6
+# asm 2: movd <z3=%xmm4,>in3=%r9
+movd %xmm4,%r9
+
+# qhasm: (uint32) in0 ^= *(uint32 *) (m + 192)
+# asm 1: xorl 192(<m=int64#2),<in0=int64#3d
+# asm 2: xorl 192(<m=%rsi),<in0=%edx
+xorl 192(%rsi),%edx
+
+# qhasm: (uint32) in1 ^= *(uint32 *) (m + 196)
+# asm 1: xorl 196(<m=int64#2),<in1=int64#4d
+# asm 2: xorl 196(<m=%rsi),<in1=%ecx
+xorl 196(%rsi),%ecx
+
+# qhasm: (uint32) in2 ^= *(uint32 *) (m + 200)
+# asm 1: xorl 200(<m=int64#2),<in2=int64#5d
+# asm 2: xorl 200(<m=%rsi),<in2=%r8d
+xorl 200(%rsi),%r8d
+
+# qhasm: (uint32) in3 ^= *(uint32 *) (m + 204)
+# asm 1: xorl 204(<m=int64#2),<in3=int64#6d
+# asm 2: xorl 204(<m=%rsi),<in3=%r9d
+xorl 204(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 192) = in0
+# asm 1: movl <in0=int64#3d,192(<out=int64#1)
+# asm 2: movl <in0=%edx,192(<out=%rdi)
+movl %edx,192(%rdi)
+
+# qhasm: *(uint32 *) (out + 196) = in1
+# asm 1: movl <in1=int64#4d,196(<out=int64#1)
+# asm 2: movl <in1=%ecx,196(<out=%rdi)
+movl %ecx,196(%rdi)
+
+# qhasm: *(uint32 *) (out + 200) = in2
+# asm 1: movl <in2=int64#5d,200(<out=int64#1)
+# asm 2: movl <in2=%r8d,200(<out=%rdi)
+movl %r8d,200(%rdi)
+
+# qhasm: *(uint32 *) (out + 204) = in3
+# asm 1: movl <in3=int64#6d,204(<out=int64#1)
+# asm 2: movl <in3=%r9d,204(<out=%rdi)
+movl %r9d,204(%rdi)
+
+# qhasm: uint32323232 z4 += orig4
+# asm 1: paddd <orig4=stack128#16,<z4=int6464#15
+# asm 2: paddd <orig4=240(%rsp),<z4=%xmm14
+paddd 240(%rsp),%xmm14
+
+# qhasm: uint32323232 z5 += orig5
+# asm 1: paddd <orig5=stack128#5,<z5=int6464#1
+# asm 2: paddd <orig5=64(%rsp),<z5=%xmm0
+paddd 64(%rsp),%xmm0
+
+# qhasm: uint32323232 z6 += orig6
+# asm 1: paddd <orig6=stack128#9,<z6=int6464#6
+# asm 2: paddd <orig6=128(%rsp),<z6=%xmm5
+paddd 128(%rsp),%xmm5
+
+# qhasm: uint32323232 z7 += orig7
+# asm 1: paddd <orig7=stack128#13,<z7=int6464#9
+# asm 2: paddd <orig7=192(%rsp),<z7=%xmm8
+paddd 192(%rsp),%xmm8
+
+# qhasm: in4 = z4
+# asm 1: movd <z4=int6464#15,>in4=int64#3
+# asm 2: movd <z4=%xmm14,>in4=%rdx
+movd %xmm14,%rdx
+
+# qhasm: in5 = z5
+# asm 1: movd <z5=int6464#1,>in5=int64#4
+# asm 2: movd <z5=%xmm0,>in5=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in6 = z6
+# asm 1: movd <z6=int6464#6,>in6=int64#5
+# asm 2: movd <z6=%xmm5,>in6=%r8
+movd %xmm5,%r8
+
+# qhasm: in7 = z7
+# asm 1: movd <z7=int6464#9,>in7=int64#6
+# asm 2: movd <z7=%xmm8,>in7=%r9
+movd %xmm8,%r9
+
+# qhasm: z4 <<<= 96
+# asm 1: pshufd $0x39,<z4=int6464#15,<z4=int6464#15
+# asm 2: pshufd $0x39,<z4=%xmm14,<z4=%xmm14
+pshufd $0x39,%xmm14,%xmm14
+
+# qhasm: z5 <<<= 96
+# asm 1: pshufd $0x39,<z5=int6464#1,<z5=int6464#1
+# asm 2: pshufd $0x39,<z5=%xmm0,<z5=%xmm0
+pshufd $0x39,%xmm0,%xmm0
+
+# qhasm: z6 <<<= 96
+# asm 1: pshufd $0x39,<z6=int6464#6,<z6=int6464#6
+# asm 2: pshufd $0x39,<z6=%xmm5,<z6=%xmm5
+pshufd $0x39,%xmm5,%xmm5
+
+# qhasm: z7 <<<= 96
+# asm 1: pshufd $0x39,<z7=int6464#9,<z7=int6464#9
+# asm 2: pshufd $0x39,<z7=%xmm8,<z7=%xmm8
+pshufd $0x39,%xmm8,%xmm8
+
+# qhasm: (uint32) in4 ^= *(uint32 *) (m + 16)
+# asm 1: xorl 16(<m=int64#2),<in4=int64#3d
+# asm 2: xorl 16(<m=%rsi),<in4=%edx
+xorl 16(%rsi),%edx
+
+# qhasm: (uint32) in5 ^= *(uint32 *) (m + 20)
+# asm 1: xorl 20(<m=int64#2),<in5=int64#4d
+# asm 2: xorl 20(<m=%rsi),<in5=%ecx
+xorl 20(%rsi),%ecx
+
+# qhasm: (uint32) in6 ^= *(uint32 *) (m + 24)
+# asm 1: xorl 24(<m=int64#2),<in6=int64#5d
+# asm 2: xorl 24(<m=%rsi),<in6=%r8d
+xorl 24(%rsi),%r8d
+
+# qhasm: (uint32) in7 ^= *(uint32 *) (m + 28)
+# asm 1: xorl 28(<m=int64#2),<in7=int64#6d
+# asm 2: xorl 28(<m=%rsi),<in7=%r9d
+xorl 28(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 16) = in4
+# asm 1: movl <in4=int64#3d,16(<out=int64#1)
+# asm 2: movl <in4=%edx,16(<out=%rdi)
+movl %edx,16(%rdi)
+
+# qhasm: *(uint32 *) (out + 20) = in5
+# asm 1: movl <in5=int64#4d,20(<out=int64#1)
+# asm 2: movl <in5=%ecx,20(<out=%rdi)
+movl %ecx,20(%rdi)
+
+# qhasm: *(uint32 *) (out + 24) = in6
+# asm 1: movl <in6=int64#5d,24(<out=int64#1)
+# asm 2: movl <in6=%r8d,24(<out=%rdi)
+movl %r8d,24(%rdi)
+
+# qhasm: *(uint32 *) (out + 28) = in7
+# asm 1: movl <in7=int64#6d,28(<out=int64#1)
+# asm 2: movl <in7=%r9d,28(<out=%rdi)
+movl %r9d,28(%rdi)
+
+# qhasm: in4 = z4
+# asm 1: movd <z4=int6464#15,>in4=int64#3
+# asm 2: movd <z4=%xmm14,>in4=%rdx
+movd %xmm14,%rdx
+
+# qhasm: in5 = z5
+# asm 1: movd <z5=int6464#1,>in5=int64#4
+# asm 2: movd <z5=%xmm0,>in5=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in6 = z6
+# asm 1: movd <z6=int6464#6,>in6=int64#5
+# asm 2: movd <z6=%xmm5,>in6=%r8
+movd %xmm5,%r8
+
+# qhasm: in7 = z7
+# asm 1: movd <z7=int6464#9,>in7=int64#6
+# asm 2: movd <z7=%xmm8,>in7=%r9
+movd %xmm8,%r9
+
+# qhasm: z4 <<<= 96
+# asm 1: pshufd $0x39,<z4=int6464#15,<z4=int6464#15
+# asm 2: pshufd $0x39,<z4=%xmm14,<z4=%xmm14
+pshufd $0x39,%xmm14,%xmm14
+
+# qhasm: z5 <<<= 96
+# asm 1: pshufd $0x39,<z5=int6464#1,<z5=int6464#1
+# asm 2: pshufd $0x39,<z5=%xmm0,<z5=%xmm0
+pshufd $0x39,%xmm0,%xmm0
+
+# qhasm: z6 <<<= 96
+# asm 1: pshufd $0x39,<z6=int6464#6,<z6=int6464#6
+# asm 2: pshufd $0x39,<z6=%xmm5,<z6=%xmm5
+pshufd $0x39,%xmm5,%xmm5
+
+# qhasm: z7 <<<= 96
+# asm 1: pshufd $0x39,<z7=int6464#9,<z7=int6464#9
+# asm 2: pshufd $0x39,<z7=%xmm8,<z7=%xmm8
+pshufd $0x39,%xmm8,%xmm8
+
+# qhasm: (uint32) in4 ^= *(uint32 *) (m + 80)
+# asm 1: xorl 80(<m=int64#2),<in4=int64#3d
+# asm 2: xorl 80(<m=%rsi),<in4=%edx
+xorl 80(%rsi),%edx
+
+# qhasm: (uint32) in5 ^= *(uint32 *) (m + 84)
+# asm 1: xorl 84(<m=int64#2),<in5=int64#4d
+# asm 2: xorl 84(<m=%rsi),<in5=%ecx
+xorl 84(%rsi),%ecx
+
+# qhasm: (uint32) in6 ^= *(uint32 *) (m + 88)
+# asm 1: xorl 88(<m=int64#2),<in6=int64#5d
+# asm 2: xorl 88(<m=%rsi),<in6=%r8d
+xorl 88(%rsi),%r8d
+
+# qhasm: (uint32) in7 ^= *(uint32 *) (m + 92)
+# asm 1: xorl 92(<m=int64#2),<in7=int64#6d
+# asm 2: xorl 92(<m=%rsi),<in7=%r9d
+xorl 92(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 80) = in4
+# asm 1: movl <in4=int64#3d,80(<out=int64#1)
+# asm 2: movl <in4=%edx,80(<out=%rdi)
+movl %edx,80(%rdi)
+
+# qhasm: *(uint32 *) (out + 84) = in5
+# asm 1: movl <in5=int64#4d,84(<out=int64#1)
+# asm 2: movl <in5=%ecx,84(<out=%rdi)
+movl %ecx,84(%rdi)
+
+# qhasm: *(uint32 *) (out + 88) = in6
+# asm 1: movl <in6=int64#5d,88(<out=int64#1)
+# asm 2: movl <in6=%r8d,88(<out=%rdi)
+movl %r8d,88(%rdi)
+
+# qhasm: *(uint32 *) (out + 92) = in7
+# asm 1: movl <in7=int64#6d,92(<out=int64#1)
+# asm 2: movl <in7=%r9d,92(<out=%rdi)
+movl %r9d,92(%rdi)
+
+# qhasm: in4 = z4
+# asm 1: movd <z4=int6464#15,>in4=int64#3
+# asm 2: movd <z4=%xmm14,>in4=%rdx
+movd %xmm14,%rdx
+
+# qhasm: in5 = z5
+# asm 1: movd <z5=int6464#1,>in5=int64#4
+# asm 2: movd <z5=%xmm0,>in5=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in6 = z6
+# asm 1: movd <z6=int6464#6,>in6=int64#5
+# asm 2: movd <z6=%xmm5,>in6=%r8
+movd %xmm5,%r8
+
+# qhasm: in7 = z7
+# asm 1: movd <z7=int6464#9,>in7=int64#6
+# asm 2: movd <z7=%xmm8,>in7=%r9
+movd %xmm8,%r9
+
+# qhasm: z4 <<<= 96
+# asm 1: pshufd $0x39,<z4=int6464#15,<z4=int6464#15
+# asm 2: pshufd $0x39,<z4=%xmm14,<z4=%xmm14
+pshufd $0x39,%xmm14,%xmm14
+
+# qhasm: z5 <<<= 96
+# asm 1: pshufd $0x39,<z5=int6464#1,<z5=int6464#1
+# asm 2: pshufd $0x39,<z5=%xmm0,<z5=%xmm0
+pshufd $0x39,%xmm0,%xmm0
+
+# qhasm: z6 <<<= 96
+# asm 1: pshufd $0x39,<z6=int6464#6,<z6=int6464#6
+# asm 2: pshufd $0x39,<z6=%xmm5,<z6=%xmm5
+pshufd $0x39,%xmm5,%xmm5
+
+# qhasm: z7 <<<= 96
+# asm 1: pshufd $0x39,<z7=int6464#9,<z7=int6464#9
+# asm 2: pshufd $0x39,<z7=%xmm8,<z7=%xmm8
+pshufd $0x39,%xmm8,%xmm8
+
+# qhasm: (uint32) in4 ^= *(uint32 *) (m + 144)
+# asm 1: xorl 144(<m=int64#2),<in4=int64#3d
+# asm 2: xorl 144(<m=%rsi),<in4=%edx
+xorl 144(%rsi),%edx
+
+# qhasm: (uint32) in5 ^= *(uint32 *) (m + 148)
+# asm 1: xorl 148(<m=int64#2),<in5=int64#4d
+# asm 2: xorl 148(<m=%rsi),<in5=%ecx
+xorl 148(%rsi),%ecx
+
+# qhasm: (uint32) in6 ^= *(uint32 *) (m + 152)
+# asm 1: xorl 152(<m=int64#2),<in6=int64#5d
+# asm 2: xorl 152(<m=%rsi),<in6=%r8d
+xorl 152(%rsi),%r8d
+
+# qhasm: (uint32) in7 ^= *(uint32 *) (m + 156)
+# asm 1: xorl 156(<m=int64#2),<in7=int64#6d
+# asm 2: xorl 156(<m=%rsi),<in7=%r9d
+xorl 156(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 144) = in4
+# asm 1: movl <in4=int64#3d,144(<out=int64#1)
+# asm 2: movl <in4=%edx,144(<out=%rdi)
+movl %edx,144(%rdi)
+
+# qhasm: *(uint32 *) (out + 148) = in5
+# asm 1: movl <in5=int64#4d,148(<out=int64#1)
+# asm 2: movl <in5=%ecx,148(<out=%rdi)
+movl %ecx,148(%rdi)
+
+# qhasm: *(uint32 *) (out + 152) = in6
+# asm 1: movl <in6=int64#5d,152(<out=int64#1)
+# asm 2: movl <in6=%r8d,152(<out=%rdi)
+movl %r8d,152(%rdi)
+
+# qhasm: *(uint32 *) (out + 156) = in7
+# asm 1: movl <in7=int64#6d,156(<out=int64#1)
+# asm 2: movl <in7=%r9d,156(<out=%rdi)
+movl %r9d,156(%rdi)
+
+# qhasm: in4 = z4
+# asm 1: movd <z4=int6464#15,>in4=int64#3
+# asm 2: movd <z4=%xmm14,>in4=%rdx
+movd %xmm14,%rdx
+
+# qhasm: in5 = z5
+# asm 1: movd <z5=int6464#1,>in5=int64#4
+# asm 2: movd <z5=%xmm0,>in5=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in6 = z6
+# asm 1: movd <z6=int6464#6,>in6=int64#5
+# asm 2: movd <z6=%xmm5,>in6=%r8
+movd %xmm5,%r8
+
+# qhasm: in7 = z7
+# asm 1: movd <z7=int6464#9,>in7=int64#6
+# asm 2: movd <z7=%xmm8,>in7=%r9
+movd %xmm8,%r9
+
+# qhasm: (uint32) in4 ^= *(uint32 *) (m + 208)
+# asm 1: xorl 208(<m=int64#2),<in4=int64#3d
+# asm 2: xorl 208(<m=%rsi),<in4=%edx
+xorl 208(%rsi),%edx
+
+# qhasm: (uint32) in5 ^= *(uint32 *) (m + 212)
+# asm 1: xorl 212(<m=int64#2),<in5=int64#4d
+# asm 2: xorl 212(<m=%rsi),<in5=%ecx
+xorl 212(%rsi),%ecx
+
+# qhasm: (uint32) in6 ^= *(uint32 *) (m + 216)
+# asm 1: xorl 216(<m=int64#2),<in6=int64#5d
+# asm 2: xorl 216(<m=%rsi),<in6=%r8d
+xorl 216(%rsi),%r8d
+
+# qhasm: (uint32) in7 ^= *(uint32 *) (m + 220)
+# asm 1: xorl 220(<m=int64#2),<in7=int64#6d
+# asm 2: xorl 220(<m=%rsi),<in7=%r9d
+xorl 220(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 208) = in4
+# asm 1: movl <in4=int64#3d,208(<out=int64#1)
+# asm 2: movl <in4=%edx,208(<out=%rdi)
+movl %edx,208(%rdi)
+
+# qhasm: *(uint32 *) (out + 212) = in5
+# asm 1: movl <in5=int64#4d,212(<out=int64#1)
+# asm 2: movl <in5=%ecx,212(<out=%rdi)
+movl %ecx,212(%rdi)
+
+# qhasm: *(uint32 *) (out + 216) = in6
+# asm 1: movl <in6=int64#5d,216(<out=int64#1)
+# asm 2: movl <in6=%r8d,216(<out=%rdi)
+movl %r8d,216(%rdi)
+
+# qhasm: *(uint32 *) (out + 220) = in7
+# asm 1: movl <in7=int64#6d,220(<out=int64#1)
+# asm 2: movl <in7=%r9d,220(<out=%rdi)
+movl %r9d,220(%rdi)
+
+# qhasm: uint32323232 z8 += orig8
+# asm 1: paddd <orig8=stack128#19,<z8=int6464#16
+# asm 2: paddd <orig8=288(%rsp),<z8=%xmm15
+paddd 288(%rsp),%xmm15
+
+# qhasm: uint32323232 z9 += orig9
+# asm 1: paddd <orig9=stack128#20,<z9=int6464#12
+# asm 2: paddd <orig9=304(%rsp),<z9=%xmm11
+paddd 304(%rsp),%xmm11
+
+# qhasm: uint32323232 z10 += orig10
+# asm 1: paddd <orig10=stack128#6,<z10=int6464#2
+# asm 2: paddd <orig10=80(%rsp),<z10=%xmm1
+paddd 80(%rsp),%xmm1
+
+# qhasm: uint32323232 z11 += orig11
+# asm 1: paddd <orig11=stack128#10,<z11=int6464#7
+# asm 2: paddd <orig11=144(%rsp),<z11=%xmm6
+paddd 144(%rsp),%xmm6
+
+# qhasm: in8 = z8
+# asm 1: movd <z8=int6464#16,>in8=int64#3
+# asm 2: movd <z8=%xmm15,>in8=%rdx
+movd %xmm15,%rdx
+
+# qhasm: in9 = z9
+# asm 1: movd <z9=int6464#12,>in9=int64#4
+# asm 2: movd <z9=%xmm11,>in9=%rcx
+movd %xmm11,%rcx
+
+# qhasm: in10 = z10
+# asm 1: movd <z10=int6464#2,>in10=int64#5
+# asm 2: movd <z10=%xmm1,>in10=%r8
+movd %xmm1,%r8
+
+# qhasm: in11 = z11
+# asm 1: movd <z11=int6464#7,>in11=int64#6
+# asm 2: movd <z11=%xmm6,>in11=%r9
+movd %xmm6,%r9
+
+# qhasm: z8 <<<= 96
+# asm 1: pshufd $0x39,<z8=int6464#16,<z8=int6464#16
+# asm 2: pshufd $0x39,<z8=%xmm15,<z8=%xmm15
+pshufd $0x39,%xmm15,%xmm15
+
+# qhasm: z9 <<<= 96
+# asm 1: pshufd $0x39,<z9=int6464#12,<z9=int6464#12
+# asm 2: pshufd $0x39,<z9=%xmm11,<z9=%xmm11
+pshufd $0x39,%xmm11,%xmm11
+
+# qhasm: z10 <<<= 96
+# asm 1: pshufd $0x39,<z10=int6464#2,<z10=int6464#2
+# asm 2: pshufd $0x39,<z10=%xmm1,<z10=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: z11 <<<= 96
+# asm 1: pshufd $0x39,<z11=int6464#7,<z11=int6464#7
+# asm 2: pshufd $0x39,<z11=%xmm6,<z11=%xmm6
+pshufd $0x39,%xmm6,%xmm6
+
+# qhasm: (uint32) in8 ^= *(uint32 *) (m + 32)
+# asm 1: xorl 32(<m=int64#2),<in8=int64#3d
+# asm 2: xorl 32(<m=%rsi),<in8=%edx
+xorl 32(%rsi),%edx
+
+# qhasm: (uint32) in9 ^= *(uint32 *) (m + 36)
+# asm 1: xorl 36(<m=int64#2),<in9=int64#4d
+# asm 2: xorl 36(<m=%rsi),<in9=%ecx
+xorl 36(%rsi),%ecx
+
+# qhasm: (uint32) in10 ^= *(uint32 *) (m + 40)
+# asm 1: xorl 40(<m=int64#2),<in10=int64#5d
+# asm 2: xorl 40(<m=%rsi),<in10=%r8d
+xorl 40(%rsi),%r8d
+
+# qhasm: (uint32) in11 ^= *(uint32 *) (m + 44)
+# asm 1: xorl 44(<m=int64#2),<in11=int64#6d
+# asm 2: xorl 44(<m=%rsi),<in11=%r9d
+xorl 44(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 32) = in8
+# asm 1: movl <in8=int64#3d,32(<out=int64#1)
+# asm 2: movl <in8=%edx,32(<out=%rdi)
+movl %edx,32(%rdi)
+
+# qhasm: *(uint32 *) (out + 36) = in9
+# asm 1: movl <in9=int64#4d,36(<out=int64#1)
+# asm 2: movl <in9=%ecx,36(<out=%rdi)
+movl %ecx,36(%rdi)
+
+# qhasm: *(uint32 *) (out + 40) = in10
+# asm 1: movl <in10=int64#5d,40(<out=int64#1)
+# asm 2: movl <in10=%r8d,40(<out=%rdi)
+movl %r8d,40(%rdi)
+
+# qhasm: *(uint32 *) (out + 44) = in11
+# asm 1: movl <in11=int64#6d,44(<out=int64#1)
+# asm 2: movl <in11=%r9d,44(<out=%rdi)
+movl %r9d,44(%rdi)
+
+# qhasm: in8 = z8
+# asm 1: movd <z8=int6464#16,>in8=int64#3
+# asm 2: movd <z8=%xmm15,>in8=%rdx
+movd %xmm15,%rdx
+
+# qhasm: in9 = z9
+# asm 1: movd <z9=int6464#12,>in9=int64#4
+# asm 2: movd <z9=%xmm11,>in9=%rcx
+movd %xmm11,%rcx
+
+# qhasm: in10 = z10
+# asm 1: movd <z10=int6464#2,>in10=int64#5
+# asm 2: movd <z10=%xmm1,>in10=%r8
+movd %xmm1,%r8
+
+# qhasm: in11 = z11
+# asm 1: movd <z11=int6464#7,>in11=int64#6
+# asm 2: movd <z11=%xmm6,>in11=%r9
+movd %xmm6,%r9
+
+# qhasm: z8 <<<= 96
+# asm 1: pshufd $0x39,<z8=int6464#16,<z8=int6464#16
+# asm 2: pshufd $0x39,<z8=%xmm15,<z8=%xmm15
+pshufd $0x39,%xmm15,%xmm15
+
+# qhasm: z9 <<<= 96
+# asm 1: pshufd $0x39,<z9=int6464#12,<z9=int6464#12
+# asm 2: pshufd $0x39,<z9=%xmm11,<z9=%xmm11
+pshufd $0x39,%xmm11,%xmm11
+
+# qhasm: z10 <<<= 96
+# asm 1: pshufd $0x39,<z10=int6464#2,<z10=int6464#2
+# asm 2: pshufd $0x39,<z10=%xmm1,<z10=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: z11 <<<= 96
+# asm 1: pshufd $0x39,<z11=int6464#7,<z11=int6464#7
+# asm 2: pshufd $0x39,<z11=%xmm6,<z11=%xmm6
+pshufd $0x39,%xmm6,%xmm6
+
+# qhasm: (uint32) in8 ^= *(uint32 *) (m + 96)
+# asm 1: xorl 96(<m=int64#2),<in8=int64#3d
+# asm 2: xorl 96(<m=%rsi),<in8=%edx
+xorl 96(%rsi),%edx
+
+# qhasm: (uint32) in9 ^= *(uint32 *) (m + 100)
+# asm 1: xorl 100(<m=int64#2),<in9=int64#4d
+# asm 2: xorl 100(<m=%rsi),<in9=%ecx
+xorl 100(%rsi),%ecx
+
+# qhasm: (uint32) in10 ^= *(uint32 *) (m + 104)
+# asm 1: xorl 104(<m=int64#2),<in10=int64#5d
+# asm 2: xorl 104(<m=%rsi),<in10=%r8d
+xorl 104(%rsi),%r8d
+
+# qhasm: (uint32) in11 ^= *(uint32 *) (m + 108)
+# asm 1: xorl 108(<m=int64#2),<in11=int64#6d
+# asm 2: xorl 108(<m=%rsi),<in11=%r9d
+xorl 108(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 96) = in8
+# asm 1: movl <in8=int64#3d,96(<out=int64#1)
+# asm 2: movl <in8=%edx,96(<out=%rdi)
+movl %edx,96(%rdi)
+
+# qhasm: *(uint32 *) (out + 100) = in9
+# asm 1: movl <in9=int64#4d,100(<out=int64#1)
+# asm 2: movl <in9=%ecx,100(<out=%rdi)
+movl %ecx,100(%rdi)
+
+# qhasm: *(uint32 *) (out + 104) = in10
+# asm 1: movl <in10=int64#5d,104(<out=int64#1)
+# asm 2: movl <in10=%r8d,104(<out=%rdi)
+movl %r8d,104(%rdi)
+
+# qhasm: *(uint32 *) (out + 108) = in11
+# asm 1: movl <in11=int64#6d,108(<out=int64#1)
+# asm 2: movl <in11=%r9d,108(<out=%rdi)
+movl %r9d,108(%rdi)
+
+# qhasm: in8 = z8
+# asm 1: movd <z8=int6464#16,>in8=int64#3
+# asm 2: movd <z8=%xmm15,>in8=%rdx
+movd %xmm15,%rdx
+
+# qhasm: in9 = z9
+# asm 1: movd <z9=int6464#12,>in9=int64#4
+# asm 2: movd <z9=%xmm11,>in9=%rcx
+movd %xmm11,%rcx
+
+# qhasm: in10 = z10
+# asm 1: movd <z10=int6464#2,>in10=int64#5
+# asm 2: movd <z10=%xmm1,>in10=%r8
+movd %xmm1,%r8
+
+# qhasm: in11 = z11
+# asm 1: movd <z11=int6464#7,>in11=int64#6
+# asm 2: movd <z11=%xmm6,>in11=%r9
+movd %xmm6,%r9
+
+# qhasm: z8 <<<= 96
+# asm 1: pshufd $0x39,<z8=int6464#16,<z8=int6464#16
+# asm 2: pshufd $0x39,<z8=%xmm15,<z8=%xmm15
+pshufd $0x39,%xmm15,%xmm15
+
+# qhasm: z9 <<<= 96
+# asm 1: pshufd $0x39,<z9=int6464#12,<z9=int6464#12
+# asm 2: pshufd $0x39,<z9=%xmm11,<z9=%xmm11
+pshufd $0x39,%xmm11,%xmm11
+
+# qhasm: z10 <<<= 96
+# asm 1: pshufd $0x39,<z10=int6464#2,<z10=int6464#2
+# asm 2: pshufd $0x39,<z10=%xmm1,<z10=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: z11 <<<= 96
+# asm 1: pshufd $0x39,<z11=int6464#7,<z11=int6464#7
+# asm 2: pshufd $0x39,<z11=%xmm6,<z11=%xmm6
+pshufd $0x39,%xmm6,%xmm6
+
+# qhasm: (uint32) in8 ^= *(uint32 *) (m + 160)
+# asm 1: xorl 160(<m=int64#2),<in8=int64#3d
+# asm 2: xorl 160(<m=%rsi),<in8=%edx
+xorl 160(%rsi),%edx
+
+# qhasm: (uint32) in9 ^= *(uint32 *) (m + 164)
+# asm 1: xorl 164(<m=int64#2),<in9=int64#4d
+# asm 2: xorl 164(<m=%rsi),<in9=%ecx
+xorl 164(%rsi),%ecx
+
+# qhasm: (uint32) in10 ^= *(uint32 *) (m + 168)
+# asm 1: xorl 168(<m=int64#2),<in10=int64#5d
+# asm 2: xorl 168(<m=%rsi),<in10=%r8d
+xorl 168(%rsi),%r8d
+
+# qhasm: (uint32) in11 ^= *(uint32 *) (m + 172)
+# asm 1: xorl 172(<m=int64#2),<in11=int64#6d
+# asm 2: xorl 172(<m=%rsi),<in11=%r9d
+xorl 172(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 160) = in8
+# asm 1: movl <in8=int64#3d,160(<out=int64#1)
+# asm 2: movl <in8=%edx,160(<out=%rdi)
+movl %edx,160(%rdi)
+
+# qhasm: *(uint32 *) (out + 164) = in9
+# asm 1: movl <in9=int64#4d,164(<out=int64#1)
+# asm 2: movl <in9=%ecx,164(<out=%rdi)
+movl %ecx,164(%rdi)
+
+# qhasm: *(uint32 *) (out + 168) = in10
+# asm 1: movl <in10=int64#5d,168(<out=int64#1)
+# asm 2: movl <in10=%r8d,168(<out=%rdi)
+movl %r8d,168(%rdi)
+
+# qhasm: *(uint32 *) (out + 172) = in11
+# asm 1: movl <in11=int64#6d,172(<out=int64#1)
+# asm 2: movl <in11=%r9d,172(<out=%rdi)
+movl %r9d,172(%rdi)
+
+# qhasm: in8 = z8
+# asm 1: movd <z8=int6464#16,>in8=int64#3
+# asm 2: movd <z8=%xmm15,>in8=%rdx
+movd %xmm15,%rdx
+
+# qhasm: in9 = z9
+# asm 1: movd <z9=int6464#12,>in9=int64#4
+# asm 2: movd <z9=%xmm11,>in9=%rcx
+movd %xmm11,%rcx
+
+# qhasm: in10 = z10
+# asm 1: movd <z10=int6464#2,>in10=int64#5
+# asm 2: movd <z10=%xmm1,>in10=%r8
+movd %xmm1,%r8
+
+# qhasm: in11 = z11
+# asm 1: movd <z11=int6464#7,>in11=int64#6
+# asm 2: movd <z11=%xmm6,>in11=%r9
+movd %xmm6,%r9
+
+# qhasm: (uint32) in8 ^= *(uint32 *) (m + 224)
+# asm 1: xorl 224(<m=int64#2),<in8=int64#3d
+# asm 2: xorl 224(<m=%rsi),<in8=%edx
+xorl 224(%rsi),%edx
+
+# qhasm: (uint32) in9 ^= *(uint32 *) (m + 228)
+# asm 1: xorl 228(<m=int64#2),<in9=int64#4d
+# asm 2: xorl 228(<m=%rsi),<in9=%ecx
+xorl 228(%rsi),%ecx
+
+# qhasm: (uint32) in10 ^= *(uint32 *) (m + 232)
+# asm 1: xorl 232(<m=int64#2),<in10=int64#5d
+# asm 2: xorl 232(<m=%rsi),<in10=%r8d
+xorl 232(%rsi),%r8d
+
+# qhasm: (uint32) in11 ^= *(uint32 *) (m + 236)
+# asm 1: xorl 236(<m=int64#2),<in11=int64#6d
+# asm 2: xorl 236(<m=%rsi),<in11=%r9d
+xorl 236(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 224) = in8
+# asm 1: movl <in8=int64#3d,224(<out=int64#1)
+# asm 2: movl <in8=%edx,224(<out=%rdi)
+movl %edx,224(%rdi)
+
+# qhasm: *(uint32 *) (out + 228) = in9
+# asm 1: movl <in9=int64#4d,228(<out=int64#1)
+# asm 2: movl <in9=%ecx,228(<out=%rdi)
+movl %ecx,228(%rdi)
+
+# qhasm: *(uint32 *) (out + 232) = in10
+# asm 1: movl <in10=int64#5d,232(<out=int64#1)
+# asm 2: movl <in10=%r8d,232(<out=%rdi)
+movl %r8d,232(%rdi)
+
+# qhasm: *(uint32 *) (out + 236) = in11
+# asm 1: movl <in11=int64#6d,236(<out=int64#1)
+# asm 2: movl <in11=%r9d,236(<out=%rdi)
+movl %r9d,236(%rdi)
+
+# qhasm: uint32323232 z12 += orig12
+# asm 1: paddd <orig12=stack128#11,<z12=int6464#14
+# asm 2: paddd <orig12=160(%rsp),<z12=%xmm13
+paddd 160(%rsp),%xmm13
+
+# qhasm: uint32323232 z13 += orig13
+# asm 1: paddd <orig13=stack128#14,<z13=int6464#10
+# asm 2: paddd <orig13=208(%rsp),<z13=%xmm9
+paddd 208(%rsp),%xmm9
+
+# qhasm: uint32323232 z14 += orig14
+# asm 1: paddd <orig14=stack128#17,<z14=int6464#4
+# asm 2: paddd <orig14=256(%rsp),<z14=%xmm3
+paddd 256(%rsp),%xmm3
+
+# qhasm: uint32323232 z15 += orig15
+# asm 1: paddd <orig15=stack128#7,<z15=int6464#3
+# asm 2: paddd <orig15=96(%rsp),<z15=%xmm2
+paddd 96(%rsp),%xmm2
+
+# qhasm: in12 = z12
+# asm 1: movd <z12=int6464#14,>in12=int64#3
+# asm 2: movd <z12=%xmm13,>in12=%rdx
+movd %xmm13,%rdx
+
+# qhasm: in13 = z13
+# asm 1: movd <z13=int6464#10,>in13=int64#4
+# asm 2: movd <z13=%xmm9,>in13=%rcx
+movd %xmm9,%rcx
+
+# qhasm: in14 = z14
+# asm 1: movd <z14=int6464#4,>in14=int64#5
+# asm 2: movd <z14=%xmm3,>in14=%r8
+movd %xmm3,%r8
+
+# qhasm: in15 = z15
+# asm 1: movd <z15=int6464#3,>in15=int64#6
+# asm 2: movd <z15=%xmm2,>in15=%r9
+movd %xmm2,%r9
+
+# qhasm: z12 <<<= 96
+# asm 1: pshufd $0x39,<z12=int6464#14,<z12=int6464#14
+# asm 2: pshufd $0x39,<z12=%xmm13,<z12=%xmm13
+pshufd $0x39,%xmm13,%xmm13
+
+# qhasm: z13 <<<= 96
+# asm 1: pshufd $0x39,<z13=int6464#10,<z13=int6464#10
+# asm 2: pshufd $0x39,<z13=%xmm9,<z13=%xmm9
+pshufd $0x39,%xmm9,%xmm9
+
+# qhasm: z14 <<<= 96
+# asm 1: pshufd $0x39,<z14=int6464#4,<z14=int6464#4
+# asm 2: pshufd $0x39,<z14=%xmm3,<z14=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: z15 <<<= 96
+# asm 1: pshufd $0x39,<z15=int6464#3,<z15=int6464#3
+# asm 2: pshufd $0x39,<z15=%xmm2,<z15=%xmm2
+pshufd $0x39,%xmm2,%xmm2
+
+# qhasm: (uint32) in12 ^= *(uint32 *) (m + 48)
+# asm 1: xorl 48(<m=int64#2),<in12=int64#3d
+# asm 2: xorl 48(<m=%rsi),<in12=%edx
+xorl 48(%rsi),%edx
+
+# qhasm: (uint32) in13 ^= *(uint32 *) (m + 52)
+# asm 1: xorl 52(<m=int64#2),<in13=int64#4d
+# asm 2: xorl 52(<m=%rsi),<in13=%ecx
+xorl 52(%rsi),%ecx
+
+# qhasm: (uint32) in14 ^= *(uint32 *) (m + 56)
+# asm 1: xorl 56(<m=int64#2),<in14=int64#5d
+# asm 2: xorl 56(<m=%rsi),<in14=%r8d
+xorl 56(%rsi),%r8d
+
+# qhasm: (uint32) in15 ^= *(uint32 *) (m + 60)
+# asm 1: xorl 60(<m=int64#2),<in15=int64#6d
+# asm 2: xorl 60(<m=%rsi),<in15=%r9d
+xorl 60(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 48) = in12
+# asm 1: movl <in12=int64#3d,48(<out=int64#1)
+# asm 2: movl <in12=%edx,48(<out=%rdi)
+movl %edx,48(%rdi)
+
+# qhasm: *(uint32 *) (out + 52) = in13
+# asm 1: movl <in13=int64#4d,52(<out=int64#1)
+# asm 2: movl <in13=%ecx,52(<out=%rdi)
+movl %ecx,52(%rdi)
+
+# qhasm: *(uint32 *) (out + 56) = in14
+# asm 1: movl <in14=int64#5d,56(<out=int64#1)
+# asm 2: movl <in14=%r8d,56(<out=%rdi)
+movl %r8d,56(%rdi)
+
+# qhasm: *(uint32 *) (out + 60) = in15
+# asm 1: movl <in15=int64#6d,60(<out=int64#1)
+# asm 2: movl <in15=%r9d,60(<out=%rdi)
+movl %r9d,60(%rdi)
+
+# qhasm: in12 = z12
+# asm 1: movd <z12=int6464#14,>in12=int64#3
+# asm 2: movd <z12=%xmm13,>in12=%rdx
+movd %xmm13,%rdx
+
+# qhasm: in13 = z13
+# asm 1: movd <z13=int6464#10,>in13=int64#4
+# asm 2: movd <z13=%xmm9,>in13=%rcx
+movd %xmm9,%rcx
+
+# qhasm: in14 = z14
+# asm 1: movd <z14=int6464#4,>in14=int64#5
+# asm 2: movd <z14=%xmm3,>in14=%r8
+movd %xmm3,%r8
+
+# qhasm: in15 = z15
+# asm 1: movd <z15=int6464#3,>in15=int64#6
+# asm 2: movd <z15=%xmm2,>in15=%r9
+movd %xmm2,%r9
+
+# qhasm: z12 <<<= 96
+# asm 1: pshufd $0x39,<z12=int6464#14,<z12=int6464#14
+# asm 2: pshufd $0x39,<z12=%xmm13,<z12=%xmm13
+pshufd $0x39,%xmm13,%xmm13
+
+# qhasm: z13 <<<= 96
+# asm 1: pshufd $0x39,<z13=int6464#10,<z13=int6464#10
+# asm 2: pshufd $0x39,<z13=%xmm9,<z13=%xmm9
+pshufd $0x39,%xmm9,%xmm9
+
+# qhasm: z14 <<<= 96
+# asm 1: pshufd $0x39,<z14=int6464#4,<z14=int6464#4
+# asm 2: pshufd $0x39,<z14=%xmm3,<z14=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: z15 <<<= 96
+# asm 1: pshufd $0x39,<z15=int6464#3,<z15=int6464#3
+# asm 2: pshufd $0x39,<z15=%xmm2,<z15=%xmm2
+pshufd $0x39,%xmm2,%xmm2
+
+# qhasm: (uint32) in12 ^= *(uint32 *) (m + 112)
+# asm 1: xorl 112(<m=int64#2),<in12=int64#3d
+# asm 2: xorl 112(<m=%rsi),<in12=%edx
+xorl 112(%rsi),%edx
+
+# qhasm: (uint32) in13 ^= *(uint32 *) (m + 116)
+# asm 1: xorl 116(<m=int64#2),<in13=int64#4d
+# asm 2: xorl 116(<m=%rsi),<in13=%ecx
+xorl 116(%rsi),%ecx
+
+# qhasm: (uint32) in14 ^= *(uint32 *) (m + 120)
+# asm 1: xorl 120(<m=int64#2),<in14=int64#5d
+# asm 2: xorl 120(<m=%rsi),<in14=%r8d
+xorl 120(%rsi),%r8d
+
+# qhasm: (uint32) in15 ^= *(uint32 *) (m + 124)
+# asm 1: xorl 124(<m=int64#2),<in15=int64#6d
+# asm 2: xorl 124(<m=%rsi),<in15=%r9d
+xorl 124(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 112) = in12
+# asm 1: movl <in12=int64#3d,112(<out=int64#1)
+# asm 2: movl <in12=%edx,112(<out=%rdi)
+movl %edx,112(%rdi)
+
+# qhasm: *(uint32 *) (out + 116) = in13
+# asm 1: movl <in13=int64#4d,116(<out=int64#1)
+# asm 2: movl <in13=%ecx,116(<out=%rdi)
+movl %ecx,116(%rdi)
+
+# qhasm: *(uint32 *) (out + 120) = in14
+# asm 1: movl <in14=int64#5d,120(<out=int64#1)
+# asm 2: movl <in14=%r8d,120(<out=%rdi)
+movl %r8d,120(%rdi)
+
+# qhasm: *(uint32 *) (out + 124) = in15
+# asm 1: movl <in15=int64#6d,124(<out=int64#1)
+# asm 2: movl <in15=%r9d,124(<out=%rdi)
+movl %r9d,124(%rdi)
+
+# qhasm: in12 = z12
+# asm 1: movd <z12=int6464#14,>in12=int64#3
+# asm 2: movd <z12=%xmm13,>in12=%rdx
+movd %xmm13,%rdx
+
+# qhasm: in13 = z13
+# asm 1: movd <z13=int6464#10,>in13=int64#4
+# asm 2: movd <z13=%xmm9,>in13=%rcx
+movd %xmm9,%rcx
+
+# qhasm: in14 = z14
+# asm 1: movd <z14=int6464#4,>in14=int64#5
+# asm 2: movd <z14=%xmm3,>in14=%r8
+movd %xmm3,%r8
+
+# qhasm: in15 = z15
+# asm 1: movd <z15=int6464#3,>in15=int64#6
+# asm 2: movd <z15=%xmm2,>in15=%r9
+movd %xmm2,%r9
+
+# qhasm: z12 <<<= 96
+# asm 1: pshufd $0x39,<z12=int6464#14,<z12=int6464#14
+# asm 2: pshufd $0x39,<z12=%xmm13,<z12=%xmm13
+pshufd $0x39,%xmm13,%xmm13
+
+# qhasm: z13 <<<= 96
+# asm 1: pshufd $0x39,<z13=int6464#10,<z13=int6464#10
+# asm 2: pshufd $0x39,<z13=%xmm9,<z13=%xmm9
+pshufd $0x39,%xmm9,%xmm9
+
+# qhasm: z14 <<<= 96
+# asm 1: pshufd $0x39,<z14=int6464#4,<z14=int6464#4
+# asm 2: pshufd $0x39,<z14=%xmm3,<z14=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: z15 <<<= 96
+# asm 1: pshufd $0x39,<z15=int6464#3,<z15=int6464#3
+# asm 2: pshufd $0x39,<z15=%xmm2,<z15=%xmm2
+pshufd $0x39,%xmm2,%xmm2
+
+# qhasm: (uint32) in12 ^= *(uint32 *) (m + 176)
+# asm 1: xorl 176(<m=int64#2),<in12=int64#3d
+# asm 2: xorl 176(<m=%rsi),<in12=%edx
+xorl 176(%rsi),%edx
+
+# qhasm: (uint32) in13 ^= *(uint32 *) (m + 180)
+# asm 1: xorl 180(<m=int64#2),<in13=int64#4d
+# asm 2: xorl 180(<m=%rsi),<in13=%ecx
+xorl 180(%rsi),%ecx
+
+# qhasm: (uint32) in14 ^= *(uint32 *) (m + 184)
+# asm 1: xorl 184(<m=int64#2),<in14=int64#5d
+# asm 2: xorl 184(<m=%rsi),<in14=%r8d
+xorl 184(%rsi),%r8d
+
+# qhasm: (uint32) in15 ^= *(uint32 *) (m + 188)
+# asm 1: xorl 188(<m=int64#2),<in15=int64#6d
+# asm 2: xorl 188(<m=%rsi),<in15=%r9d
+xorl 188(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 176) = in12
+# asm 1: movl <in12=int64#3d,176(<out=int64#1)
+# asm 2: movl <in12=%edx,176(<out=%rdi)
+movl %edx,176(%rdi)
+
+# qhasm: *(uint32 *) (out + 180) = in13
+# asm 1: movl <in13=int64#4d,180(<out=int64#1)
+# asm 2: movl <in13=%ecx,180(<out=%rdi)
+movl %ecx,180(%rdi)
+
+# qhasm: *(uint32 *) (out + 184) = in14
+# asm 1: movl <in14=int64#5d,184(<out=int64#1)
+# asm 2: movl <in14=%r8d,184(<out=%rdi)
+movl %r8d,184(%rdi)
+
+# qhasm: *(uint32 *) (out + 188) = in15
+# asm 1: movl <in15=int64#6d,188(<out=int64#1)
+# asm 2: movl <in15=%r9d,188(<out=%rdi)
+movl %r9d,188(%rdi)
+
+# qhasm: in12 = z12
+# asm 1: movd <z12=int6464#14,>in12=int64#3
+# asm 2: movd <z12=%xmm13,>in12=%rdx
+movd %xmm13,%rdx
+
+# qhasm: in13 = z13
+# asm 1: movd <z13=int6464#10,>in13=int64#4
+# asm 2: movd <z13=%xmm9,>in13=%rcx
+movd %xmm9,%rcx
+
+# qhasm: in14 = z14
+# asm 1: movd <z14=int6464#4,>in14=int64#5
+# asm 2: movd <z14=%xmm3,>in14=%r8
+movd %xmm3,%r8
+
+# qhasm: in15 = z15
+# asm 1: movd <z15=int6464#3,>in15=int64#6
+# asm 2: movd <z15=%xmm2,>in15=%r9
+movd %xmm2,%r9
+
+# qhasm: (uint32) in12 ^= *(uint32 *) (m + 240)
+# asm 1: xorl 240(<m=int64#2),<in12=int64#3d
+# asm 2: xorl 240(<m=%rsi),<in12=%edx
+xorl 240(%rsi),%edx
+
+# qhasm: (uint32) in13 ^= *(uint32 *) (m + 244)
+# asm 1: xorl 244(<m=int64#2),<in13=int64#4d
+# asm 2: xorl 244(<m=%rsi),<in13=%ecx
+xorl 244(%rsi),%ecx
+
+# qhasm: (uint32) in14 ^= *(uint32 *) (m + 248)
+# asm 1: xorl 248(<m=int64#2),<in14=int64#5d
+# asm 2: xorl 248(<m=%rsi),<in14=%r8d
+xorl 248(%rsi),%r8d
+
+# qhasm: (uint32) in15 ^= *(uint32 *) (m + 252)
+# asm 1: xorl 252(<m=int64#2),<in15=int64#6d
+# asm 2: xorl 252(<m=%rsi),<in15=%r9d
+xorl 252(%rsi),%r9d
+
+# qhasm: *(uint32 *) (out + 240) = in12
+# asm 1: movl <in12=int64#3d,240(<out=int64#1)
+# asm 2: movl <in12=%edx,240(<out=%rdi)
+movl %edx,240(%rdi)
+
+# qhasm: *(uint32 *) (out + 244) = in13
+# asm 1: movl <in13=int64#4d,244(<out=int64#1)
+# asm 2: movl <in13=%ecx,244(<out=%rdi)
+movl %ecx,244(%rdi)
+
+# qhasm: *(uint32 *) (out + 248) = in14
+# asm 1: movl <in14=int64#5d,248(<out=int64#1)
+# asm 2: movl <in14=%r8d,248(<out=%rdi)
+movl %r8d,248(%rdi)
+
+# qhasm: *(uint32 *) (out + 252) = in15
+# asm 1: movl <in15=int64#6d,252(<out=int64#1)
+# asm 2: movl <in15=%r9d,252(<out=%rdi)
+movl %r9d,252(%rdi)
+
+# qhasm: bytes = bytes_backup
+# asm 1: movq <bytes_backup=stack64#8,>bytes=int64#6
+# asm 2: movq <bytes_backup=408(%rsp),>bytes=%r9
+movq 408(%rsp),%r9
+
+# qhasm: bytes -= 256
+# asm 1: sub $256,<bytes=int64#6
+# asm 2: sub $256,<bytes=%r9
+sub $256,%r9
+
+# qhasm: m += 256
+# asm 1: add $256,<m=int64#2
+# asm 2: add $256,<m=%rsi
+add $256,%rsi
+
+# qhasm: out += 256
+# asm 1: add $256,<out=int64#1
+# asm 2: add $256,<out=%rdi
+add $256,%rdi
+
+# qhasm: unsigned<? bytes - 256
+# asm 1: cmp $256,<bytes=int64#6
+# asm 2: cmp $256,<bytes=%r9
+cmp $256,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto bytesatleast256 if !unsigned<
+jae ._bytesatleast256
+
+# qhasm: unsigned>? bytes - 0
+# asm 1: cmp $0,<bytes=int64#6
+# asm 2: cmp $0,<bytes=%r9
+cmp $0,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto done if !unsigned>
+jbe ._done
+# comment:fp stack unchanged by fallthrough
+
+# qhasm: bytesbetween1and255:
+._bytesbetween1and255:
+
+# qhasm: unsigned<? bytes - 64
+# asm 1: cmp $64,<bytes=int64#6
+# asm 2: cmp $64,<bytes=%r9
+cmp $64,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto nocopy if !unsigned<
+jae ._nocopy
+
+# qhasm: ctarget = out
+# asm 1: mov <out=int64#1,>ctarget=int64#3
+# asm 2: mov <out=%rdi,>ctarget=%rdx
+mov %rdi,%rdx
+
+# qhasm: out = &tmp
+# asm 1: leaq <tmp=stack512#1,>out=int64#1
+# asm 2: leaq <tmp=416(%rsp),>out=%rdi
+leaq 416(%rsp),%rdi
+
+# qhasm: i = bytes
+# asm 1: mov <bytes=int64#6,>i=int64#4
+# asm 2: mov <bytes=%r9,>i=%rcx
+mov %r9,%rcx
+
+# qhasm: while (i) { *out++ = *m++; --i }
+rep movsb
+
+# qhasm: out = &tmp
+# asm 1: leaq <tmp=stack512#1,>out=int64#1
+# asm 2: leaq <tmp=416(%rsp),>out=%rdi
+leaq 416(%rsp),%rdi
+
+# qhasm: m = &tmp
+# asm 1: leaq <tmp=stack512#1,>m=int64#2
+# asm 2: leaq <tmp=416(%rsp),>m=%rsi
+leaq 416(%rsp),%rsi
+# comment:fp stack unchanged by fallthrough
+
+# qhasm: nocopy:
+._nocopy:
+
+# qhasm: bytes_backup = bytes
+# asm 1: movq <bytes=int64#6,>bytes_backup=stack64#8
+# asm 2: movq <bytes=%r9,>bytes_backup=408(%rsp)
+movq %r9,408(%rsp)
+
+# qhasm: diag0 = x0
+# asm 1: movdqa <x0=stack128#4,>diag0=int6464#1
+# asm 2: movdqa <x0=48(%rsp),>diag0=%xmm0
+movdqa 48(%rsp),%xmm0
+
+# qhasm: diag1 = x1
+# asm 1: movdqa <x1=stack128#1,>diag1=int6464#2
+# asm 2: movdqa <x1=0(%rsp),>diag1=%xmm1
+movdqa 0(%rsp),%xmm1
+
+# qhasm: diag2 = x2
+# asm 1: movdqa <x2=stack128#2,>diag2=int6464#3
+# asm 2: movdqa <x2=16(%rsp),>diag2=%xmm2
+movdqa 16(%rsp),%xmm2
+
+# qhasm: diag3 = x3
+# asm 1: movdqa <x3=stack128#3,>diag3=int6464#4
+# asm 2: movdqa <x3=32(%rsp),>diag3=%xmm3
+movdqa 32(%rsp),%xmm3
+
+# qhasm: a0 = diag1
+# asm 1: movdqa <diag1=int6464#2,>a0=int6464#5
+# asm 2: movdqa <diag1=%xmm1,>a0=%xmm4
+movdqa %xmm1,%xmm4
+
+# qhasm: i = 12
+# asm 1: mov $12,>i=int64#4
+# asm 2: mov $12,>i=%rcx
+mov $12,%rcx
+
+# qhasm: mainloop2:
+._mainloop2:
+
+# qhasm: uint32323232 a0 += diag0
+# asm 1: paddd <diag0=int6464#1,<a0=int6464#5
+# asm 2: paddd <diag0=%xmm0,<a0=%xmm4
+paddd %xmm0,%xmm4
+
+# qhasm: a1 = diag0
+# asm 1: movdqa <diag0=int6464#1,>a1=int6464#6
+# asm 2: movdqa <diag0=%xmm0,>a1=%xmm5
+movdqa %xmm0,%xmm5
+
+# qhasm: b0 = a0
+# asm 1: movdqa <a0=int6464#5,>b0=int6464#7
+# asm 2: movdqa <a0=%xmm4,>b0=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a0 <<= 7
+# asm 1: pslld $7,<a0=int6464#5
+# asm 2: pslld $7,<a0=%xmm4
+pslld $7,%xmm4
+
+# qhasm: uint32323232 b0 >>= 25
+# asm 1: psrld $25,<b0=int6464#7
+# asm 2: psrld $25,<b0=%xmm6
+psrld $25,%xmm6
+
+# qhasm: diag3 ^= a0
+# asm 1: pxor <a0=int6464#5,<diag3=int6464#4
+# asm 2: pxor <a0=%xmm4,<diag3=%xmm3
+pxor %xmm4,%xmm3
+
+# qhasm: diag3 ^= b0
+# asm 1: pxor <b0=int6464#7,<diag3=int6464#4
+# asm 2: pxor <b0=%xmm6,<diag3=%xmm3
+pxor %xmm6,%xmm3
+
+# qhasm: uint32323232 a1 += diag3
+# asm 1: paddd <diag3=int6464#4,<a1=int6464#6
+# asm 2: paddd <diag3=%xmm3,<a1=%xmm5
+paddd %xmm3,%xmm5
+
+# qhasm: a2 = diag3
+# asm 1: movdqa <diag3=int6464#4,>a2=int6464#5
+# asm 2: movdqa <diag3=%xmm3,>a2=%xmm4
+movdqa %xmm3,%xmm4
+
+# qhasm: b1 = a1
+# asm 1: movdqa <a1=int6464#6,>b1=int6464#7
+# asm 2: movdqa <a1=%xmm5,>b1=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a1 <<= 9
+# asm 1: pslld $9,<a1=int6464#6
+# asm 2: pslld $9,<a1=%xmm5
+pslld $9,%xmm5
+
+# qhasm: uint32323232 b1 >>= 23
+# asm 1: psrld $23,<b1=int6464#7
+# asm 2: psrld $23,<b1=%xmm6
+psrld $23,%xmm6
+
+# qhasm: diag2 ^= a1
+# asm 1: pxor <a1=int6464#6,<diag2=int6464#3
+# asm 2: pxor <a1=%xmm5,<diag2=%xmm2
+pxor %xmm5,%xmm2
+
+# qhasm: diag3 <<<= 32
+# asm 1: pshufd $0x93,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x93,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x93,%xmm3,%xmm3
+
+# qhasm: diag2 ^= b1
+# asm 1: pxor <b1=int6464#7,<diag2=int6464#3
+# asm 2: pxor <b1=%xmm6,<diag2=%xmm2
+pxor %xmm6,%xmm2
+
+# qhasm: uint32323232 a2 += diag2
+# asm 1: paddd <diag2=int6464#3,<a2=int6464#5
+# asm 2: paddd <diag2=%xmm2,<a2=%xmm4
+paddd %xmm2,%xmm4
+
+# qhasm: a3 = diag2
+# asm 1: movdqa <diag2=int6464#3,>a3=int6464#6
+# asm 2: movdqa <diag2=%xmm2,>a3=%xmm5
+movdqa %xmm2,%xmm5
+
+# qhasm: b2 = a2
+# asm 1: movdqa <a2=int6464#5,>b2=int6464#7
+# asm 2: movdqa <a2=%xmm4,>b2=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a2 <<= 13
+# asm 1: pslld $13,<a2=int6464#5
+# asm 2: pslld $13,<a2=%xmm4
+pslld $13,%xmm4
+
+# qhasm: uint32323232 b2 >>= 19
+# asm 1: psrld $19,<b2=int6464#7
+# asm 2: psrld $19,<b2=%xmm6
+psrld $19,%xmm6
+
+# qhasm: diag1 ^= a2
+# asm 1: pxor <a2=int6464#5,<diag1=int6464#2
+# asm 2: pxor <a2=%xmm4,<diag1=%xmm1
+pxor %xmm4,%xmm1
+
+# qhasm: diag2 <<<= 64
+# asm 1: pshufd $0x4e,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x4e,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x4e,%xmm2,%xmm2
+
+# qhasm: diag1 ^= b2
+# asm 1: pxor <b2=int6464#7,<diag1=int6464#2
+# asm 2: pxor <b2=%xmm6,<diag1=%xmm1
+pxor %xmm6,%xmm1
+
+# qhasm: uint32323232 a3 += diag1
+# asm 1: paddd <diag1=int6464#2,<a3=int6464#6
+# asm 2: paddd <diag1=%xmm1,<a3=%xmm5
+paddd %xmm1,%xmm5
+
+# qhasm: a4 = diag3
+# asm 1: movdqa <diag3=int6464#4,>a4=int6464#5
+# asm 2: movdqa <diag3=%xmm3,>a4=%xmm4
+movdqa %xmm3,%xmm4
+
+# qhasm: b3 = a3
+# asm 1: movdqa <a3=int6464#6,>b3=int6464#7
+# asm 2: movdqa <a3=%xmm5,>b3=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a3 <<= 18
+# asm 1: pslld $18,<a3=int6464#6
+# asm 2: pslld $18,<a3=%xmm5
+pslld $18,%xmm5
+
+# qhasm: uint32323232 b3 >>= 14
+# asm 1: psrld $14,<b3=int6464#7
+# asm 2: psrld $14,<b3=%xmm6
+psrld $14,%xmm6
+
+# qhasm: diag0 ^= a3
+# asm 1: pxor <a3=int6464#6,<diag0=int6464#1
+# asm 2: pxor <a3=%xmm5,<diag0=%xmm0
+pxor %xmm5,%xmm0
+
+# qhasm: diag1 <<<= 96
+# asm 1: pshufd $0x39,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x39,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: diag0 ^= b3
+# asm 1: pxor <b3=int6464#7,<diag0=int6464#1
+# asm 2: pxor <b3=%xmm6,<diag0=%xmm0
+pxor %xmm6,%xmm0
+
+# qhasm: uint32323232 a4 += diag0
+# asm 1: paddd <diag0=int6464#1,<a4=int6464#5
+# asm 2: paddd <diag0=%xmm0,<a4=%xmm4
+paddd %xmm0,%xmm4
+
+# qhasm: a5 = diag0
+# asm 1: movdqa <diag0=int6464#1,>a5=int6464#6
+# asm 2: movdqa <diag0=%xmm0,>a5=%xmm5
+movdqa %xmm0,%xmm5
+
+# qhasm: b4 = a4
+# asm 1: movdqa <a4=int6464#5,>b4=int6464#7
+# asm 2: movdqa <a4=%xmm4,>b4=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a4 <<= 7
+# asm 1: pslld $7,<a4=int6464#5
+# asm 2: pslld $7,<a4=%xmm4
+pslld $7,%xmm4
+
+# qhasm: uint32323232 b4 >>= 25
+# asm 1: psrld $25,<b4=int6464#7
+# asm 2: psrld $25,<b4=%xmm6
+psrld $25,%xmm6
+
+# qhasm: diag1 ^= a4
+# asm 1: pxor <a4=int6464#5,<diag1=int6464#2
+# asm 2: pxor <a4=%xmm4,<diag1=%xmm1
+pxor %xmm4,%xmm1
+
+# qhasm: diag1 ^= b4
+# asm 1: pxor <b4=int6464#7,<diag1=int6464#2
+# asm 2: pxor <b4=%xmm6,<diag1=%xmm1
+pxor %xmm6,%xmm1
+
+# qhasm: uint32323232 a5 += diag1
+# asm 1: paddd <diag1=int6464#2,<a5=int6464#6
+# asm 2: paddd <diag1=%xmm1,<a5=%xmm5
+paddd %xmm1,%xmm5
+
+# qhasm: a6 = diag1
+# asm 1: movdqa <diag1=int6464#2,>a6=int6464#5
+# asm 2: movdqa <diag1=%xmm1,>a6=%xmm4
+movdqa %xmm1,%xmm4
+
+# qhasm: b5 = a5
+# asm 1: movdqa <a5=int6464#6,>b5=int6464#7
+# asm 2: movdqa <a5=%xmm5,>b5=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a5 <<= 9
+# asm 1: pslld $9,<a5=int6464#6
+# asm 2: pslld $9,<a5=%xmm5
+pslld $9,%xmm5
+
+# qhasm: uint32323232 b5 >>= 23
+# asm 1: psrld $23,<b5=int6464#7
+# asm 2: psrld $23,<b5=%xmm6
+psrld $23,%xmm6
+
+# qhasm: diag2 ^= a5
+# asm 1: pxor <a5=int6464#6,<diag2=int6464#3
+# asm 2: pxor <a5=%xmm5,<diag2=%xmm2
+pxor %xmm5,%xmm2
+
+# qhasm: diag1 <<<= 32
+# asm 1: pshufd $0x93,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x93,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x93,%xmm1,%xmm1
+
+# qhasm: diag2 ^= b5
+# asm 1: pxor <b5=int6464#7,<diag2=int6464#3
+# asm 2: pxor <b5=%xmm6,<diag2=%xmm2
+pxor %xmm6,%xmm2
+
+# qhasm: uint32323232 a6 += diag2
+# asm 1: paddd <diag2=int6464#3,<a6=int6464#5
+# asm 2: paddd <diag2=%xmm2,<a6=%xmm4
+paddd %xmm2,%xmm4
+
+# qhasm: a7 = diag2
+# asm 1: movdqa <diag2=int6464#3,>a7=int6464#6
+# asm 2: movdqa <diag2=%xmm2,>a7=%xmm5
+movdqa %xmm2,%xmm5
+
+# qhasm: b6 = a6
+# asm 1: movdqa <a6=int6464#5,>b6=int6464#7
+# asm 2: movdqa <a6=%xmm4,>b6=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a6 <<= 13
+# asm 1: pslld $13,<a6=int6464#5
+# asm 2: pslld $13,<a6=%xmm4
+pslld $13,%xmm4
+
+# qhasm: uint32323232 b6 >>= 19
+# asm 1: psrld $19,<b6=int6464#7
+# asm 2: psrld $19,<b6=%xmm6
+psrld $19,%xmm6
+
+# qhasm: diag3 ^= a6
+# asm 1: pxor <a6=int6464#5,<diag3=int6464#4
+# asm 2: pxor <a6=%xmm4,<diag3=%xmm3
+pxor %xmm4,%xmm3
+
+# qhasm: diag2 <<<= 64
+# asm 1: pshufd $0x4e,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x4e,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x4e,%xmm2,%xmm2
+
+# qhasm: diag3 ^= b6
+# asm 1: pxor <b6=int6464#7,<diag3=int6464#4
+# asm 2: pxor <b6=%xmm6,<diag3=%xmm3
+pxor %xmm6,%xmm3
+
+# qhasm: uint32323232 a7 += diag3
+# asm 1: paddd <diag3=int6464#4,<a7=int6464#6
+# asm 2: paddd <diag3=%xmm3,<a7=%xmm5
+paddd %xmm3,%xmm5
+
+# qhasm: a0 = diag1
+# asm 1: movdqa <diag1=int6464#2,>a0=int6464#5
+# asm 2: movdqa <diag1=%xmm1,>a0=%xmm4
+movdqa %xmm1,%xmm4
+
+# qhasm: b7 = a7
+# asm 1: movdqa <a7=int6464#6,>b7=int6464#7
+# asm 2: movdqa <a7=%xmm5,>b7=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a7 <<= 18
+# asm 1: pslld $18,<a7=int6464#6
+# asm 2: pslld $18,<a7=%xmm5
+pslld $18,%xmm5
+
+# qhasm: uint32323232 b7 >>= 14
+# asm 1: psrld $14,<b7=int6464#7
+# asm 2: psrld $14,<b7=%xmm6
+psrld $14,%xmm6
+
+# qhasm: diag0 ^= a7
+# asm 1: pxor <a7=int6464#6,<diag0=int6464#1
+# asm 2: pxor <a7=%xmm5,<diag0=%xmm0
+pxor %xmm5,%xmm0
+
+# qhasm: diag3 <<<= 96
+# asm 1: pshufd $0x39,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x39,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: diag0 ^= b7
+# asm 1: pxor <b7=int6464#7,<diag0=int6464#1
+# asm 2: pxor <b7=%xmm6,<diag0=%xmm0
+pxor %xmm6,%xmm0
+
+# qhasm: uint32323232 a0 += diag0
+# asm 1: paddd <diag0=int6464#1,<a0=int6464#5
+# asm 2: paddd <diag0=%xmm0,<a0=%xmm4
+paddd %xmm0,%xmm4
+
+# qhasm: a1 = diag0
+# asm 1: movdqa <diag0=int6464#1,>a1=int6464#6
+# asm 2: movdqa <diag0=%xmm0,>a1=%xmm5
+movdqa %xmm0,%xmm5
+
+# qhasm: b0 = a0
+# asm 1: movdqa <a0=int6464#5,>b0=int6464#7
+# asm 2: movdqa <a0=%xmm4,>b0=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a0 <<= 7
+# asm 1: pslld $7,<a0=int6464#5
+# asm 2: pslld $7,<a0=%xmm4
+pslld $7,%xmm4
+
+# qhasm: uint32323232 b0 >>= 25
+# asm 1: psrld $25,<b0=int6464#7
+# asm 2: psrld $25,<b0=%xmm6
+psrld $25,%xmm6
+
+# qhasm: diag3 ^= a0
+# asm 1: pxor <a0=int6464#5,<diag3=int6464#4
+# asm 2: pxor <a0=%xmm4,<diag3=%xmm3
+pxor %xmm4,%xmm3
+
+# qhasm: diag3 ^= b0
+# asm 1: pxor <b0=int6464#7,<diag3=int6464#4
+# asm 2: pxor <b0=%xmm6,<diag3=%xmm3
+pxor %xmm6,%xmm3
+
+# qhasm: uint32323232 a1 += diag3
+# asm 1: paddd <diag3=int6464#4,<a1=int6464#6
+# asm 2: paddd <diag3=%xmm3,<a1=%xmm5
+paddd %xmm3,%xmm5
+
+# qhasm: a2 = diag3
+# asm 1: movdqa <diag3=int6464#4,>a2=int6464#5
+# asm 2: movdqa <diag3=%xmm3,>a2=%xmm4
+movdqa %xmm3,%xmm4
+
+# qhasm: b1 = a1
+# asm 1: movdqa <a1=int6464#6,>b1=int6464#7
+# asm 2: movdqa <a1=%xmm5,>b1=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a1 <<= 9
+# asm 1: pslld $9,<a1=int6464#6
+# asm 2: pslld $9,<a1=%xmm5
+pslld $9,%xmm5
+
+# qhasm: uint32323232 b1 >>= 23
+# asm 1: psrld $23,<b1=int6464#7
+# asm 2: psrld $23,<b1=%xmm6
+psrld $23,%xmm6
+
+# qhasm: diag2 ^= a1
+# asm 1: pxor <a1=int6464#6,<diag2=int6464#3
+# asm 2: pxor <a1=%xmm5,<diag2=%xmm2
+pxor %xmm5,%xmm2
+
+# qhasm: diag3 <<<= 32
+# asm 1: pshufd $0x93,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x93,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x93,%xmm3,%xmm3
+
+# qhasm: diag2 ^= b1
+# asm 1: pxor <b1=int6464#7,<diag2=int6464#3
+# asm 2: pxor <b1=%xmm6,<diag2=%xmm2
+pxor %xmm6,%xmm2
+
+# qhasm: uint32323232 a2 += diag2
+# asm 1: paddd <diag2=int6464#3,<a2=int6464#5
+# asm 2: paddd <diag2=%xmm2,<a2=%xmm4
+paddd %xmm2,%xmm4
+
+# qhasm: a3 = diag2
+# asm 1: movdqa <diag2=int6464#3,>a3=int6464#6
+# asm 2: movdqa <diag2=%xmm2,>a3=%xmm5
+movdqa %xmm2,%xmm5
+
+# qhasm: b2 = a2
+# asm 1: movdqa <a2=int6464#5,>b2=int6464#7
+# asm 2: movdqa <a2=%xmm4,>b2=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a2 <<= 13
+# asm 1: pslld $13,<a2=int6464#5
+# asm 2: pslld $13,<a2=%xmm4
+pslld $13,%xmm4
+
+# qhasm: uint32323232 b2 >>= 19
+# asm 1: psrld $19,<b2=int6464#7
+# asm 2: psrld $19,<b2=%xmm6
+psrld $19,%xmm6
+
+# qhasm: diag1 ^= a2
+# asm 1: pxor <a2=int6464#5,<diag1=int6464#2
+# asm 2: pxor <a2=%xmm4,<diag1=%xmm1
+pxor %xmm4,%xmm1
+
+# qhasm: diag2 <<<= 64
+# asm 1: pshufd $0x4e,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x4e,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x4e,%xmm2,%xmm2
+
+# qhasm: diag1 ^= b2
+# asm 1: pxor <b2=int6464#7,<diag1=int6464#2
+# asm 2: pxor <b2=%xmm6,<diag1=%xmm1
+pxor %xmm6,%xmm1
+
+# qhasm: uint32323232 a3 += diag1
+# asm 1: paddd <diag1=int6464#2,<a3=int6464#6
+# asm 2: paddd <diag1=%xmm1,<a3=%xmm5
+paddd %xmm1,%xmm5
+
+# qhasm: a4 = diag3
+# asm 1: movdqa <diag3=int6464#4,>a4=int6464#5
+# asm 2: movdqa <diag3=%xmm3,>a4=%xmm4
+movdqa %xmm3,%xmm4
+
+# qhasm: b3 = a3
+# asm 1: movdqa <a3=int6464#6,>b3=int6464#7
+# asm 2: movdqa <a3=%xmm5,>b3=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a3 <<= 18
+# asm 1: pslld $18,<a3=int6464#6
+# asm 2: pslld $18,<a3=%xmm5
+pslld $18,%xmm5
+
+# qhasm: uint32323232 b3 >>= 14
+# asm 1: psrld $14,<b3=int6464#7
+# asm 2: psrld $14,<b3=%xmm6
+psrld $14,%xmm6
+
+# qhasm: diag0 ^= a3
+# asm 1: pxor <a3=int6464#6,<diag0=int6464#1
+# asm 2: pxor <a3=%xmm5,<diag0=%xmm0
+pxor %xmm5,%xmm0
+
+# qhasm: diag1 <<<= 96
+# asm 1: pshufd $0x39,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x39,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: diag0 ^= b3
+# asm 1: pxor <b3=int6464#7,<diag0=int6464#1
+# asm 2: pxor <b3=%xmm6,<diag0=%xmm0
+pxor %xmm6,%xmm0
+
+# qhasm: uint32323232 a4 += diag0
+# asm 1: paddd <diag0=int6464#1,<a4=int6464#5
+# asm 2: paddd <diag0=%xmm0,<a4=%xmm4
+paddd %xmm0,%xmm4
+
+# qhasm: a5 = diag0
+# asm 1: movdqa <diag0=int6464#1,>a5=int6464#6
+# asm 2: movdqa <diag0=%xmm0,>a5=%xmm5
+movdqa %xmm0,%xmm5
+
+# qhasm: b4 = a4
+# asm 1: movdqa <a4=int6464#5,>b4=int6464#7
+# asm 2: movdqa <a4=%xmm4,>b4=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a4 <<= 7
+# asm 1: pslld $7,<a4=int6464#5
+# asm 2: pslld $7,<a4=%xmm4
+pslld $7,%xmm4
+
+# qhasm: uint32323232 b4 >>= 25
+# asm 1: psrld $25,<b4=int6464#7
+# asm 2: psrld $25,<b4=%xmm6
+psrld $25,%xmm6
+
+# qhasm: diag1 ^= a4
+# asm 1: pxor <a4=int6464#5,<diag1=int6464#2
+# asm 2: pxor <a4=%xmm4,<diag1=%xmm1
+pxor %xmm4,%xmm1
+
+# qhasm: diag1 ^= b4
+# asm 1: pxor <b4=int6464#7,<diag1=int6464#2
+# asm 2: pxor <b4=%xmm6,<diag1=%xmm1
+pxor %xmm6,%xmm1
+
+# qhasm: uint32323232 a5 += diag1
+# asm 1: paddd <diag1=int6464#2,<a5=int6464#6
+# asm 2: paddd <diag1=%xmm1,<a5=%xmm5
+paddd %xmm1,%xmm5
+
+# qhasm: a6 = diag1
+# asm 1: movdqa <diag1=int6464#2,>a6=int6464#5
+# asm 2: movdqa <diag1=%xmm1,>a6=%xmm4
+movdqa %xmm1,%xmm4
+
+# qhasm: b5 = a5
+# asm 1: movdqa <a5=int6464#6,>b5=int6464#7
+# asm 2: movdqa <a5=%xmm5,>b5=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a5 <<= 9
+# asm 1: pslld $9,<a5=int6464#6
+# asm 2: pslld $9,<a5=%xmm5
+pslld $9,%xmm5
+
+# qhasm: uint32323232 b5 >>= 23
+# asm 1: psrld $23,<b5=int6464#7
+# asm 2: psrld $23,<b5=%xmm6
+psrld $23,%xmm6
+
+# qhasm: diag2 ^= a5
+# asm 1: pxor <a5=int6464#6,<diag2=int6464#3
+# asm 2: pxor <a5=%xmm5,<diag2=%xmm2
+pxor %xmm5,%xmm2
+
+# qhasm: diag1 <<<= 32
+# asm 1: pshufd $0x93,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x93,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x93,%xmm1,%xmm1
+
+# qhasm: diag2 ^= b5
+# asm 1: pxor <b5=int6464#7,<diag2=int6464#3
+# asm 2: pxor <b5=%xmm6,<diag2=%xmm2
+pxor %xmm6,%xmm2
+
+# qhasm: uint32323232 a6 += diag2
+# asm 1: paddd <diag2=int6464#3,<a6=int6464#5
+# asm 2: paddd <diag2=%xmm2,<a6=%xmm4
+paddd %xmm2,%xmm4
+
+# qhasm: a7 = diag2
+# asm 1: movdqa <diag2=int6464#3,>a7=int6464#6
+# asm 2: movdqa <diag2=%xmm2,>a7=%xmm5
+movdqa %xmm2,%xmm5
+
+# qhasm: b6 = a6
+# asm 1: movdqa <a6=int6464#5,>b6=int6464#7
+# asm 2: movdqa <a6=%xmm4,>b6=%xmm6
+movdqa %xmm4,%xmm6
+
+# qhasm: uint32323232 a6 <<= 13
+# asm 1: pslld $13,<a6=int6464#5
+# asm 2: pslld $13,<a6=%xmm4
+pslld $13,%xmm4
+
+# qhasm: uint32323232 b6 >>= 19
+# asm 1: psrld $19,<b6=int6464#7
+# asm 2: psrld $19,<b6=%xmm6
+psrld $19,%xmm6
+
+# qhasm: diag3 ^= a6
+# asm 1: pxor <a6=int6464#5,<diag3=int6464#4
+# asm 2: pxor <a6=%xmm4,<diag3=%xmm3
+pxor %xmm4,%xmm3
+
+# qhasm: diag2 <<<= 64
+# asm 1: pshufd $0x4e,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x4e,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x4e,%xmm2,%xmm2
+
+# qhasm: diag3 ^= b6
+# asm 1: pxor <b6=int6464#7,<diag3=int6464#4
+# asm 2: pxor <b6=%xmm6,<diag3=%xmm3
+pxor %xmm6,%xmm3
+
+# qhasm: unsigned>? i -= 4
+# asm 1: sub $4,<i=int64#4
+# asm 2: sub $4,<i=%rcx
+sub $4,%rcx
+
+# qhasm: uint32323232 a7 += diag3
+# asm 1: paddd <diag3=int6464#4,<a7=int6464#6
+# asm 2: paddd <diag3=%xmm3,<a7=%xmm5
+paddd %xmm3,%xmm5
+
+# qhasm: a0 = diag1
+# asm 1: movdqa <diag1=int6464#2,>a0=int6464#5
+# asm 2: movdqa <diag1=%xmm1,>a0=%xmm4
+movdqa %xmm1,%xmm4
+
+# qhasm: b7 = a7
+# asm 1: movdqa <a7=int6464#6,>b7=int6464#7
+# asm 2: movdqa <a7=%xmm5,>b7=%xmm6
+movdqa %xmm5,%xmm6
+
+# qhasm: uint32323232 a7 <<= 18
+# asm 1: pslld $18,<a7=int6464#6
+# asm 2: pslld $18,<a7=%xmm5
+pslld $18,%xmm5
+
+# qhasm: b0 = 0
+# asm 1: pxor >b0=int6464#8,>b0=int6464#8
+# asm 2: pxor >b0=%xmm7,>b0=%xmm7
+pxor %xmm7,%xmm7
+
+# qhasm: uint32323232 b7 >>= 14
+# asm 1: psrld $14,<b7=int6464#7
+# asm 2: psrld $14,<b7=%xmm6
+psrld $14,%xmm6
+
+# qhasm: diag0 ^= a7
+# asm 1: pxor <a7=int6464#6,<diag0=int6464#1
+# asm 2: pxor <a7=%xmm5,<diag0=%xmm0
+pxor %xmm5,%xmm0
+
+# qhasm: diag3 <<<= 96
+# asm 1: pshufd $0x39,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x39,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: diag0 ^= b7
+# asm 1: pxor <b7=int6464#7,<diag0=int6464#1
+# asm 2: pxor <b7=%xmm6,<diag0=%xmm0
+pxor %xmm6,%xmm0
+# comment:fp stack unchanged by jump
+
+# qhasm: goto mainloop2 if unsigned>
+ja ._mainloop2
+
+# qhasm: uint32323232 diag0 += x0
+# asm 1: paddd <x0=stack128#4,<diag0=int6464#1
+# asm 2: paddd <x0=48(%rsp),<diag0=%xmm0
+paddd 48(%rsp),%xmm0
+
+# qhasm: uint32323232 diag1 += x1
+# asm 1: paddd <x1=stack128#1,<diag1=int6464#2
+# asm 2: paddd <x1=0(%rsp),<diag1=%xmm1
+paddd 0(%rsp),%xmm1
+
+# qhasm: uint32323232 diag2 += x2
+# asm 1: paddd <x2=stack128#2,<diag2=int6464#3
+# asm 2: paddd <x2=16(%rsp),<diag2=%xmm2
+paddd 16(%rsp),%xmm2
+
+# qhasm: uint32323232 diag3 += x3
+# asm 1: paddd <x3=stack128#3,<diag3=int6464#4
+# asm 2: paddd <x3=32(%rsp),<diag3=%xmm3
+paddd 32(%rsp),%xmm3
+
+# qhasm: in0 = diag0
+# asm 1: movd <diag0=int6464#1,>in0=int64#4
+# asm 2: movd <diag0=%xmm0,>in0=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in12 = diag1
+# asm 1: movd <diag1=int6464#2,>in12=int64#5
+# asm 2: movd <diag1=%xmm1,>in12=%r8
+movd %xmm1,%r8
+
+# qhasm: in8 = diag2
+# asm 1: movd <diag2=int6464#3,>in8=int64#6
+# asm 2: movd <diag2=%xmm2,>in8=%r9
+movd %xmm2,%r9
+
+# qhasm: in4 = diag3
+# asm 1: movd <diag3=int6464#4,>in4=int64#7
+# asm 2: movd <diag3=%xmm3,>in4=%rax
+movd %xmm3,%rax
+
+# qhasm: diag0 <<<= 96
+# asm 1: pshufd $0x39,<diag0=int6464#1,<diag0=int6464#1
+# asm 2: pshufd $0x39,<diag0=%xmm0,<diag0=%xmm0
+pshufd $0x39,%xmm0,%xmm0
+
+# qhasm: diag1 <<<= 96
+# asm 1: pshufd $0x39,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x39,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: diag2 <<<= 96
+# asm 1: pshufd $0x39,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x39,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x39,%xmm2,%xmm2
+
+# qhasm: diag3 <<<= 96
+# asm 1: pshufd $0x39,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x39,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: (uint32) in0 ^= *(uint32 *) (m + 0)
+# asm 1: xorl 0(<m=int64#2),<in0=int64#4d
+# asm 2: xorl 0(<m=%rsi),<in0=%ecx
+xorl 0(%rsi),%ecx
+
+# qhasm: (uint32) in12 ^= *(uint32 *) (m + 48)
+# asm 1: xorl 48(<m=int64#2),<in12=int64#5d
+# asm 2: xorl 48(<m=%rsi),<in12=%r8d
+xorl 48(%rsi),%r8d
+
+# qhasm: (uint32) in8 ^= *(uint32 *) (m + 32)
+# asm 1: xorl 32(<m=int64#2),<in8=int64#6d
+# asm 2: xorl 32(<m=%rsi),<in8=%r9d
+xorl 32(%rsi),%r9d
+
+# qhasm: (uint32) in4 ^= *(uint32 *) (m + 16)
+# asm 1: xorl 16(<m=int64#2),<in4=int64#7d
+# asm 2: xorl 16(<m=%rsi),<in4=%eax
+xorl 16(%rsi),%eax
+
+# qhasm: *(uint32 *) (out + 0) = in0
+# asm 1: movl <in0=int64#4d,0(<out=int64#1)
+# asm 2: movl <in0=%ecx,0(<out=%rdi)
+movl %ecx,0(%rdi)
+
+# qhasm: *(uint32 *) (out + 48) = in12
+# asm 1: movl <in12=int64#5d,48(<out=int64#1)
+# asm 2: movl <in12=%r8d,48(<out=%rdi)
+movl %r8d,48(%rdi)
+
+# qhasm: *(uint32 *) (out + 32) = in8
+# asm 1: movl <in8=int64#6d,32(<out=int64#1)
+# asm 2: movl <in8=%r9d,32(<out=%rdi)
+movl %r9d,32(%rdi)
+
+# qhasm: *(uint32 *) (out + 16) = in4
+# asm 1: movl <in4=int64#7d,16(<out=int64#1)
+# asm 2: movl <in4=%eax,16(<out=%rdi)
+movl %eax,16(%rdi)
+
+# qhasm: in5 = diag0
+# asm 1: movd <diag0=int6464#1,>in5=int64#4
+# asm 2: movd <diag0=%xmm0,>in5=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in1 = diag1
+# asm 1: movd <diag1=int6464#2,>in1=int64#5
+# asm 2: movd <diag1=%xmm1,>in1=%r8
+movd %xmm1,%r8
+
+# qhasm: in13 = diag2
+# asm 1: movd <diag2=int6464#3,>in13=int64#6
+# asm 2: movd <diag2=%xmm2,>in13=%r9
+movd %xmm2,%r9
+
+# qhasm: in9 = diag3
+# asm 1: movd <diag3=int6464#4,>in9=int64#7
+# asm 2: movd <diag3=%xmm3,>in9=%rax
+movd %xmm3,%rax
+
+# qhasm: diag0 <<<= 96
+# asm 1: pshufd $0x39,<diag0=int6464#1,<diag0=int6464#1
+# asm 2: pshufd $0x39,<diag0=%xmm0,<diag0=%xmm0
+pshufd $0x39,%xmm0,%xmm0
+
+# qhasm: diag1 <<<= 96
+# asm 1: pshufd $0x39,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x39,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: diag2 <<<= 96
+# asm 1: pshufd $0x39,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x39,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x39,%xmm2,%xmm2
+
+# qhasm: diag3 <<<= 96
+# asm 1: pshufd $0x39,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x39,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: (uint32) in5 ^= *(uint32 *) (m + 20)
+# asm 1: xorl 20(<m=int64#2),<in5=int64#4d
+# asm 2: xorl 20(<m=%rsi),<in5=%ecx
+xorl 20(%rsi),%ecx
+
+# qhasm: (uint32) in1 ^= *(uint32 *) (m + 4)
+# asm 1: xorl 4(<m=int64#2),<in1=int64#5d
+# asm 2: xorl 4(<m=%rsi),<in1=%r8d
+xorl 4(%rsi),%r8d
+
+# qhasm: (uint32) in13 ^= *(uint32 *) (m + 52)
+# asm 1: xorl 52(<m=int64#2),<in13=int64#6d
+# asm 2: xorl 52(<m=%rsi),<in13=%r9d
+xorl 52(%rsi),%r9d
+
+# qhasm: (uint32) in9 ^= *(uint32 *) (m + 36)
+# asm 1: xorl 36(<m=int64#2),<in9=int64#7d
+# asm 2: xorl 36(<m=%rsi),<in9=%eax
+xorl 36(%rsi),%eax
+
+# qhasm: *(uint32 *) (out + 20) = in5
+# asm 1: movl <in5=int64#4d,20(<out=int64#1)
+# asm 2: movl <in5=%ecx,20(<out=%rdi)
+movl %ecx,20(%rdi)
+
+# qhasm: *(uint32 *) (out + 4) = in1
+# asm 1: movl <in1=int64#5d,4(<out=int64#1)
+# asm 2: movl <in1=%r8d,4(<out=%rdi)
+movl %r8d,4(%rdi)
+
+# qhasm: *(uint32 *) (out + 52) = in13
+# asm 1: movl <in13=int64#6d,52(<out=int64#1)
+# asm 2: movl <in13=%r9d,52(<out=%rdi)
+movl %r9d,52(%rdi)
+
+# qhasm: *(uint32 *) (out + 36) = in9
+# asm 1: movl <in9=int64#7d,36(<out=int64#1)
+# asm 2: movl <in9=%eax,36(<out=%rdi)
+movl %eax,36(%rdi)
+
+# qhasm: in10 = diag0
+# asm 1: movd <diag0=int6464#1,>in10=int64#4
+# asm 2: movd <diag0=%xmm0,>in10=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in6 = diag1
+# asm 1: movd <diag1=int6464#2,>in6=int64#5
+# asm 2: movd <diag1=%xmm1,>in6=%r8
+movd %xmm1,%r8
+
+# qhasm: in2 = diag2
+# asm 1: movd <diag2=int6464#3,>in2=int64#6
+# asm 2: movd <diag2=%xmm2,>in2=%r9
+movd %xmm2,%r9
+
+# qhasm: in14 = diag3
+# asm 1: movd <diag3=int6464#4,>in14=int64#7
+# asm 2: movd <diag3=%xmm3,>in14=%rax
+movd %xmm3,%rax
+
+# qhasm: diag0 <<<= 96
+# asm 1: pshufd $0x39,<diag0=int6464#1,<diag0=int6464#1
+# asm 2: pshufd $0x39,<diag0=%xmm0,<diag0=%xmm0
+pshufd $0x39,%xmm0,%xmm0
+
+# qhasm: diag1 <<<= 96
+# asm 1: pshufd $0x39,<diag1=int6464#2,<diag1=int6464#2
+# asm 2: pshufd $0x39,<diag1=%xmm1,<diag1=%xmm1
+pshufd $0x39,%xmm1,%xmm1
+
+# qhasm: diag2 <<<= 96
+# asm 1: pshufd $0x39,<diag2=int6464#3,<diag2=int6464#3
+# asm 2: pshufd $0x39,<diag2=%xmm2,<diag2=%xmm2
+pshufd $0x39,%xmm2,%xmm2
+
+# qhasm: diag3 <<<= 96
+# asm 1: pshufd $0x39,<diag3=int6464#4,<diag3=int6464#4
+# asm 2: pshufd $0x39,<diag3=%xmm3,<diag3=%xmm3
+pshufd $0x39,%xmm3,%xmm3
+
+# qhasm: (uint32) in10 ^= *(uint32 *) (m + 40)
+# asm 1: xorl 40(<m=int64#2),<in10=int64#4d
+# asm 2: xorl 40(<m=%rsi),<in10=%ecx
+xorl 40(%rsi),%ecx
+
+# qhasm: (uint32) in6 ^= *(uint32 *) (m + 24)
+# asm 1: xorl 24(<m=int64#2),<in6=int64#5d
+# asm 2: xorl 24(<m=%rsi),<in6=%r8d
+xorl 24(%rsi),%r8d
+
+# qhasm: (uint32) in2 ^= *(uint32 *) (m + 8)
+# asm 1: xorl 8(<m=int64#2),<in2=int64#6d
+# asm 2: xorl 8(<m=%rsi),<in2=%r9d
+xorl 8(%rsi),%r9d
+
+# qhasm: (uint32) in14 ^= *(uint32 *) (m + 56)
+# asm 1: xorl 56(<m=int64#2),<in14=int64#7d
+# asm 2: xorl 56(<m=%rsi),<in14=%eax
+xorl 56(%rsi),%eax
+
+# qhasm: *(uint32 *) (out + 40) = in10
+# asm 1: movl <in10=int64#4d,40(<out=int64#1)
+# asm 2: movl <in10=%ecx,40(<out=%rdi)
+movl %ecx,40(%rdi)
+
+# qhasm: *(uint32 *) (out + 24) = in6
+# asm 1: movl <in6=int64#5d,24(<out=int64#1)
+# asm 2: movl <in6=%r8d,24(<out=%rdi)
+movl %r8d,24(%rdi)
+
+# qhasm: *(uint32 *) (out + 8) = in2
+# asm 1: movl <in2=int64#6d,8(<out=int64#1)
+# asm 2: movl <in2=%r9d,8(<out=%rdi)
+movl %r9d,8(%rdi)
+
+# qhasm: *(uint32 *) (out + 56) = in14
+# asm 1: movl <in14=int64#7d,56(<out=int64#1)
+# asm 2: movl <in14=%eax,56(<out=%rdi)
+movl %eax,56(%rdi)
+
+# qhasm: in15 = diag0
+# asm 1: movd <diag0=int6464#1,>in15=int64#4
+# asm 2: movd <diag0=%xmm0,>in15=%rcx
+movd %xmm0,%rcx
+
+# qhasm: in11 = diag1
+# asm 1: movd <diag1=int6464#2,>in11=int64#5
+# asm 2: movd <diag1=%xmm1,>in11=%r8
+movd %xmm1,%r8
+
+# qhasm: in7 = diag2
+# asm 1: movd <diag2=int6464#3,>in7=int64#6
+# asm 2: movd <diag2=%xmm2,>in7=%r9
+movd %xmm2,%r9
+
+# qhasm: in3 = diag3
+# asm 1: movd <diag3=int6464#4,>in3=int64#7
+# asm 2: movd <diag3=%xmm3,>in3=%rax
+movd %xmm3,%rax
+
+# qhasm: (uint32) in15 ^= *(uint32 *) (m + 60)
+# asm 1: xorl 60(<m=int64#2),<in15=int64#4d
+# asm 2: xorl 60(<m=%rsi),<in15=%ecx
+xorl 60(%rsi),%ecx
+
+# qhasm: (uint32) in11 ^= *(uint32 *) (m + 44)
+# asm 1: xorl 44(<m=int64#2),<in11=int64#5d
+# asm 2: xorl 44(<m=%rsi),<in11=%r8d
+xorl 44(%rsi),%r8d
+
+# qhasm: (uint32) in7 ^= *(uint32 *) (m + 28)
+# asm 1: xorl 28(<m=int64#2),<in7=int64#6d
+# asm 2: xorl 28(<m=%rsi),<in7=%r9d
+xorl 28(%rsi),%r9d
+
+# qhasm: (uint32) in3 ^= *(uint32 *) (m + 12)
+# asm 1: xorl 12(<m=int64#2),<in3=int64#7d
+# asm 2: xorl 12(<m=%rsi),<in3=%eax
+xorl 12(%rsi),%eax
+
+# qhasm: *(uint32 *) (out + 60) = in15
+# asm 1: movl <in15=int64#4d,60(<out=int64#1)
+# asm 2: movl <in15=%ecx,60(<out=%rdi)
+movl %ecx,60(%rdi)
+
+# qhasm: *(uint32 *) (out + 44) = in11
+# asm 1: movl <in11=int64#5d,44(<out=int64#1)
+# asm 2: movl <in11=%r8d,44(<out=%rdi)
+movl %r8d,44(%rdi)
+
+# qhasm: *(uint32 *) (out + 28) = in7
+# asm 1: movl <in7=int64#6d,28(<out=int64#1)
+# asm 2: movl <in7=%r9d,28(<out=%rdi)
+movl %r9d,28(%rdi)
+
+# qhasm: *(uint32 *) (out + 12) = in3
+# asm 1: movl <in3=int64#7d,12(<out=int64#1)
+# asm 2: movl <in3=%eax,12(<out=%rdi)
+movl %eax,12(%rdi)
+
+# qhasm: bytes = bytes_backup
+# asm 1: movq <bytes_backup=stack64#8,>bytes=int64#6
+# asm 2: movq <bytes_backup=408(%rsp),>bytes=%r9
+movq 408(%rsp),%r9
+
+# qhasm: in8 = ((uint32 *)&x2)[0]
+# asm 1: movl <x2=stack128#2,>in8=int64#4d
+# asm 2: movl <x2=16(%rsp),>in8=%ecx
+movl 16(%rsp),%ecx
+
+# qhasm: in9 = ((uint32 *)&x3)[1]
+# asm 1: movl 4+<x3=stack128#3,>in9=int64#5d
+# asm 2: movl 4+<x3=32(%rsp),>in9=%r8d
+movl 4+32(%rsp),%r8d
+
+# qhasm: in8 += 1
+# asm 1: add $1,<in8=int64#4
+# asm 2: add $1,<in8=%rcx
+add $1,%rcx
+
+# qhasm: in9 <<= 32
+# asm 1: shl $32,<in9=int64#5
+# asm 2: shl $32,<in9=%r8
+shl $32,%r8
+
+# qhasm: in8 += in9
+# asm 1: add <in9=int64#5,<in8=int64#4
+# asm 2: add <in9=%r8,<in8=%rcx
+add %r8,%rcx
+
+# qhasm: in9 = in8
+# asm 1: mov <in8=int64#4,>in9=int64#5
+# asm 2: mov <in8=%rcx,>in9=%r8
+mov %rcx,%r8
+
+# qhasm: (uint64) in9 >>= 32
+# asm 1: shr $32,<in9=int64#5
+# asm 2: shr $32,<in9=%r8
+shr $32,%r8
+
+# qhasm: ((uint32 *)&x2)[0] = in8
+# asm 1: movl <in8=int64#4d,>x2=stack128#2
+# asm 2: movl <in8=%ecx,>x2=16(%rsp)
+movl %ecx,16(%rsp)
+
+# qhasm: ((uint32 *)&x3)[1] = in9
+# asm 1: movl <in9=int64#5d,4+<x3=stack128#3
+# asm 2: movl <in9=%r8d,4+<x3=32(%rsp)
+movl %r8d,4+32(%rsp)
+
+# qhasm: unsigned>? unsigned<? bytes - 64
+# asm 1: cmp $64,<bytes=int64#6
+# asm 2: cmp $64,<bytes=%r9
+cmp $64,%r9
+# comment:fp stack unchanged by jump
+
+# qhasm: goto bytesatleast65 if unsigned>
+ja ._bytesatleast65
+# comment:fp stack unchanged by jump
+
+# qhasm: goto bytesatleast64 if !unsigned<
+jae ._bytesatleast64
+
+# qhasm: m = out
+# asm 1: mov <out=int64#1,>m=int64#2
+# asm 2: mov <out=%rdi,>m=%rsi
+mov %rdi,%rsi
+
+# qhasm: out = ctarget
+# asm 1: mov <ctarget=int64#3,>out=int64#1
+# asm 2: mov <ctarget=%rdx,>out=%rdi
+mov %rdx,%rdi
+
+# qhasm: i = bytes
+# asm 1: mov <bytes=int64#6,>i=int64#4
+# asm 2: mov <bytes=%r9,>i=%rcx
+mov %r9,%rcx
+
+# qhasm: while (i) { *out++ = *m++; --i }
+rep movsb
+# comment:fp stack unchanged by fallthrough
+
+# qhasm: bytesatleast64:
+._bytesatleast64:
+# comment:fp stack unchanged by fallthrough
+
+# qhasm: done:
+._done:
+
+# qhasm: r11_caller = r11_stack
+# asm 1: movq <r11_stack=stack64#1,>r11_caller=int64#9
+# asm 2: movq <r11_stack=352(%rsp),>r11_caller=%r11
+movq 352(%rsp),%r11
+
+# qhasm: r12_caller = r12_stack
+# asm 1: movq <r12_stack=stack64#2,>r12_caller=int64#10
+# asm 2: movq <r12_stack=360(%rsp),>r12_caller=%r12
+movq 360(%rsp),%r12
+
+# qhasm: r13_caller = r13_stack
+# asm 1: movq <r13_stack=stack64#3,>r13_caller=int64#11
+# asm 2: movq <r13_stack=368(%rsp),>r13_caller=%r13
+movq 368(%rsp),%r13
+
+# qhasm: r14_caller = r14_stack
+# asm 1: movq <r14_stack=stack64#4,>r14_caller=int64#12
+# asm 2: movq <r14_stack=376(%rsp),>r14_caller=%r14
+movq 376(%rsp),%r14
+
+# qhasm: r15_caller = r15_stack
+# asm 1: movq <r15_stack=stack64#5,>r15_caller=int64#13
+# asm 2: movq <r15_stack=384(%rsp),>r15_caller=%r15
+movq 384(%rsp),%r15
+
+# qhasm: rbx_caller = rbx_stack
+# asm 1: movq <rbx_stack=stack64#6,>rbx_caller=int64#14
+# asm 2: movq <rbx_stack=392(%rsp),>rbx_caller=%rbx
+movq 392(%rsp),%rbx
+
+# qhasm: rbp_caller = rbp_stack
+# asm 1: movq <rbp_stack=stack64#7,>rbp_caller=int64#15
+# asm 2: movq <rbp_stack=400(%rsp),>rbp_caller=%rbp
+movq 400(%rsp),%rbp
+
+# qhasm: leave
+add %r11,%rsp
+xor %rax,%rax
+xor %rdx,%rdx
+ret
+
+# qhasm: bytesatleast65:
+._bytesatleast65:
+
+# qhasm: bytes -= 64
+# asm 1: sub $64,<bytes=int64#6
+# asm 2: sub $64,<bytes=%r9
+sub $64,%r9
+
+# qhasm: out += 64
+# asm 1: add $64,<out=int64#1
+# asm 2: add $64,<out=%rdi
+add $64,%rdi
+
+# qhasm: m += 64
+# asm 1: add $64,<m=int64#2
+# asm 2: add $64,<m=%rsi
+add $64,%rsi
+# comment:fp stack unchanged by jump
+
+# qhasm: goto bytesbetween1and255
+jmp ._bytesbetween1and255