diff --git a/games-fps/gzdoom/Manifest b/games-fps/gzdoom/Manifest new file mode 100644 index 0000000..ec70c18 --- /dev/null +++ b/games-fps/gzdoom/Manifest @@ -0,0 +1,53 @@ +AUX 0001-Add-casts-to-F32-Map-MapIterator-functions-to-get-ri.patch 1456 BLAKE2B 9f2b914ff41c671f12e5ec7840cff901b40ffafe525572fc58b0b11d12fc7902921fb81a9da0b4054f299f0e6da12dd164776ec21d3372c4a3f4266fe5acccc5 SHA512 6d989d7381fee0a4cbff8ff73fdb93d27c0176593fb92f63d082f49e38607f8b91d8f94b7772934899be69802627207ceae817aa82a4a2bd7921fa60ed7a3a25 +AUX 0002-Fix-PMapValueReader-warning-on-Clang-GCC.patch 843 BLAKE2B ffc17e9671ad7db66a7600ef788245c904a6cd3ae097357b073f9e667aeffe30570931e5c7ae3d5b3d2aba349889bb7e16a7940a67904072bfe30d7299c5cec7 SHA512 f3ccf5cf7cbdf89ae933c60c2b6d04f1030f3087f5b49e110595037459d5c77a10cc9f287676d0ad9a77c50f50fe0b8acf2d3f44b815196714da0df650e54a15 +AUX 0003-Fix-Quicksave-Rotation.patch 765 BLAKE2B 3d25b8e8f83286fd06d042ad2cb6d6628592655d749ad9bbdf3a900c1cbcb213e2f39f1059e9e4248ad863ca74da9aadbe4166a21956a7f91402fd0112c40878 SHA512 2f9ea45b230068a0c80c5fb526dd1bc0fb57836a12a17e48c026d54e7d3b1097ef1faecdceacfccfe263054ac899ed63248c851c0258766b2d39b516f1e4b167 +AUX 0004-fixed-some-bad-character-offsets-in-Doom-s-and-Raven.patch 8532 BLAKE2B ac46b7068b6bdb2d29674a8fe42dbaa6ae9fb69c54d651162afb8866c3637dd32f45acaf55b2781f6e2c81e9ab185d056ca63d4b6a2d82f750526ef2c03d03e5 SHA512 66f2753f09957e881ab14df5b27ba46aaea516f84bbb85982741c0ca17b2347347bb6a87fd84318187905655e500007055f6aef7b2cbfa7afd961d46f164522d +AUX 0005-fixed-GC-FullGC-not-collecting-everything-anymore.patch 1948 BLAKE2B 59ef34a0240c5a92a60240e8e1324b4c83e290adaa12c3a9d5040df013e7d0529ba0d7291c301330662d5c20677ffeb02ef9710f99891d12cdf8466def278621 SHA512 9b32f343df38365dde2b0aac8b289f5e81a7ea1d73f296d937ed61917c2d0a8553f446b4a72f8208db976a091a734cf5e282b914c9f42ecee144f295827ad1db +AUX 0006-Fix-wrong-assumptions-about-actor-initialization-in-.patch 1720 BLAKE2B 0690194614019ea1bda135dbb9c805abfd5fe63c268b13c856c3602347e6a46d406e5fbd00c2e00725b2e0ddc81470eb8343933e540bc288bf5bb9fc9c3437be SHA512 3d7c44eb809852cb3b7875696b00bb4b0889ce9bef7f05714f351ca75ffb265b79ebcadee9818022985df5ff0e68d63661113255660dacf507a536e693cea1d5 +AUX 0007-Fixed-IsActorPlayingSound-s-default-argument.patch 1451 BLAKE2B a8f8a1d595aac08593f62eb9c3a49c46dbb67e5ff1c7379d3ce40c9a8b2e7018c4d3b645d1809421f261d9be8e6657420c665367571057eee53d2bcf18ed5a6f SHA512 a31ef8faaa08aed04d9718e68924b0907e84d7b3929eb358ccdd16738f625c6f12593689d62568945ce2609544a2f1c3630aedbd6b27f65eea2c5bd6130b3680 +AUX 0008-removed-clangformat-from-discord-rpc.patch 814 BLAKE2B 3d829420b250dd830028c229c8c9a2ff39064902ad0ab50ac42c83bd454e052966cdb23c1cf08de006878567b66132f83da43aa3c44f71458be0c982f3df73b0 SHA512 bacd20da979045cf07b843de3048c10d2adf6ac45ec48e1bc958a698731c0901b2f5acd0ce2d275298a210c002b07323dbbb591db745063d5078f95c3efe1a8a +AUX 0009-Error-out-instead-of-crashing-for-vector-out-variabl.patch 1055 BLAKE2B 84daa43accc83e4df92a4d19c38754e5e58a7ffa72deceb53db0ee8dcfb4872b2b49966204c3d6a66ecb26aba15db097a72bfedce882e55c58d37d87acecffc6 SHA512 ac1696c41738b6bba94544013435f59d5f3b72d2aed75756047a38d0a6c2242de5228404c219e61a1bc831f9695be10c51b0384982bbeb633b2456a0a5129224 +AUX 0010-Fix-StripLeftRight.patch 1288 BLAKE2B d6e12b0347c902f7294b1a0f06e792a4280224e982209c609905a418fa8aedd3c6659aa0efd81028700d759bc37d71efc092cc251bcbad771cefe44b70b2c099 SHA512 42ffbb9a8d4f2774e5eb216cc8e016100b827c543d5c3630c8d5ccb5477d50af88bdf7347c28be3c4a2a022944d41eed2d34d87e548facdfbfdfd48bff2b54b9 +AUX 0011-Fixed-custom-height-and-width-not-saving.patch 987 BLAKE2B 33b32cd6b150a2a28bc2cadc11fecc4e726d9d501072b849a2a7580086a5c20d604e3b99a8b78a8d333010c0d0043caac54ed5e201631b16c0608a9c3dc464f1 SHA512 98334424983c53948000687d41f18a76cbd6d1666f8eeea5584a22e45cabf9eb2250a009a3b47dafcee68f3043d32d12cc56cc75f267d044a05ab43c69ec5aa4 +AUX 0012-Prevent-important-messages-from-being-accidentally-f.patch 7650 BLAKE2B 09dd89592ac214f0ec064606bf0f51081e0fb0aaffd7ae5f00d25ecaf14adc82be8bf190d75384a7d9fdc00d969929caf9dec6ca959f272825ce62dc89825b55 SHA512 ac97d668204188e610f7f6aaee25eaee82d35bc9a9543f38099bed2fbc502e23765f9c0083e9925085b389ea9111a52b2225f5fe9e6352f4cd65930482e98de2 +AUX 0013-fixed-buffer-size-checks-for-raw-textures.patch 1387 BLAKE2B 767d1f5108fcff0a085de443a68dbf40ada25d9183bfdc4f53f52cb2da90ad71dfaf6ffff1e1512fc91e4902cd97a5893a4483eafd30229b6ed8536cb74d14c3 SHA512 e09c445a3cbe1579e84271ebbceb5acb28cc6ef47673b66586319ee128db13fa93b3f94461b33a20ab21351e694980a167c2be9a0dc44b4145cc67fc56e9836b +AUX 0014-Impel-people-to-include-demo-mods-in-bug-reports.patch 1102 BLAKE2B 7a1efd0b5b0a4bba7efaa57f97f3e24d29fdd1743568da2eff99d10a71b205c6b6ddf48ac8ff04296938b3af16d98e40d35585d0ec86b7b1e780d6bfc0cb1ff7 SHA512 572e5df262dcf88163cb64beceeda9d6eded2d52b9b459817eeea8d4b3332bf94b6b680bbdf235e8b5e01b91542826e30d780cd9d5e395e1c2234b50ebdcb3f6 +AUX 0015-Fixed-a-bug-where-static-events-would-fail-to-halt-p.patch 803 BLAKE2B 8c22648bdb0a5fdf95aad3b632cc3dcac149900b2d850b1f7f6fbdccaf8711633487c1840f41e0bffb231d9642e432fe81580236f9b657b795e3cbc569d2133d SHA512 28766c717660398c9b6b9e15cec9ee3060c2491529165b2e18d2a4870aaf127d790b196ab88354e33fc322f5450ea7141e75b29b419b18724441746bc927b69d +AUX 0016-Fix-MapIterator-X-String-GetValue.patch 1318 BLAKE2B ffd9be0e59d78acb72940b887780b5e57ca610925f627770cbf2b23e10da2809d391b4b9930b617b6416e02a783f44d67eac76229e88a9834cf919d71f5cffab SHA512 b0301667c1eca2026f68774b95a1c7a14dedcee0a96b4aa07120f60885bd068891c8c8022fb7a02991f7a705f03c60308b8d0c7ba0d9446592ed96a9b7fb3a10 +AUX 0017-Fix-two-different-portable-names.patch 1238 BLAKE2B 7b01baa717ac4d605e2f606914aee2849e7bfcf5a403f6e4e6c6d8df34c2e34e979b2140843e099fddc47d070c9b3e71c61cc9d345a584ab305c1a0f5ad1974d SHA512 bd23ec87123fdbd1610b5c0674e863054d9df58915a13262d5d3d3140fbab25d9525061edb0658087b64c5561f1bbaa6998e8c7e49e0adb74563396fc90f236c +AUX 0018-indicate-in-the-startup-window-title-when-GZDoom-is-.patch 1163 BLAKE2B ffb0fe6be80c1c5f217f9ee89485157859550ab65908f95db9e47ff1d44e6c58ba808b4038d8b53d45396b021adbeb4b0fcd68374023f01b9e701b01e7fc510a SHA512 8a66a5d5233df2d3007c1476f3c893d13e53cde9482b446203a414c6b6dd13e0d26e8542fc8897449a8f554d4b4ab4ea514b45626fb0f3760a56a4e4d1909787 +AUX 0019-alt-HUD-use-NewSmallFont-for-drawing-player-s-coordi.patch 2924 BLAKE2B 81c63cb2c2d3fbbff60c744d118f5b7506acfde04c25ff638ad57522f44007bdf5ebf511a95a8cdab1338cd7167ce5cbf5a543045358fb3e0730c23fc53e9c95 SHA512 70749d0e82014801d36e8b7295f7bf7d9f8d15698274a98888b4e2d669e6f317afc2cdc6fdb6fb985efb017eb127d8359e9069417c13406436b4d8274b101f31 +AUX 0020-new-characters-for-Doom-s-SmallFont-and-BigFont.patch 24590 BLAKE2B 97bcbc8e4e2f38bafbd9356ef4fbc958a5a8eabf131a3499fcd0e065f55c3c05b82f92cf8774c9251f54edfbe6300d3061fd50b72e0467c601a48031e0a0e994 SHA512 30e7676386d5ae1691a63df5b3f5f8b3bd906609b8e82f9ac28638f03b7534423aa3656c91d00ccba9dbc177145aed2c497058d2755aa4e483184e330d6999ff +AUX 0021-4-non-letter-characters-for-Chex.patch 3356 BLAKE2B c15174981469a24b3070d0351c292ece1c18c755ebe2b0270a431ed44955a2360cbf23c5069aa7acd0e062c77907b6d4a8da8c998991c5d99ea95a050b799e52 SHA512 39a0889571bcbdf4bc265550d5fff9eb003b2c07c274de68ea18ba71b3b590819ceafd835e9fe7db8957b5768b740078ed599afe4bfdd225b870591c8fc1ef52 +AUX 0022-Fixed-global-TerrainDef-array-not-being-exported-cor.patch 952 BLAKE2B 3f0c89165c4d4047e5774e01900f46c885ce6f7eb4f5e8f0221048faf74a36e1ad29dbd2b2d775f7a3ad844c9e96e7778ce8572a9faa65958b5a2657d5147887 SHA512 b060d2fc4091f5c82c04e7551ff071b2336993600abe5d82a9ee128730ab50c86c39fbbb60959901ea8574c948362eb2dc7023d3c1582744f33072454b916e38 +AUX 0023-convert-characters-to-Doom-patch-format.patch 17507 BLAKE2B 56ce3b780636e751c316be4fd75ff16d37cb020dafa9f5a33424aa80a0bea49e8ce0132df2a889d60944b27751419a867945afc1448db93d8c5aaa07566e7fd0 SHA512 da87583292167475af6f75409b6e7bdcffe3abc0eff9b697bd65ae1d5768d0af871a31aa63ebf62e026a0d17d0b5303959ff723eed386920de3dfa3ddda9662a +AUX 0024-Mark-non-modifying-map-functions-as-const.patch 8847 BLAKE2B 97180c261bd1228d798ead59a7bf83b5f137a740b4a5bd3149b8d4f299207e664459dcf00ffbdf1b6aeef53773fe4ad3d181628a8eed876a8c14516e065c2b94 SHA512 5527569a52f929232aefb874f413084d880ba79a0937822820feaa3cd2580c15d0941d4e54651b8316b467d94cba5c4c2e398e12cba6020bad3c922945d8f9a4 +AUX 0025-Fix-iterator-invalidation-for-Map-Get.patch 1027 BLAKE2B f2360c2546aeebfed91a34fcc714879763005263940b87ad02f39397d348ff1c89fcb2b352a0784ff2c4e10e13b65da4528b8747aab34f029444d5f0fb6f926b SHA512 624c2d1a72e5ad3f531aba3ccc67588c4d0d1b4bd1386ee58181aacfa8777846674a0a6a8bd7aff5bc3c1fad7af92bbf1e1f1638bdbbabe990f91dc68c7bbda3 +AUX 0026-Add-Missing-Read-Barriers-to-Map-Get-Functions.patch 1853 BLAKE2B 289b7988c7ac2e94b5aef45561559b8a7aacc0f954707a9e72babc2411affbc8601c5d445e55c05ef18fdf1cb7cb0a38d02e58eb7a12020ca4464e87c6d06166 SHA512 a5f0026c715a8035b4d799815b2dba10cffe55011efed17e6376077e2f9ca7ee172630e5a93d36cca111ce453b81888030a8f868be513554b5f90da696effddf +AUX 0027-cleanup-of-the-Chex-Quest-small-font.patch 51380 BLAKE2B f55a209204ed08b8f6b9ac1a59e405e7f77577b812b99415118ba1e37164ba93c4b616770d797ff9fe9b8a3aeabe1c5f31be7aadcc3b3509cf5b129dca92647a SHA512 7dd652af071dd727b8dd4d2fbe3674354e360f5dd206956bb1ad02e1a1f6f3452491dcca84f3e9a99e07478792664a28ed642b40ac27f5c9edf2a01376a6ed95 +AUX 0028-refactor-add-some-logs-to-help-understand-what-is-ha.patch 1570 BLAKE2B 26445bf09b1dc03d5346751f1046987c8e198ab42498a5bf3e01e3803a74d884747b30fd0c3f9ebb7fe7c6fdde443a9b24d43c4c1abba91442499777c4bc974e SHA512 01c2f3fc8dc8a4d9d6a05ff074fba1fb98951797820da6a8145a15d03ac958069e9f54adb8c2fe45e0d58174073fa6fe292425ab3db38ac89d7e4ba603889b3a +AUX 0029-Added-check-for-invalid-class-on-in-VM-instantiation.patch 1320 BLAKE2B 393795d4bddf50de35ca9154126a462eb436d3165e7f2da2a14c62e2ba0e23adde405363619b57d46287138dd46c5ce57066cef2ebe2e0351815a7c419500cf1 SHA512 c040918c8e3fe3acc879d186d8eb58723ef4ea96cd3fcb3938b2aa3685fb2e4e3ebfdf891f870e097da812fb3a5fc11cb14c829900bfeb34b841d991c39976c9 +AUX 0030-Fixed-a-bug-where-calling-an-invalid-virtual-functio.patch 893 BLAKE2B 3514f0002599bbd85b15693ebb05e7054ccedca48c9d61c93bafc0a1eca0871d42954c9fd9c7011d30319473840da5a6116413e903308fd4d2b252a7324a8837 SHA512 ae6f1cf65920681f7d936a2e7755f3dc62b7dce4aeea13af742ddca509023b651ec4f7224908024bd59f63c98bc962dfd69e75da4f62ef484d69e0edcb4481e1 +AUX 0031-GLES-Fix-first-wipe.patch 792 BLAKE2B e4295d5a2658e30dbc148154417387fcc29e34a4a89d2f9be2598c2032da42a2e4f36fd5709396b851d16116efbb7c55093f5f731143398934ea3ec87f7db639 SHA512 ca296f234e00a352181fbcf5572d5fb2b5a2e94e0aed31e2bdb6a58c7e44675829a6b709c7782d91a1b1f5e50bb0b186d833f7dbd32a3ccb54c83041fb3ae4b5 +AUX 0032-Mark-const-methods-as-const-in-pseudo-generics.patch 3452 BLAKE2B 5dbe86b77d5d61f82c1be53966bd79be0f73833765b9225b4af36261d451ca5addc96e998131a61c3eaf9fff7c41ebaeb28fa4a5e58f54dc832d798cc2c6bb6f SHA512 21456d9f22300c092f2afb9e2769f7713ed8b785f4b1e0e2df524e063bf6bbee4c5f00e5af9e741266fb8232bfdcc086226786a3a50d4643694065a8bfe80437 +AUX 0033-Fixing-GLES-mode-to-work-on-real-GLES-hardware-and-O.patch 14991 BLAKE2B ab325995dda89d624382dee0b0d04b6894177ba8f4c468c76aeb17a00a2ec0aaaec7c5fd0bed12a15b12bf1f64af426dba5ac97ddcab57cbdfe659da6fafed2a SHA512 7dfc6735de633bdb888cd1af36fba9a3ed0c18bc3e415e81bd77d2e2f1213f7d81242efe584f4845b1104a0690e0561d1779a99f6a0f77116668c8f4e5fa92a4 +AUX 0034-Fix-Software-Slope-Rendering-for-non-1.2-pixel-ratio.patch 976 BLAKE2B 650f1a2c7b10d95b1850979137a3bd396dde4f2c9828de43728a0ff0140622ca4f4c7f4611b6b00e9116365caef00b51d87d8ec3943fd0f9fd4968d2b9db2231 SHA512 bff63b8615e0983f7c16cd810da39e48187d24ef8827261aff3afcabcbf6ad21a443f1cc3d2a41c3585594c912c0b5dc5263a4fc5af3473fb6132297968ff2c9 +AUX 0035-Improve-Services.patch 5438 BLAKE2B 346dc0cb29ddd137fbd730054d4022e8511ad13794495c522b150c6fb3aa1a95251215a8812a1773eedabe79dfafaab506b86cae4f7ccb6e2a61607b299eeb05 SHA512 0483a8893d0ad9cbf288f83d8e13a778105569b6892c4cec18d029573c185d4150c978cecaf6fba9249e35ad497428c46ff70f00154ded249a0c3a78c0a5f02f +AUX 0036-fixed-typo-in-string-label.patch 633 BLAKE2B 7a7c71c2595c1a5456bdd83f60a490bdeddf5f92efd7d1e576cfeddde9a4edaaaa6a894f6417250b4849313a4a27bf918c7068bbc9d6d08c110c9e27bd4ef8db SHA512 3816735c6d8b5d3bd74a3246041a3a13a4a2c7988b2d1440c5677957657784cae3d6ab2eca28bc80f6b4a4818d9d798a7b675bbc4a06cda2dc7d05459119e466 +AUX 0037-Update-service.zs.patch 846 BLAKE2B d422688413b7ad6e8270f9685f211296ef43e5d77051360df79a48de4aadf45c91dc33c825e01c10fe2160ed60a41db754c8c93b90c2bc6eedc1ed348f125fdf SHA512 a4831e68ad13029f7356cf544747ea6dc4bee306588e10768be577de0d478bdc558aa4d2a7828d67bfbe7de7dd495989c0caae4630be85c51f229a7a2bedd765 +AUX 0038-Allow-GAMEINFO-LOAD-to-load-directories.patch 985 BLAKE2B f1491cafdbe2ce28b35d6014a0b125ece148ea58c6112d4e9217e304f1f325b65bab56ec942ccb45ea417fefba172c4855cd82d085884a96ca9cd7e9ab8d40c3 SHA512 dd9af90a268dedc4c241ddddc59821ad4f14ff557331c9d7e6d21fef40cc5a230789d5beb5e376f4e391d86f6b830dd6b7b751c8bb46afd0b928c6975aac6557 +AUX 0039-fixed-bad-character-offset.patch 700 BLAKE2B 8675d782fa14fdb3907e3410cef1b6d384f63bae1260cc8f184217d667bdd6d024e8b3ecc2b1edf691781ef079f0d134d28b5e588c190da140a393fb7860656c SHA512 7075e16c2eac170835d41a2d68fe1afc21ecbe435062345981b356bc72135aa54953b38762e289d2fd598de0d371d7e935f27dfdf4e86eebc07da34519cbb8a7 +AUX 0040-Fixed-incorrect-parameter-type-in-A_CheckForResurrec.patch 884 BLAKE2B 2d27f953bb7a23e637dfce738f93716f97e7b4ab1e15736c42edd48b8048af165aa58b090152bd302e845ec53ececa6ff48f02dad74e2058187a66bb9efaad50 SHA512 1c3730bad63d52589d378b1dcad67c033c77a205d37e1c2a2b59ab799fecf5ceaad32033e4b3bb7846952a714d10efc966c24ddc59dfc6508ef92174a8bbfa5e +AUX 0041-Fix-TArray-allocating-0-bytes-in-constructor.patch 883 BLAKE2B ac1832b18047e65af9e30d2a886b3f26bb65255290370dcac67c6cc6520edd8a0a14a0416cad507e9c0b198b06aeb5c1f9f93d57b18596e555c0d81e788d4f77 SHA512 3a77b47332352674940efbfbb5faa3346da49e1e7bb626bbcb02968596f66fa76bf678adeff690678fc2ed70575b905532f244e637cb886d4153f3c8c853f848 +AUX 0042-Use-simpler-constructor-for-TArray-in-FBlockThingsIt.patch 1005 BLAKE2B 30573f45426762ae08ae8481f6e238c7d2bb4f87ff35b40a523c6900cfc0c369e725f234eb6a24c526d6f61fa0eb52fd0165360cc20ceb81f1804725d71e792c SHA512 d0ba0ec3fa6bf9ec3e0a3ac5487fadb4bde9971c35990a4eb660f3118cb05067857350b45311443d696d3a3c10712b76748ed89c97034f6c011f9505c69212bb +AUX 0043-Fix-possible-memory-corruption-in-TArray-Delete-inde.patch 739 BLAKE2B 9d275d2ba6849c821e7b97e262823167d325fea21c001e2b477e7efe9b9b7cc85e0ff956e84becd1e50f49793753ba47d2c55c7c00cc8366bbf01a85014f8771 SHA512 94f4c5448b8bd08b9734108d16f0719b62a122fac41438b4d2e9363518bd853930532bb2d23cbfdf4797f065a207e8ae892bea12325fa7f623c671e87c63baf5 +AUX 0044-updated-RapidJson-library.patch 460535 BLAKE2B 33a439547b0cc291340e31b5cc471a929442a75acf3dc97f598b2019233499b307be9e4a75eb18f42c2e3f9d489960c12d0427ca5c22b54a38bdf67481948942 SHA512 6b19ba0454a054b02c7faa0f49493511510d2c7451a4e5aa66f8a8004fa257aa4bfe1c31557f8e5e24078b6eba4808298f2cb870a9955abeba85d438fa69ac91 +AUX 0045-made-D_WriteUserInfoStrings-memory-safe.patch 7055 BLAKE2B e65c9ebfe4fad7e67b62a968ab25c412b30936e93576d14e7cbc446491602acc19b4f3de302fa74693b208926f513fa98708c22612c217127def91b40b2e05ae SHA512 596844c81ea53bde64d914907579e70dc994c3ac722178c693aa9a015e7b0c71c8d9699b5fd0b65005cbef93b0e73db85d64452e08951a55179c4e54a721c2fa +AUX 0046-avoid-arithmetics-with-literal-null-pointers-in-Pars.patch 1910 BLAKE2B 0b6cacd3b9d899bfa1a2bc208e1cb67fa83318ccdd364b5c8739208c53595f5fb68c1721234bb3e9ec6f54458df81f98552fd2c36e932976f11568eb596ef7bb SHA512 b1764a2aac19ddf344a39e5c37354d663fa722593d69aa497180890efdd7800f60ed047a62552f41f3675bf56cf6a6774bd2586ce2ba585e194d22550079385f +AUX 0047-backported-RapidJSON-fix-from-Raze.patch 2723 BLAKE2B e276f64f80a2164e3b206e99af81255cb1b50e5555bd8c26860c8caeaeff1abc983311cf9e3c787ae1bb251d02c61bc9256270cb4aacbc8da0724084d9fb9789 SHA512 e02f1349102e657a8a408191be75f4e660d4dc11a2805e955d5b99be00aa1c7e3ff2982bf69ca282e0fd889190092355da76810c41d8eb3bee3de9e0cd60c963 +AUX 0048-Fix-value-of-X-Y-when-Y-is-an-int-constant.patch 933 BLAKE2B 562f19d03b102aaf5ce8e61c8a9df57e8b7dfe1b2b0b5ba6a758326754952f438cded34021b581203c4ffe9a5448f8050db7139715ef7c12339ac0995a1c1aec SHA512 b45a265401d0e34964ece6359d7ccd5b896ba33405e4175bacb7162a3efa0d87aaaa65f640d8338f9e9b304c0f49db38bac727b87efc2bc6313460e7418ff866 +AUX 0049-Fix-BUILD_SHARED_LIBS-build-option-on-Windows.patch 985 BLAKE2B 8aa48badc2e3ea5e0667b6d5b7eb40aabb94f9139a52df3eb32f5d1426376343ad1aec4999f98a8bcf4863e41d85785bf121c079487959fe17c53cd6977e1d02 SHA512 2e4c383a45082cfe3de0f6c9932c28655b4ae20ffba6f4b0989e31ac36b5c675a05c907248e968e83d4dd4735ed20c5537343954c00381e6b82d1957aff0689b +AUX 0050-Add-missing-include-guards.patch 7356 BLAKE2B ea6585c407855027501c2b19c5066b7be632f25eaf644689a2adbf5962b4ef3e860bad43e37094c5e67fe13c476a8a23480b54ef22cf3a52907e826ff0a0fd75 SHA512 bdd5ad506f8f09dd668fd943fb61bc8c919843ca7f4a58142faad395ac6499ac22d79d5bf3fdd2d7d6fdff47f028d8f6ff5ae16687c8cf045bddc61e64a79402 +AUX 0051-Update-service.zs.patch 806 BLAKE2B fb813ae2c68b4736d02a86576922111f7eaaf4b8ac35284240e2a3d1c5f4bdd8347fda2671d618d80aabd3d9c56ed2b186f816a9e724ee586fc63c9d7b9137f6 SHA512 cfa581be100a46b2daf025f4a916fb63d1a9d186e489ddaf66c27253082f6288afd528fb85364df36927f8ea4f7a66807df5ed8b3c48ca3ddc53f2d38785259a +DIST gzdoom-4.10.0.tar.gz 24319337 BLAKE2B a683182ed1bb091d19cff127352068faa846f0a10bc0ade07f8277dca7a5367d0bc19d2828c485fba11cefdb47aa8d99224bb8babbebe3df0b99a6fde577a586 SHA512 fd2f6e34aaa59e3d153de6359211082398878dae3d396ab55fc736f94e1378d5e03193d7912a29a531cf1dc255d30af63ad1c6472784e3745db6ac4a3a9e6fe6 +EBUILD gzdoom-4.10.0-r1.ebuild 5736 BLAKE2B f4f8768736c626e15c6bc3394e424a56af43e84d7175521d59de8800a5a9d8c9654f6d91533d995be6da9af6eff62797687077bce632c8994c260255f1996d0d SHA512 aba87d5389843beb03cbe23af85aba7a66920580aeadf9b09390e8d25df0cf91d7939be390ce32309d624fba9a63ebb566696ec36630490c12530c4acf93e12f diff --git a/games-fps/gzdoom/files/0001-Add-casts-to-F32-Map-MapIterator-functions-to-get-ri.patch b/games-fps/gzdoom/files/0001-Add-casts-to-F32-Map-MapIterator-functions-to-get-ri.patch new file mode 100644 index 0000000..f49799c --- /dev/null +++ b/games-fps/gzdoom/files/0001-Add-casts-to-F32-Map-MapIterator-functions-to-get-ri.patch @@ -0,0 +1,51 @@ +From ac07dac1782544b61e44b9fe1d5f0fffd356aa15 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sun, 4 Dec 2022 17:10:09 -0300 +Subject: [PATCH 01/51] Add casts to F32 Map/MapIterator functions to get rid + of double to float conversion warnings + +--- + src/common/scripting/core/maps.cpp | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/src/common/scripting/core/maps.cpp b/src/common/scripting/core/maps.cpp +index bb7cd369b..28fda643e 100644 +--- a/src/common/scripting/core/maps.cpp ++++ b/src/common/scripting/core/maps.cpp +@@ -162,7 +162,15 @@ template void MapInsert(M * self, expand_types_vmInsert(key, value); ++ ++ if constexpr(std::is_same_v) ++ { ++ self->Insert(key,static_cast(value)); ++ } ++ else ++ { ++ self->Insert(key, value); ++ } + self->info->rev++; // invalidate iterators + } + +@@ -246,7 +254,15 @@ template void MapIteratorSetValue(I * self, expand_types_vm) ++ { ++ val = static_cast(value); ++ } ++ else ++ { ++ val = value; ++ } + } + + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0002-Fix-PMapValueReader-warning-on-Clang-GCC.patch b/games-fps/gzdoom/files/0002-Fix-PMapValueReader-warning-on-Clang-GCC.patch new file mode 100644 index 0000000..6bb22e7 --- /dev/null +++ b/games-fps/gzdoom/files/0002-Fix-PMapValueReader-warning-on-Clang-GCC.patch @@ -0,0 +1,25 @@ +From e07fcbfc8f1be46712ce5a3271334b63494ac3d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sun, 4 Dec 2022 17:21:09 -0300 +Subject: [PATCH 02/51] Fix PMapValueReader warning on Clang/GCC + +--- + src/common/scripting/core/types.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp +index 702277e89..3054335ac 100644 +--- a/src/common/scripting/core/types.cpp ++++ b/src/common/scripting/core/types.cpp +@@ -2603,7 +2603,7 @@ template + static bool PMapValueReader(FSerializer &ar, M *map, const PMap *m) + { + const char * k; +- while(k = ar.GetKey()) ++ while((k = ar.GetKey())) + { + typename M::ValueType * val; + if constexpr(std::is_same_v) +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0003-Fix-Quicksave-Rotation.patch b/games-fps/gzdoom/files/0003-Fix-Quicksave-Rotation.patch new file mode 100644 index 0000000..156a32e --- /dev/null +++ b/games-fps/gzdoom/files/0003-Fix-Quicksave-Rotation.patch @@ -0,0 +1,25 @@ +From 0d60192f3dfed0c6bf62a037241329543c006b4d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sun, 4 Dec 2022 22:25:51 -0300 +Subject: [PATCH 03/51] Fix Quicksave Rotation + +--- + src/g_game.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/g_game.cpp b/src/g_game.cpp +index d015fe837..4a3398fde 100644 +--- a/src/g_game.cpp ++++ b/src/g_game.cpp +@@ -2250,7 +2250,7 @@ void G_DoQuickSave () + num.Int = lastquicksave; + quicksavenum->ForceSet (num, CVAR_Int); + +- file = G_BuildSaveName(FStringf("quick%02d", nextautosave)); ++ file = G_BuildSaveName(FStringf("quick%02d", lastquicksave)); + + readableTime = myasctime (); + description.Format("Quicksave %s", readableTime); +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0004-fixed-some-bad-character-offsets-in-Doom-s-and-Raven.patch b/games-fps/gzdoom/files/0004-fixed-some-bad-character-offsets-in-Doom-s-and-Raven.patch new file mode 100644 index 0000000..acea3fd --- /dev/null +++ b/games-fps/gzdoom/files/0004-fixed-some-bad-character-offsets-in-Doom-s-and-Raven.patch @@ -0,0 +1,180 @@ +From 370fcda5fa5fb07bbc6bfbbedb4004e7af0a4119 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Mon, 5 Dec 2022 12:05:26 +0100 +Subject: [PATCH 04/51] - fixed some bad character offsets in Doom's and + Raven's small fonts and deleted an incomplete character. + +--- + .../filter/doom.id/fonts/defsmallfont/00CE.lmp | Bin 94 -> 94 bytes + .../filter/doom.id/fonts/defsmallfont/00CF.lmp | Bin 124 -> 124 bytes + .../filter/doom.id/fonts/defsmallfont/00D1.lmp | Bin 164 -> 164 bytes + .../filter/doom.id/fonts/defsmallfont/00D2.lmp | Bin 136 -> 136 bytes + .../game-heretic/fonts/defsmallfont/0404.lmp | Bin 129 -> 129 bytes + .../game-heretic/fonts/defsmallfont/0490.lmp | Bin 123 -> 123 bytes + .../game-hexen/fonts/defsmallfont/0403.png | Bin 1196 -> 0 bytes + .../game-hexen/fonts/defsmallfont/0404.lmp | Bin 0 -> 129 bytes + .../game-hexen/fonts/defsmallfont/0404.png | Bin 893 -> 0 bytes + .../game-hexen/fonts/defsmallfont/0490.lmp | Bin 0 -> 123 bytes + .../game-hexen/fonts/defsmallfont/0490.png | Bin 891 -> 0 bytes + 11 files changed, 0 insertions(+), 0 deletions(-) + delete mode 100644 wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0403.png + create mode 100644 wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.lmp + delete mode 100644 wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.png + create mode 100644 wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.lmp + delete mode 100644 wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.png + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CE.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CE.lmp +index fac2a4633e3c904203afa3c02714f849a4c630ca..30e2b0d3be7650dca0d8b59edb49c108f63835be 100644 +GIT binary patch +delta 13 +Ucma!xV`pXHVqjokp2!{!01Pex#Q*>R + +delta 13 +Scma!xV`pXHVgQ1P?BM_mA_2kx + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CF.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/00CF.lmp +index 2f6dcf7c27c5b216f5b85965dcc8ef0663d689a1..bf0359c31651ee01f24dbec2ec46df3b1f986af5 100644 +GIT binary patch +delta 13 +Ucmb=aVdr4rVqjokp2%Jb01sFKA^-pY + +delta 13 +Scmb=aVdr4rVgQ1P?4|kW)VBlh4U|^oe-Ut8^L;^?v + +delta 15 +UcmeBR>|kW)VBlf^f{E;n01`L?MF0Q* + +diff --git a/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/game-heretic/fonts/defsmallfont/0404.lmp +index d515a5a362e89d28f9cd28dd57c7338c14538824..af549dd86f3dd84956c7c3fbe24759017b21c939 100644 +GIT binary patch +delta 16 +XcmZoJ!F#s7f1Q`GT + +delta 14 +Vcmb=f=HOu9U|?WiVwlKL3;+;E0v!MV + +diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0403.png b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0403.png +deleted file mode 100644 +index c6ea83aeeb115b78e29217ea6d6686ef4de817aa..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 1196 +zcmd^9!K>V45TEBOJ;P~{$$t@C(h*3v}#J|w__rr6b{n6DANCZTDCc&pHz#-gx@Ah>9 +z2^`Halx0~Y$MZbPvNTOo6eX*IC^4KsF&x;MWGbRA@i-no9S)xi2D^TLTNIm4XPu_Y +zIG%^$EC{BaH*wv@wnwH}>-s>`N=50*av@1wQOpG)0y&U9j5z1ye-2`FIaWGMefWqdzxBJYz`x15b9;1 +z6~5YWmCTV7TMEsVZ-|aASSqi}oFcK3$n5v~?RLA_Y}V`ba=Dz(=d;;tI-QQkJ8Fbsmg^E}seZQC|Y(=ZH8(^OTJWx3UAiK3Wb +z6z$vXjqfj9Z)!Uu)2ei%r|P+^#*!R}Er%Bjj#C&`q-lw<6bQJGyVFuAw-(T;)NLIC*F#zTS2e&y;LUG!#C~f+%*|q3s2x<7%d@ +z=%%FVEyQ@Yc2^VQK`D_zU4RTA2519#0AyukU)wFtW;h&TQD7XS63aBE>oN^t>;3d#t=It>5#`}kde1NivXnL|?l +z>+`erk3^p8;=LPp$d+mL+z#OTA6_Qlo2MsNZy$XZJp6rr_|yHjzr6qBZ(l!r{OjFU +z#kZK(zU5!)&yOx#{^XlKUw`NBE1w_yb%A^~ca|?+yv%&@2C0VA>t`pwTzmhs{{Z$O +Ba>@Vz + +diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..cec6e159655acc71a3bea2d48f12112da4b75d78 +GIT binary patch +literal 129 +zcmX|(!3}^g3YF+{SN##mAcpI2lgUGzSqAiq5+`}?Zh)W0~1@6jIQbr0JB + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.png b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0404.png +deleted file mode 100644 +index 0e4d9ac52322e0ad145632cc74a3a5d257330a17..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 893 +zcmW-fF{s;C6oyaw28E{vQ#1&wK`A0QAc_VJDrgX?-a~yTM31L{C>oR^iicZJL4yi{ +z2r7zOJg6Xw2MroLXfVWs1`i(G5Q-okoZy0?9y|oD$TVI36F0Vm}=2(sUEYD?++3T>AdP^IFH5Syp2h +z6J4)Vb*w0bERQ597sX5v5}uDaj`Vs1mJJxjXBd}Z8~_Wzq{AHd_-2E<4mS&2x7anf +ztZ-3co4=c;r%8OM$i57>BY&N{tIS!Zb{kvM$ea+P3iTq;hMtIbIe8ltTU +zhQg~dCriE4>2x?8_WS*Ax7%zstJSLOy5({?pU>O2old7s)6{i69*@hi9F0bKo@ZH> +zBuNxSgpe={ec$&y&v6{fvP{#|bzRdmMN#_wz9dNrM$u_7*ayMd^Ouf0v+UY1OU=j? +zEtZu~>brty^1RyPB$nlwWmC-S;cT2WMN$u=DkEhYj$%J2UK%<{U`L)gaE-v$JX3WI +zrOv}5adToPfiZAZ-;y0&GF2hX!YK9z#PLJR^>oWo4NKOHK4N^_dE15gqEcq5Soz%0 +zWMUa;*0|f@Vu4kKX^KIBhJm6;VK@Q20oVep0G0qPKm$+#i~ur#7+?V41JKB5UWWsA +z9ZsiM6d1?ox~OTCA}T`{m7y9`fOh8q1i<~@_qfCD0=o*^6em6wI%dM#m_J6n{h+rE +z*pqQ>71yw?p^AVsg#2**mrB1sySjMr_`5&utsb1i-4D;6|2ew3e|i7u-GA`) +zkMpmeoc(<9$**7jVn4qsFB|#z+u!`F-~C&!%5QId`s}0btDBe93*hSV(Z#dRpM3ux +DKQnIz + +diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.lmp b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..16033384e9ef18923ca85327569eff6e9eb20461 +GIT binary patch +literal 123 +zcmXYpK?;B{3N+Gi>$q*XNEMiw4;uKw6;uep1 +kMFI(EfJlngYALgC*|U?{llAxHEWo(iDml;MKFjzOAAP0|fB*mh + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.png b/wadsrc_extra/static/filter/game-hexen/fonts/defsmallfont/0490.png +deleted file mode 100644 +index 4af1bb68091ca11c81730a6c549cbc56ec9a452b..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 891 +zcmW-fF{s;C6oyYpsKQf%DH;S7)F~QF(V&2!8Wa$XUaCA)o!qsB +z6eX9WsVHWGFy{HR-%mI$V%d;k{9bQJ(=J6h6lGDA37`XLWSPSbUv02!akIpAjctid +zj>`$w>FX*!&cc1}?8&Jnr}V-EP-)-Da~{tyXQ@HchiwEb6+hs;Vr@q9~@*>0~k)kH=}6CP@-S +zQ4j>a?|Yu-IF4=GrfKTBu4$U0D6%YzqBs}~c%F|i2#&+y&UM$e)0oy=Hwsmo$Z9Ie +zp&)wvz~cHE%St_lr)idI%4|`L=F_CiqGA-}i9dEojz}_3o +zWm7LqSm-d<-tLK8#2PU}^bvJL9uZ0v3K=FMjCf+sfhKY?&xjmNM!dC>0w4nL04xAW +z0u~zX4U9=Eu3=q39)Mr^{_ns2@HZ)ce0KWD!zcfEkFI`wadG?Ge=ly|{BHI5Px|Eg +zv+v)Pe!l$gj|U%q`TXYN>tFr&^46!HfAGyae_j0opt|>-e(R@SKOzJ;yL*26%biD0 +F{|BW2ZJ7W7 + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0005-fixed-GC-FullGC-not-collecting-everything-anymore.patch b/games-fps/gzdoom/files/0005-fixed-GC-FullGC-not-collecting-everything-anymore.patch new file mode 100644 index 0000000..7cedc47 --- /dev/null +++ b/games-fps/gzdoom/files/0005-fixed-GC-FullGC-not-collecting-everything-anymore.patch @@ -0,0 +1,70 @@ +From 91930dfe53d6ca1432c9e58cb108124e5b3ea5b0 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Mon, 5 Dec 2022 12:29:03 +0100 +Subject: [PATCH 05/51] - fixed GC::FullGC not collecting everything anymore. + +With the delayed handling of internal references of destroyed objects the function now returned without making sure that it really got everything. +Repeating until it cannot delete anything new anymore makes it work again as intended. +--- + src/common/objects/dobjgc.cpp | 40 ++++++++++++++++++++--------------- + 1 file changed, 23 insertions(+), 17 deletions(-) + +diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp +index 34199efff..9baffc3a3 100644 +--- a/src/common/objects/dobjgc.cpp ++++ b/src/common/objects/dobjgc.cpp +@@ -550,28 +550,34 @@ void Step() + + void FullGC() + { +- if (State <= GCS_Propagate) ++ bool ContinueCheck = true; ++ while (ContinueCheck) + { +- // Reset sweep mark to sweep all elements (returning them to white) +- SweepPos = &Root; +- // Reset other collector lists +- Gray = nullptr; +- State = GCS_Sweep; +- } +- // Finish any pending GC stages +- while (State != GCS_Pause) +- { +- SingleStep(); +- } +- // Loop until everything that can be destroyed and freed is +- do +- { +- MarkRoot(); ++ ContinueCheck = false; ++ if (State <= GCS_Propagate) ++ { ++ // Reset sweep mark to sweep all elements (returning them to white) ++ SweepPos = &Root; ++ // Reset other collector lists ++ Gray = nullptr; ++ State = GCS_Sweep; ++ } ++ // Finish any pending GC stages + while (State != GCS_Pause) + { + SingleStep(); + } +- } while (HadToDestroy); ++ // Loop until everything that can be destroyed and freed is ++ do ++ { ++ MarkRoot(); ++ while (State != GCS_Pause) ++ { ++ SingleStep(); ++ } ++ ContinueCheck |= HadToDestroy; ++ } while (HadToDestroy); ++ } + } + + //========================================================================== +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0006-Fix-wrong-assumptions-about-actor-initialization-in-.patch b/games-fps/gzdoom/files/0006-Fix-wrong-assumptions-about-actor-initialization-in-.patch new file mode 100644 index 0000000..5b05a8a --- /dev/null +++ b/games-fps/gzdoom/files/0006-Fix-wrong-assumptions-about-actor-initialization-in-.patch @@ -0,0 +1,55 @@ +From 50c0860dd6dd34c9aeff63e8cc348ecdc103f498 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Mon, 5 Dec 2022 15:05:08 -0300 +Subject: [PATCH 06/51] Fix wrong assumptions about actor initialization in + Map/MapIterator + +--- + src/common/scripting/core/types.cpp | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp +index 3054335ac..838275dad 100644 +--- a/src/common/scripting/core/types.cpp ++++ b/src/common/scripting/core/types.cpp +@@ -2399,10 +2399,6 @@ void PMap::Construct(void * addr) const { + + void PMap::InitializeValue(void *addr, const void *def) const + { +- if (def != nullptr) +- { +- I_Error("Map cannot have default values"); +- } + Construct(addr); + } + +@@ -2475,7 +2471,6 @@ void PMap::DestroyValue(void *addr) const + + void PMap::SetDefaultValue(void *base, unsigned offset, TArray *special) + { +- assert(!(base && special)); + if (base != nullptr) + { + Construct(((uint8_t*)base)+offset); // is this needed? string/dynarray do this initialization if base != nullptr, but their initialization doesn't need to allocate +@@ -2868,10 +2863,6 @@ void PMapIterator::Construct(void * addr) const { + + void PMapIterator::InitializeValue(void *addr, const void *def) const + { +- if (def != nullptr) +- { +- I_Error("Map cannot have default values"); +- } + Construct(addr); + } + +@@ -2944,7 +2935,6 @@ void PMapIterator::DestroyValue(void *addr) const + + void PMapIterator::SetDefaultValue(void *base, unsigned offset, TArray *special) + { +- assert(!(base && special)); + if (base != nullptr) + { + Construct(((uint8_t*)base)+offset); +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0007-Fixed-IsActorPlayingSound-s-default-argument.patch b/games-fps/gzdoom/files/0007-Fixed-IsActorPlayingSound-s-default-argument.patch new file mode 100644 index 0000000..3014dd7 --- /dev/null +++ b/games-fps/gzdoom/files/0007-Fixed-IsActorPlayingSound-s-default-argument.patch @@ -0,0 +1,26 @@ +From 7fcd1ab5449e451d1eeb2529839f0cfda7a67724 Mon Sep 17 00:00:00 2001 +From: Boondorl <59555366+Boondorl@users.noreply.github.com> +Date: Tue, 6 Dec 2022 06:02:28 -0500 +Subject: [PATCH 07/51] Fixed IsActorPlayingSound's default argument + +Now properly passes the invalid sound id. +--- + wadsrc/static/zscript/actors/actor.zs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs +index 4fbc2e761..978fc34ab 100644 +--- a/wadsrc/static/zscript/actors/actor.zs ++++ b/wadsrc/static/zscript/actors/actor.zs +@@ -1129,7 +1129,7 @@ class Actor : Thinker native + native void A_StopSounds(int chanmin, int chanmax); + deprecated("2.3", "Use A_StartSound() instead") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0); + deprecated("2.3", "Use A_StopSound() instead") native void A_StopSoundEx(name slot); +- native clearscope bool IsActorPlayingSound(int channel, Sound snd = 0); ++ native clearscope bool IsActorPlayingSound(int channel, Sound snd = -1); + native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10); + native action state A_Jump(int chance, statelabel label, ...); + native Actor A_SpawnProjectile(class missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET); +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0008-removed-clangformat-from-discord-rpc.patch b/games-fps/gzdoom/files/0008-removed-clangformat-from-discord-rpc.patch new file mode 100644 index 0000000..f37fa0e --- /dev/null +++ b/games-fps/gzdoom/files/0008-removed-clangformat-from-discord-rpc.patch @@ -0,0 +1,27 @@ +From 1fcc6826eada90cd550398376ecac9bf582aed2f Mon Sep 17 00:00:00 2001 +From: "alexey.lysiuk" +Date: Sun, 11 Dec 2022 17:15:09 +0200 +Subject: [PATCH 08/51] - removed clangformat from discord-rpc + +--- + libraries/discordrpc/src/CMakeLists.txt | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/libraries/discordrpc/src/CMakeLists.txt b/libraries/discordrpc/src/CMakeLists.txt +index 18c3009e2..34aca1e4b 100644 +--- a/libraries/discordrpc/src/CMakeLists.txt ++++ b/libraries/discordrpc/src/CMakeLists.txt +@@ -118,10 +118,6 @@ if (${BUILD_SHARED_LIBS}) + target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK) + endif(${BUILD_SHARED_LIBS}) + +-if (CLANG_FORMAT_CMD) +- add_dependencies(discord-rpc clangformat) +-endif(CLANG_FORMAT_CMD) +- + # install + + install( +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0009-Error-out-instead-of-crashing-for-vector-out-variabl.patch b/games-fps/gzdoom/files/0009-Error-out-instead-of-crashing-for-vector-out-variabl.patch new file mode 100644 index 0000000..c14d88d --- /dev/null +++ b/games-fps/gzdoom/files/0009-Error-out-instead-of-crashing-for-vector-out-variabl.patch @@ -0,0 +1,27 @@ +From 7cfb72ee4deead7a800fb9c82719bf0c2b86aa9d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sun, 18 Dec 2022 15:43:54 -0300 +Subject: [PATCH 09/51] Error out instead of crashing for vector out variables + +--- + src/common/scripting/vm/vmexec.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h +index 671bfc081..6716509da 100644 +--- a/src/common/scripting/vm/vmexec.h ++++ b/src/common/scripting/vm/vmexec.h +@@ -824,6 +824,10 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) + assert(b < f->NumRegF); + ::new(param) VMValue(®.f[b]); + break; ++ case REGT_FLOAT | REGT_MULTIREG2 | REGT_ADDROF: ++ case REGT_FLOAT | REGT_MULTIREG3 | REGT_ADDROF: ++ case REGT_FLOAT | REGT_MULTIREG4 | REGT_ADDROF: ++ I_Error("REGT_ADDROF not implemented for vectors\n"); + case REGT_FLOAT | REGT_KONST: + assert(b < sfunc->NumKonstF); + ::new(param) VMValue(konstf[b]); +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0010-Fix-StripLeftRight.patch b/games-fps/gzdoom/files/0010-Fix-StripLeftRight.patch new file mode 100644 index 0000000..7c9c30a --- /dev/null +++ b/games-fps/gzdoom/files/0010-Fix-StripLeftRight.patch @@ -0,0 +1,45 @@ +From f4374179284cc9581c8ec7d629d1e93cfd443b16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sun, 18 Dec 2022 21:19:18 -0300 +Subject: [PATCH 10/51] Fix StripLeftRight + +--- + src/common/utility/zstring.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/common/utility/zstring.cpp b/src/common/utility/zstring.cpp +index 8d4d4d119..2b3c4f1fe 100644 +--- a/src/common/utility/zstring.cpp ++++ b/src/common/utility/zstring.cpp +@@ -843,7 +843,7 @@ void FString::StripLeftRight () + } + for (j = max - 1; j >= i; --j) + { +- if (Chars[i] < 0 || !isspace((unsigned char)Chars[j])) ++ if (Chars[j] < 0 || !isspace((unsigned char)Chars[j])) + break; + } + if (i == 0 && j == max - 1) +@@ -863,7 +863,7 @@ void FString::StripLeftRight () + { + FStringData *old = Data(); + AllocBuffer(j - i + 1); +- StrCopy(Chars, old->Chars(), j - i + 1); ++ StrCopy(Chars, old->Chars() + i, j - i + 1); + old->Release(); + } + } +@@ -899,8 +899,8 @@ void FString::StripLeftRight (const char *charset) + else + { + FStringData *old = Data(); +- AllocBuffer (j - i); +- StrCopy (Chars, old->Chars(), j - i); ++ AllocBuffer (j - i + 1); ++ StrCopy (Chars, old->Chars() + i, j - i + 1); + old->Release(); + } + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0011-Fixed-custom-height-and-width-not-saving.patch b/games-fps/gzdoom/files/0011-Fixed-custom-height-and-width-not-saving.patch new file mode 100644 index 0000000..84957ff --- /dev/null +++ b/games-fps/gzdoom/files/0011-Fixed-custom-height-and-width-not-saving.patch @@ -0,0 +1,28 @@ +From ab0f928bc324750ae5e8f4b92b308fe8e0a00d7e Mon Sep 17 00:00:00 2001 +From: CandiceJoy +Date: Sun, 1 Jan 2023 22:51:37 -0500 +Subject: [PATCH 11/51] Fixed custom height and width not saving. + +Signed-off-by: CandiceJoy +--- + src/common/menu/resolutionmenu.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/common/menu/resolutionmenu.cpp b/src/common/menu/resolutionmenu.cpp +index 6074d018a..1920927bb 100644 +--- a/src/common/menu/resolutionmenu.cpp ++++ b/src/common/menu/resolutionmenu.cpp +@@ -83,8 +83,8 @@ CCMD (menu_resolution_commit_changes) + vid_fullscreen = true; + vid_scalemode = 5; + vid_scalefactor = 1.; +- vid_scale_customwidth = menu_resolution_custom_width; +- vid_scale_customheight = menu_resolution_custom_height; ++ vid_scale_customwidth = *menu_resolution_custom_width; ++ vid_scale_customheight = *menu_resolution_custom_height; + vid_scale_custompixelaspect = 1.0; + } + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0012-Prevent-important-messages-from-being-accidentally-f.patch b/games-fps/gzdoom/files/0012-Prevent-important-messages-from-being-accidentally-f.patch new file mode 100644 index 0000000..a7d3ff0 --- /dev/null +++ b/games-fps/gzdoom/files/0012-Prevent-important-messages-from-being-accidentally-f.patch @@ -0,0 +1,176 @@ +From 112d0060d58dd2a107fed3c5454504f67128d88f Mon Sep 17 00:00:00 2001 +From: Marisa the Magician +Date: Wed, 4 Jan 2023 11:56:15 +0100 +Subject: [PATCH 12/51] Prevent important messages from being accidentally + filtered. + +--- + src/common/engine/serializer.cpp | 2 +- + src/common/filesystem/filesystem.cpp | 4 ++-- + src/common/menu/menu.cpp | 2 +- + src/common/scripting/vm/vmframe.cpp | 2 +- + src/d_main.cpp | 2 +- + src/g_level.cpp | 2 +- + src/p_conversation.cpp | 2 +- + src/playsim/dthinker.cpp | 4 ++-- + src/playsim/p_acs.cpp | 2 +- + src/playsim/p_spec.cpp | 2 +- + src/playsim/p_user.cpp | 2 +- + 11 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/src/common/engine/serializer.cpp b/src/common/engine/serializer.cpp +index 808b0fedc..8c68b5a3b 100644 +--- a/src/common/engine/serializer.cpp ++++ b/src/common/engine/serializer.cpp +@@ -683,7 +683,7 @@ void FSerializer::ReadObjects(bool hubtravel) + { + r->mObjects.Clamp(size); // close all inner objects. + // In case something in here throws an error, let's continue and deal with it later. +- Printf(PRINT_NONOTIFY, TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); ++ Printf(PRINT_NONOTIFY | PRINT_BOLD, TEXTCOLOR_RED "'%s'\n while restoring %s\n", err.GetMessage(), obj ? obj->GetClass()->TypeName.GetChars() : "invalid object"); + mErrors++; + } + } +diff --git a/src/common/filesystem/filesystem.cpp b/src/common/filesystem/filesystem.cpp +index 21acc4e2f..f18ad5138 100644 +--- a/src/common/filesystem/filesystem.cpp ++++ b/src/common/filesystem/filesystem.cpp +@@ -1696,6 +1696,6 @@ CCMD(fs_dir) + auto fnid = fileSystem.GetResourceId(i); + auto length = fileSystem.FileLength(i); + bool hidden = fileSystem.FindFile(fn1) != i; +- Printf(PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : ""); ++ Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s%-64s %-15s (%5d) %10d %s %s\n", hidden ? TEXTCOLOR_RED : TEXTCOLOR_UNTRANSLATED, fn1, fns, fnid, length, container, hidden ? "(h)" : ""); + } +-} +\ No newline at end of file ++} +diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp +index deee74597..c5890080c 100644 +--- a/src/common/menu/menu.cpp ++++ b/src/common/menu/menu.cpp +@@ -925,7 +925,7 @@ void M_Init (void) + catch (CVMAbortException &err) + { + err.MaybePrintMessage(); +- Printf(PRINT_NONOTIFY, "%s", err.stacktrace.GetChars()); ++ Printf(PRINT_NONOTIFY | PRINT_BOLD, "%s", err.stacktrace.GetChars()); + I_FatalError("Failed to initialize menus"); + } + M_CreateMenus(); +diff --git a/src/common/scripting/vm/vmframe.cpp b/src/common/scripting/vm/vmframe.cpp +index 69b47dfd5..a2c972820 100644 +--- a/src/common/scripting/vm/vmframe.cpp ++++ b/src/common/scripting/vm/vmframe.cpp +@@ -682,7 +682,7 @@ void CVMAbortException::MaybePrintMessage() + auto m = GetMessage(); + if (m != nullptr) + { +- Printf(PRINT_NONOTIFY, TEXTCOLOR_RED "%s\n", m); ++ Printf(PRINT_NONOTIFY | PRINT_BOLD, TEXTCOLOR_RED "%s\n", m); + SetMessage(""); + } + } +diff --git a/src/d_main.cpp b/src/d_main.cpp +index 12b3fb9ff..5bf8e8928 100644 +--- a/src/d_main.cpp ++++ b/src/d_main.cpp +@@ -1237,7 +1237,7 @@ void D_DoomLoop () + catch (CVMAbortException &error) + { + error.MaybePrintMessage(); +- Printf(PRINT_NONOTIFY, "%s", error.stacktrace.GetChars()); ++ Printf(PRINT_NONOTIFY | PRINT_BOLD, "%s", error.stacktrace.GetChars()); + D_ErrorCleanup(); + } + } +diff --git a/src/g_level.cpp b/src/g_level.cpp +index 8aa011506..2fbba84f0 100644 +--- a/src/g_level.cpp ++++ b/src/g_level.cpp +@@ -1385,7 +1385,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au + { + FString mapname = nextmapname; + mapname.ToUpper(); +- Printf(PRINT_NONOTIFY, "\n" TEXTCOLOR_NORMAL "%s\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", console_bar, mapname.GetChars(), LevelName.GetChars()); ++ Printf(PRINT_HIGH | PRINT_NONOTIFY, "\n" TEXTCOLOR_NORMAL "%s\n\n" TEXTCOLOR_BOLD "%s - %s\n\n", console_bar, mapname.GetChars(), LevelName.GetChars()); + } + + // Set the sky map. +diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp +index 13f54e9ab..47d9a896f 100644 +--- a/src/p_conversation.cpp ++++ b/src/p_conversation.cpp +@@ -718,7 +718,7 @@ static void TerminalResponse (const char *str) + + if (StatusBar != NULL) + { +- Printf(PRINT_NONOTIFY, "%s\n", str); ++ Printf(PRINT_HIGH | PRINT_NONOTIFY, "%s\n", str); + // The message is positioned a bit above the menu choices, because + // merchants can tell you something like this but continue to show + // their dialogue screen. I think most other conversations use this +diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp +index 37e135230..86ef7918c 100644 +--- a/src/playsim/dthinker.cpp ++++ b/src/playsim/dthinker.cpp +@@ -538,7 +538,7 @@ bool FThinkerList::DoDestroyThinkers() + { + Printf("VM exception in DestroyThinkers:\n"); + exception.MaybePrintMessage(); +- Printf(PRINT_NONOTIFY, "%s", exception.stacktrace.GetChars()); ++ Printf(PRINT_NONOTIFY | PRINT_BOLD, "%s", exception.stacktrace.GetChars()); + // forcibly delete this. Cleanup may be incomplete, though. + node->ObjectFlags |= OF_YesReallyDelete; + delete node; +@@ -546,7 +546,7 @@ bool FThinkerList::DoDestroyThinkers() + } + catch (CRecoverableError &exception) + { +- Printf(PRINT_NONOTIFY, "Error in DestroyThinkers: %s\n", exception.GetMessage()); ++ Printf(PRINT_NONOTIFY | PRINT_BOLD, "Error in DestroyThinkers: %s\n", exception.GetMessage()); + // forcibly delete this. Cleanup may be incomplete, though. + node->ObjectFlags |= OF_YesReallyDelete; + delete node; +diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp +index 01def4758..9ee22264c 100644 +--- a/src/playsim/p_acs.cpp ++++ b/src/playsim/p_acs.cpp +@@ -8769,7 +8769,7 @@ scriptwait: + if (type & HUDMSG_LOG) + { + int consolecolor = color >= CR_BRICK && color < NUM_TEXT_COLORS && color != CR_UNTRANSLATED ? color + 'A' : '-'; +- Printf(PRINT_NONOTIFY, "\n" TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", consolecolor, console_bar, work.GetChars(), console_bar); ++ Printf(PRINT_HIGH | PRINT_NONOTIFY, "\n" TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", consolecolor, console_bar, work.GetChars(), console_bar); + } + } + } +diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp +index ab682f171..52760d935 100644 +--- a/src/playsim/p_spec.cpp ++++ b/src/playsim/p_spec.cpp +@@ -622,7 +622,7 @@ void P_GiveSecret(FLevelLocals *Level, AActor *actor, bool printmessage, bool pl + C_MidPrint(nullptr, GStrings["SECRETMESSAGE"]); + if (showsecretsector && sectornum >= 0) + { +- Printf(PRINT_NONOTIFY, "Secret found in sector %d\n", sectornum); ++ Printf(PRINT_HIGH | PRINT_NONOTIFY, "Secret found in sector %d\n", sectornum); + } + } + if (playsound) S_Sound (CHAN_AUTO, CHANF_UI, "misc/secret", 1, ATTN_NORM); +diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp +index 0fa33a90e..0bc45d1f4 100644 +--- a/src/playsim/p_user.cpp ++++ b/src/playsim/p_user.cpp +@@ -422,7 +422,7 @@ void player_t::SetLogText (const char *text) + if (mo && mo->CheckLocalView()) + { + // Print log text to console +- Printf(PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings(text + 1) : text); ++ Printf(PRINT_HIGH | PRINT_NONOTIFY, TEXTCOLOR_GOLD "%s\n", LogText[0] == '$' ? GStrings(text + 1) : text); + } + } + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0013-fixed-buffer-size-checks-for-raw-textures.patch b/games-fps/gzdoom/files/0013-fixed-buffer-size-checks-for-raw-textures.patch new file mode 100644 index 0000000..3e86f37 --- /dev/null +++ b/games-fps/gzdoom/files/0013-fixed-buffer-size-checks-for-raw-textures.patch @@ -0,0 +1,43 @@ +From 6333e4fefb5c41971ca0d4bf97648f21b693e8f7 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sat, 7 Jan 2023 16:15:32 +0100 +Subject: [PATCH 13/51] - fixed buffer size checks for raw textures. + +--- + src/common/textures/formats/rawpagetexture.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/common/textures/formats/rawpagetexture.cpp b/src/common/textures/formats/rawpagetexture.cpp +index 1ee29e13d..8f1a357b2 100644 +--- a/src/common/textures/formats/rawpagetexture.cpp ++++ b/src/common/textures/formats/rawpagetexture.cpp +@@ -94,7 +94,7 @@ bool CheckIfRaw(FileReader & data, int desiredsize) + { + gapAtStart = false; + } +- else if (ofs >= 64000-1) // Need one byte for an empty column ++ else if (ofs >= desiredsize-1) // Need one byte for an empty column + { + return true; + } +@@ -102,7 +102,7 @@ bool CheckIfRaw(FileReader & data, int desiredsize) + { + // Ensure this column does not extend beyond the end of the patch + const uint8_t *foo2 = (const uint8_t *)foo; +- while (ofs < 64000) ++ while (ofs < desiredsize) + { + if (foo2[ofs] == 255) + { +@@ -110,7 +110,7 @@ bool CheckIfRaw(FileReader & data, int desiredsize) + } + ofs += foo2[ofs+1] + 4; + } +- if (ofs >= 64000) ++ if (ofs >= desiredsize) + { + return true; + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0014-Impel-people-to-include-demo-mods-in-bug-reports.patch b/games-fps/gzdoom/files/0014-Impel-people-to-include-demo-mods-in-bug-reports.patch new file mode 100644 index 0000000..34a3884 --- /dev/null +++ b/games-fps/gzdoom/files/0014-Impel-people-to-include-demo-mods-in-bug-reports.patch @@ -0,0 +1,26 @@ +From f729f2375fa9f18bfd3cc4fcec8523a0a8e8a325 Mon Sep 17 00:00:00 2001 +From: Kevin Caccamo +Date: Wed, 11 Jan 2023 21:43:35 -0500 +Subject: [PATCH 14/51] Impel people to include demo mods in bug reports + +Since small demo mods are the preferred way for GZDoom developers to reproduce bugs +--- + .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml +index d50d02070..7ed0af7ce 100644 +--- a/.github/ISSUE_TEMPLATE/bug_report.yml ++++ b/.github/ISSUE_TEMPLATE/bug_report.yml +@@ -82,7 +82,7 @@ body: + id: description + attributes: + label: A clear and concise description of what the bug is. +- description: Describe what happens, what software were you running? _Include screenshot if possible_ ++ description: Describe what happens, what software were you running? _Include a small mod demonstrating the bug, or a screenshot if possible_ + placeholder: "How & When does this occur?" + validations: + required: true +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0015-Fixed-a-bug-where-static-events-would-fail-to-halt-p.patch b/games-fps/gzdoom/files/0015-Fixed-a-bug-where-static-events-would-fail-to-halt-p.patch new file mode 100644 index 0000000..5932e93 --- /dev/null +++ b/games-fps/gzdoom/files/0015-Fixed-a-bug-where-static-events-would-fail-to-halt-p.patch @@ -0,0 +1,27 @@ +From f49d4b9766930fcd78975cf4f2276a9c40113c47 Mon Sep 17 00:00:00 2001 +From: CandiceJoy +Date: Thu, 12 Jan 2023 03:39:56 -0600 +Subject: [PATCH 15/51] Fixed a bug where static events would fail to halt + propagation. + +Signed-off-by: CandiceJoy +--- + src/events.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/events.cpp b/src/events.cpp +index 315b2d8b8..28caa1c38 100755 +--- a/src/events.cpp ++++ b/src/events.cpp +@@ -511,7 +511,7 @@ bool EventManager::Responder(const event_t* ev) + return true; // event was processed + } + } +- if (ShouldCallStatic(false)) uiProcessorsFound = staticEventManager.Responder(ev); ++ if (ShouldCallStatic(false) && staticEventManager.Responder(ev)) return true; + + return false; + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0016-Fix-MapIterator-X-String-GetValue.patch b/games-fps/gzdoom/files/0016-Fix-MapIterator-X-String-GetValue.patch new file mode 100644 index 0000000..4c0190b --- /dev/null +++ b/games-fps/gzdoom/files/0016-Fix-MapIterator-X-String-GetValue.patch @@ -0,0 +1,31 @@ +From b11754ec21f7b59c27c703fad2beccabc952d945 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Fri, 13 Jan 2023 19:37:20 -0300 +Subject: [PATCH 16/51] Fix MapIterator::GetValue + +--- + src/common/scripting/core/maps.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/common/scripting/core/maps.cpp b/src/common/scripting/core/maps.cpp +index 28fda643e..68eab6d3d 100644 +--- a/src/common/scripting/core/maps.cpp ++++ b/src/common/scripting/core/maps.cpp +@@ -438,10 +438,12 @@ template void MapIteratorSetValue(I * self, expand_types_vm ) \ ++ DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetValue , MapIteratorGetValueString< FMapIterator_I32_Str > ) \ + { \ + PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \ +- ACTION_RETURN_STRING( MapIteratorGetValue(self) ); \ ++ FString out; \ ++ MapIteratorGetValueString(self , out); \ ++ ACTION_RETURN_STRING( out ); \ + } + + #define DEF_MAP_IT_S_S() \ +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0017-Fix-two-different-portable-names.patch b/games-fps/gzdoom/files/0017-Fix-two-different-portable-names.patch new file mode 100644 index 0000000..c00bae5 --- /dev/null +++ b/games-fps/gzdoom/files/0017-Fix-two-different-portable-names.patch @@ -0,0 +1,26 @@ +From d279b71b79de02f684525fa660b85778f2d72e63 Mon Sep 17 00:00:00 2001 +From: Sally Coolatta +Date: Mon, 16 Jan 2023 22:32:59 -0500 +Subject: [PATCH 17/51] Fix two different portable names + +M_GetConfigPath uses GAMENAMELOWERCASE_portable.ini, but IsPortable() checks for GAMENAME_portable.ini. Doesn't have much of an impact on base GZDoom since it's case-insensitive, but can matter for engine forks -- IMO it should just be consistent either way. +--- + src/common/platform/win32/i_specialpaths.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/common/platform/win32/i_specialpaths.cpp b/src/common/platform/win32/i_specialpaths.cpp +index 0b29a28c5..3bfee00ea 100644 +--- a/src/common/platform/win32/i_specialpaths.cpp ++++ b/src/common/platform/win32/i_specialpaths.cpp +@@ -90,7 +90,7 @@ bool IsPortable() + } + + // A portable INI means that this storage location should also be portable if the file can be written to. +- FStringf path("%s" GAMENAME "_portable.ini", progdir.GetChars()); ++ FStringf path("%s" GAMENAMELOWERCASE "_portable.ini", progdir.GetChars()); + if (FileExists(path)) + { + file = CreateFile(path.WideString().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0018-indicate-in-the-startup-window-title-when-GZDoom-is-.patch b/games-fps/gzdoom/files/0018-indicate-in-the-startup-window-title-when-GZDoom-is-.patch new file mode 100644 index 0000000..bdc30e2 --- /dev/null +++ b/games-fps/gzdoom/files/0018-indicate-in-the-startup-window-title-when-GZDoom-is-.patch @@ -0,0 +1,40 @@ +From f759dd3d5cb849f713314769c56d36f33375f969 Mon Sep 17 00:00:00 2001 +From: Rachael Alexanderson +Date: Tue, 17 Jan 2023 02:35:42 -0500 +Subject: [PATCH 18/51] - indicate in the startup window title when GZDoom is + compiled for ARM64 Windows + +--- + src/common/platform/win32/i_main.cpp | 2 ++ + src/common/platform/win32/i_mainwindow.cpp | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp +index f153a1dac..c28a3ff4b 100644 +--- a/src/common/platform/win32/i_main.cpp ++++ b/src/common/platform/win32/i_main.cpp +@@ -85,6 +85,8 @@ + // The main window's title. + #ifdef _M_X64 + #define X64 " 64-bit" ++#elif _M_ARM64 ++#define X64 " ARM-64" + #else + #define X64 "" + #endif +diff --git a/src/common/platform/win32/i_mainwindow.cpp b/src/common/platform/win32/i_mainwindow.cpp +index 3395ec430..5b246e457 100644 +--- a/src/common/platform/win32/i_mainwindow.cpp ++++ b/src/common/platform/win32/i_mainwindow.cpp +@@ -17,6 +17,8 @@ + + #ifdef _M_X64 + #define X64 " 64-bit" ++#elif _M_ARM64 ++#define X64 " ARM-64" + #else + #define X64 "" + #endif +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0019-alt-HUD-use-NewSmallFont-for-drawing-player-s-coordi.patch b/games-fps/gzdoom/files/0019-alt-HUD-use-NewSmallFont-for-drawing-player-s-coordi.patch new file mode 100644 index 0000000..433c06e --- /dev/null +++ b/games-fps/gzdoom/files/0019-alt-HUD-use-NewSmallFont-for-drawing-player-s-coordi.patch @@ -0,0 +1,76 @@ +From 5420cc2a601b15a132bacbc245eb231a630316cc Mon Sep 17 00:00:00 2001 +From: Blue Shadow +Date: Wed, 18 Jan 2023 06:59:11 +0300 +Subject: [PATCH 19/51] - alt HUD: use `NewSmallFont` for drawing player's + coordinates if `ui_generic` is enabled + +--- + wadsrc/static/zscript/ui/statusbar/alt_hud.zs | 22 ++++++++++--------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs +index 8054e3d07..69939da27 100644 +--- a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs ++++ b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs +@@ -718,9 +718,10 @@ class AltHud ui + // + //--------------------------------------------------------------------------- + +- void DrawCoordinateEntry(int xpos, int ypos, String coordstr) ++ void DrawCoordinateEntry(int xpos, int ypos, String coordstr, Font fnt = nullptr) + { +- screen.DrawText(SmallFont, hudcolor_xyco, xpos, ypos, coordstr, ++ if (fnt == nullptr) fnt = SmallFont; ++ screen.DrawText(fnt, hudcolor_xyco, xpos, ypos, coordstr, + DTA_KeepRatio, true, + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight); + } +@@ -729,7 +730,8 @@ class AltHud ui + { + Vector3 pos; + String coordstr; +- int h = SmallFont.GetHeight(); ++ let fnt = generic_ui ? NewSmallFont : SmallFont; ++ int h = fnt.GetHeight(); + let mo = CPlayer.mo; + + if (!map_point_coordinates || !automapactive) +@@ -742,7 +744,7 @@ class AltHud ui + pos.z = Level.PointInSector(pos.xy).floorplane.ZatPoint(pos.xy); + } + +- int xpos = hudwidth - SmallFont.StringWidth("X: -00000")-6; ++ int xpos = hudwidth - fnt.StringWidth("X: -00000")-6; + int ypos = 18; + + if (withmapname) +@@ -761,20 +763,20 @@ class AltHud ui + ypos += 2 * hh + h; + } + +- DrawCoordinateEntry(xpos, ypos, String.Format("X: %.0f", pos.X)); ++ DrawCoordinateEntry(xpos, ypos, String.Format("X: %.0f", pos.X), fnt); + ypos += h; +- DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", pos.Y)); ++ DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", pos.Y), fnt); + ypos += h; +- DrawCoordinateEntry(xpos, ypos, String.Format("Z: %.0f", pos.Z)); ++ DrawCoordinateEntry(xpos, ypos, String.Format("Z: %.0f", pos.Z), fnt); + ypos += h; + + if (hud_showangles) + { +- DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", Actor.Normalize180(mo.Angle))); ++ DrawCoordinateEntry(xpos, ypos, String.Format("Y: %.0f", Actor.Normalize180(mo.Angle)), fnt); + ypos += h; +- DrawCoordinateEntry(xpos, ypos, String.Format("P: %.0f", Actor.Normalize180(mo.Pitch))); ++ DrawCoordinateEntry(xpos, ypos, String.Format("P: %.0f", Actor.Normalize180(mo.Pitch)), fnt); + ypos += h; +- DrawCoordinateEntry(xpos, ypos, String.Format("R: %.0f", Actor.Normalize180(mo.Roll))); ++ DrawCoordinateEntry(xpos, ypos, String.Format("R: %.0f", Actor.Normalize180(mo.Roll)), fnt); + } + } + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0020-new-characters-for-Doom-s-SmallFont-and-BigFont.patch b/games-fps/gzdoom/files/0020-new-characters-for-Doom-s-SmallFont-and-BigFont.patch new file mode 100644 index 0000000..c7dc66f --- /dev/null +++ b/games-fps/gzdoom/files/0020-new-characters-for-Doom-s-SmallFont-and-BigFont.patch @@ -0,0 +1,502 @@ +From fac072dbfe7a3d7184c0daa9ec921eae7c77b98a Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Fri, 20 Jan 2023 19:43:18 +0100 +Subject: [PATCH 20/51] - new characters for Doom's SmallFont and BigFont. + +This covers all somewhat relevant languages using the Latin alphabet for these two fonts. +--- + .../static/filter/doom.id/fonts/bigfont/0100.lmp | Bin 0 -> 320 bytes + .../static/filter/doom.id/fonts/bigfont/010A.lmp | Bin 0 -> 310 bytes + .../static/filter/doom.id/fonts/bigfont/0112.lmp | Bin 0 -> 321 bytes + .../static/filter/doom.id/fonts/bigfont/0116.lmp | Bin 0 -> 299 bytes + .../static/filter/doom.id/fonts/bigfont/011E.lmp | Bin 0 -> 411 bytes + .../static/filter/doom.id/fonts/bigfont/0120.lmp | Bin 0 -> 371 bytes + .../static/filter/doom.id/fonts/bigfont/0122.lmp | Bin 0 -> 365 bytes + .../static/filter/doom.id/fonts/bigfont/0126.lmp | Bin 0 -> 149 bytes + .../static/filter/doom.id/fonts/bigfont/012A.lmp | Bin 0 -> 200 bytes + .../static/filter/doom.id/fonts/bigfont/0136.lmp | Bin 0 -> 347 bytes + .../static/filter/doom.id/fonts/bigfont/013B.lmp | Bin 0 -> 209 bytes + .../static/filter/doom.id/fonts/bigfont/013D.lmp | Bin 0 -> 219 bytes + .../static/filter/doom.id/fonts/bigfont/0154.lmp | Bin 0 -> 331 bytes + .../static/filter/doom.id/fonts/bigfont/016A.lmp | Bin 0 -> 350 bytes + .../static/filter/doom.id/fonts/bigfont/0172.lmp | Bin 0 -> 320 bytes + .../static/filter/doom.id/fonts/bigfont/0174.lmp | Bin 0 -> 356 bytes + .../static/filter/doom.id/fonts/bigfont/0176.lmp | Bin 0 -> 302 bytes + .../static/filter/doom.id/fonts/bigfont/1E80.lmp | Bin 0 -> 359 bytes + .../static/filter/doom.id/fonts/bigfont/1E82.lmp | Bin 0 -> 359 bytes + .../static/filter/doom.id/fonts/bigfont/1EF2.lmp | Bin 0 -> 307 bytes + .../filter/doom.id/fonts/defsmallfont/0122.png | Bin 0 -> 1162 bytes + .../filter/doom.id/fonts/defsmallfont/012E.png | Bin 0 -> 1140 bytes + .../filter/doom.id/fonts/defsmallfont/0136.png | Bin 0 -> 1164 bytes + .../filter/doom.id/fonts/defsmallfont/013B.png | Bin 0 -> 1158 bytes + .../filter/doom.id/fonts/defsmallfont/013D.png | Bin 0 -> 1152 bytes + .../filter/doom.id/fonts/defsmallfont/0172.png | Bin 0 -> 1163 bytes + .../filter/doom.id/fonts/defsmallfont/040D.png | Bin 0 -> 1178 bytes + 27 files changed, 0 insertions(+), 0 deletions(-) + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0100.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/010A.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0112.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0116.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/011E.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0120.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0122.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0126.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/012A.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0136.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/013B.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/013D.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0154.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/016A.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0172.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0174.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/0176.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E80.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E82.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/bigfont/1EF2.lmp + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.png + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0100.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0100.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..ec5879e8597a1387e674e77db87a5f14b63e9207 +GIT binary patch +literal 320 +zcmYL@%MHRX5JU|TzW~aSB4~pnmkb}|j! +zfzacQP|b9Q%5J!6>9S8)X)h|q*znF-hgIx)8bxef5syAby-d!smBALj%9@kWqWDge +S!0?~LmJv%MkLb75p^<**nqFZ5 + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0112.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0112.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..593e1a6d9841a459c93ae1d69769e1184d5187c0 +GIT binary patch +literal 321 +zcmY+9%?-jZ424}NKjP5d8G;$Oax775S*>Ih%Ecov1VboO_Y&S#i|hZIPv*aV;zSBhxc{05-K}xc~qF + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0116.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0116.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..a1d8302f127d2b1a79371be1e3668161142c870e +GIT binary patch +literal 299 +zcmX|*%?-jZ3`SkGh##T$&NN&(mMFEXRm4QqK}N{$ERZp>MyKc!-N1e1IJA(1 +z$Fkm6camP++BsLaE#Cm|aDXG6;R0Xq4L?v!oO^=}lyHC(EFN_@{cKLmDJ4Sxv{dbO +ztw>XKq{TC$Tu)2x9>}#=aUsT-QqFmA@>I3H>e6wKH@Z*L=}~=P5QV}QVw=ras5a&_ +zRGS)1oiIsV!YFzf#WGSsa#tA`dO5R(TJih$u2q|{lPH5hkJ}`H*Ua-Fgkh<1dP?e> +Z<-Py6FHU4YyCk+ZooppLV|V-Qe*t??el-99 + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0120.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0120.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..b1e8d26071e682cdd8bebd2a602fd467c031e3f3 +GIT binary patch +literal 371 +zcmYL^;cdb&5JnAZ2+$&6h7Q3BNd03sN>P*(mfZ*>OC6yrbcJrwCAtJl@H>4+onYzZ +z?3XWh&cu7LQ2zU#*^>hCw~B}jToD#=;Li*q%d*3TgvEn^9oT{`*o95lghgBdd*8(D4Sa;W +zym>R(xt+5*fWS9g;0iam!vmi1f?rt8ocn}5d_f0`MJ_eY8_pDCbrWbZi6#~5MxT|Tm>C)(lz{;K&tZ6aP}$Z?cCmq++u5(CCE8c@l-{xS=vby#raX3 +zQpOS{thZcQSU%dO?@V(padsLMwagJ>O!FfD-KR&ZlWj7GOC8$GQ&erKSvx34xg>XIJ!=GdMMTkf)-T)Rkct)` +TSufRBLf`D)4IaRk)90Z#7>hp0 + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0136.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0136.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..9fb95b3fb50b2665286fdc0e948d80d333d21368 +GIT binary patch +literal 347 +zcmY+8!EM7Z3`G?ubsD!uGelMxO9}!(3`868Gcw9t#uIphRt9ONAtbn}t+((H9>D#q-FmB7X+$eLNGe73X-J_1 +zIg%4GawB*0AWt%r7kQJk#b2I!K(A(|BDC8*idwCu)VOy*E~-*F_BE!KHw$CGh&E5d +huT=5`u*|y+aF%>&`x+SA$Ga76b~CU9O8asN`3LyBK@ + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0154.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0154.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..80e105523b49f94e2ea0a7e7cea630d6db60fab4 +GIT binary patch +literal 331 +zcmY+9!41MN3`JeqB1A#-$_k9YnE@IiD~gf|^}@jmbOlym1~y;>R$vJ>DBp=Hgr(Og +zKi~fDj#?tB=!7qWD;U8I+`$7p!3(^>2doOBJve|Ps5bIflL~PV2{Cwo5lKQ9MGUiZ +zcu0c5OXnT)ET{uQZYj5z*{KDp*0flQxGZT$(ctQTcS7jd_sMTHlv)^iga!pII)ut} +s>V_u7Xst080eK;IY*A)jXfW1cKdYNgHSz`zZ;0uimU&WBr-3kh0lE@sx&QzG + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/016A.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/016A.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..195a8da668b386ab88937a2789b6a72303e5e186 +GIT binary patch +literal 350 +zcmY+A%?$z}5QW*S2Y;e#1NLAIo;Tu!aq^P>8jH}9_vg?h4eQ|0!@0!w +r6&w*mz6;(nr?aptPd+-?An_$E2D*T0n*rv=?Ntm&i6T+riJmy4_g(4T} +gb8vnOhxJ8;ZH;{(#zY7s)?kJ1Ob^@;0mrF__u^`ggXcgrNT|%3eMmT4&e|E;SlP3rGgDS{qgjD +zbJuR&);Z_h2~PrNZ~<3v19$KMPw)b7u&bQgg9A8%2>eq2&d0A*6Eh2^)Tn;^TD2x3 +zj)ABQf)L;oVz9(?^XrGYu3MPNR5hwD=BUOH1gi2-tU5O*EEaQc6jW#CaN*BI8XR`8 +ziPjakzRQx$*$CWgBVsAdcn^rwA!NJf7H_jiKhZ?$+L9$_=@a-`X)=yTw#N8pd;x~s +BZ*~9x + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0176.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/0176.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..4443deed608f0593a722189f4c9f6f02e72bde0d +GIT binary patch +literal 302 +zcmYL^!3}~y6huF=Dta&^p1oR&$K8<4&t^#oc>4z%um`)a3ahXSd+>lW5aK3}48zX+ +zPc5~GIJw~IK>}BB19$KMPw)b7@Bv>?6(UD)0%zb#;~AYZivz_PqU)(PW?nO8S>cWk +zG4W+}zzwse389_BHWo~0v&|m9=G^rIy9Bm2X4@Uo38!VAZq&c4+QDT-3wN$anp2|9 +eVVDv$re)Z)Owjo|mke=g;O2f-=n70PfA<5)qgu}Z + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E80.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E80.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..9a4901d0b73afabd28b2b6551fcc881cff727258 +GIT binary patch +literal 359 +zcmY+9(QU#o5QZIM3Zi}Bg%!F2EASeu$hCZxl_&z~CSV0tU<{UEi4M^X((kMywI_YC +z{O7;>&s(>3&Uts>8{rHWxWWzY@PIG)hPH8T2k)?l1AKtr=%1SXt7^(QOHOG}o&B3? +z7h}wQh;jTCB8HqoAD)gnA#`0g;c#ue`i5h@qP-76Okb+TPsEjplBJpvkEy7>n8;WY +z8;_Hgs + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E82.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1E82.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..c4fed22fbb6e09b0289576d8a329ade067adc48a +GIT binary patch +literal 359 +zcmY+9!A%1(5JkO-At-Rjg%)Um7IIyz)nIv$wX0PkO$D?-3)GMvQUp!V1X|u$i3B4( +zOaA`zXS@r$5JC)lPJtu5!v}oA3C{2Z-|z#ET?kL`410KmxV1mE#Cx+`O3{+@Xtu-$ +zvtC5XkVK}7AQ(zcL%KRzLhAc|#<5=c^=?DskdmUT)@E2YE@@FWb(^b + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1EF2.lmp b/wadsrc_extra/static/filter/doom.id/fonts/bigfont/1EF2.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..f1c3ff3dc03cb69c7356da5729a546eb8abf4c2b +GIT binary patch +literal 307 +zcmYL^K@NgI3`GkJ5H%(&UAy%nE*Z(BX$C{UT^HQJV|WZt;U&C;C(vIe#7Q3cY5RXm +zLk$r*I^){{0XHy%J9vO6c!4+gfGi{0g9A8%6L5vv`#Pr@CKDyZFq*1VTaG3vO}QEs +zA7m-Pz*p6Br`mPi_e%~&;lBtP)fNqoaTq7d&1_y&>kTplueX#O!Tc{W4=5J7WhK9G +f6tSZ1@f>8`W4CxtJ-gJ0#cSucNnxQk=lY93Fz;H& + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.png +new file mode 100644 +index 0000000000000000000000000000000000000000..14f48f25d79dfd10510267cf35bbc387692b2de8 +GIT binary patch +literal 1162 +zcmd^-v8&`%6vmIPko9FBSx6BuYJ?QC5G6&5xC9Mr-jaRBeOX=>BBqEKaEidDh!7!2 +z-~}0ETmnupMU)g%q!@IH6eCVC$|55S>=c6x7-WPMr;4;F?md@#59fC- +z_xrxOcV-?Ry>bKq$ESBr&dGk2te3A|A@S{p-@OWO1@3)t|28=a9L+J5Wm$;G^E}J4 +zG)+?!C98rcF`Pg#9N3y>KH<2SWkZJP(zH)e9z{76WdoQ11_182_+*Xk0@pKK +zHMpp8UgB(kP5yM89!Bx547Y<|)Av@nv&`&yYBjMrj*L;Lmw{IJYR^?NM^0=hG&{Z_ +zI=Wz~ye@N!#7ZJ_I2?An-FCZe+jhNPFPF>3Vlki3r_*WEG~@BOuIs9*hQr}tFzEOD +zd7fukmLy3OMPV2QLEw3w>$-t5>2yRsj%y?AF +zlT;`@wr5bW1Vn3WTb#|XEHO>d_fgkT5D?%1@C0B3umqR`GypX~3D5_~0AheHfCoS% +zBYN$2xLDwLj75QQjE;kW +zG21S)@#&>YJ+fhH!o+y~PTU|ihy`MZXd;S;Q0q{sFp!}q5_5J8nO8+t=4sO6xs@~k +z89)T!0LUd^W#G=jl$7EMRuz;HgmoA`{`>fSfEVDi^D~E}{@3Gs?H`GJ)y>nBTlYWz +zt8>7_rtqyGCy9w@$=|ndgrHa-nskNM@QfO{^0Sa@fW{Ymlwsg +dm(G8E{jJW8?Vq1~d5b{c^!C}w5AS_^@h=+(ZxjFk + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.png +new file mode 100644 +index 0000000000000000000000000000000000000000..d637b362bf5cf27cbf72ae8f146a164cf6390255 +GIT binary patch +literal 1140 +zcmd^7zpJEH6h7f?aPxeNkbxCqVZdSv3kwSiLnQGn=3#g)>jMi3282vuVPS{?2|_G} +zFolK16c!d!SQs({AyW*jfh{bCFvS!TVll-oOfkh28}f=kPVR30j9kwB!R4IqJDl(P +z;pwgM=<31TlDxxfD3r~`P~yl5wG5DB1);@B5wWt{tbftfgVp +znzm5YQkLhEl#Aj_5Hg-mIWA_|Xfz5KW``iKQiP=U*6Y7gVD}6Qhl&K@9wiH`pV2nLour=OP +zI89<@aU=@N`FuVekB7ry7>3<$x7lp^zVEtjwOX}p+cZsG*Hu-`=kuZ{X0utAWoeqm +zaU6zW5Cp#OyRPdvj%8VfVd%Q9s;Z(Wk|d4CV?hvN48!wea`3#Z<93$4G|WoV3q{K$ +zB@!iH7~34Lv#iXF1e#{4uFhB0bU9D!Jg%l;nFdAT&muPqoW!?c&kP-XVr!nMIJ#_W +zQkD66Y-fQPd)ma7T|=}~L6^BC^~1=S1eWU?wxb%BtQn%BjS-{M;Oy7>i&9!9eCdv+ +zIu(gPw8mk;^%~0(lLS2vH4S+l0nPv~0rmhJfDWJqr~yiV89)jU0Zaf~03sRD>v+Vz +z$ELwN$0$PEMnxemA}}Nf48b4(q&fo#0PHusrvdkC>`QDDT)3F4m~yWp_7pOQ3A6X; +zjYGY#U}eBkf7>VS5nIF@F+emB1w^Pds1zt9m +z30UcPG%+EixP@&6We7nX1mE1>lB9Rw>u0z2e`Ieu{C}>?`JW$=Q3*HKpWJ=>hyOeC +z;Ogq{RrsJNe|`1U)i2MVe|(Ys^Vb(2zW)$@zIn{t<=?#`>2UMp_WGw!zx@7Rnwn^! + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.png +new file mode 100644 +index 0000000000000000000000000000000000000000..ab1bc61c19152955ac127820f689f97edaca41ae +GIT binary patch +literal 1164 +zcmd^-v8(G;9LIlhhg@#BbjT1iV3dFzqC^RjAw#&Pmv~>~=DwGw0fR&cSS3S-2oW*_ +z3|OQ?h9X5WWatni+*dF|hoT)GTBKlyf&~jkcw&VP9o}%=exCRK4G-u14(I&%eSU}Y +z{eFFOZJeLIbOr$DSMT;7ko}abv(pn2e|+)yJ-`Xvy!Y^u9C?;zJCtdfh{$mq!!R^W +zQxqjBydZX1p6ak*siGkZn#kd7c30O=CzHc?ywCG?FxVx@CW=-;u=M?f>&_jgv8<_K +zRGKzX)k2oXl9Y?$P!KYnPdP4T*@$6+PNz@P9!0qnWmA*|U;yX&#xI)*>;R$f!eo5@?05=AJTepG5OS(afKx~{9Lswj#iN!@N&5QG@R@YwISp0{?~g=J3-v()sF +zqGgg2iIOjLZI0JjR_-tYO|#UZ%4g+ZI!>!RE(c+e2BX9uMs5~3iEqW889I93);v>j +zblKLVGV}A;&H^*`w7xC7hG?mRE^|rhhmq3{EY~+|M>Q;2Gekw}B1VUuvz_aY3u&70 +zh06?dDiVQcjk_Jr=U5b&Bka0GY)umxBFEC3pS3ZMWO0;B*DKp(&bAd(Ti +z_Iq3|v92-CF^bT(QBjDC2!>38Aq)Z_)fqqlU_a}7*x`1L%L1DOCobkHrrgtrJ%pXM +z-`RTf%Ap=xFf(APKYu4~5gWuDF+emB1w^PcC>0n9Z(>49aSiJdiV%V-2!8$R{2ssy@cDylo235N<5vA!BwwXo^)4QM@%tOA +z`)BaVY473({OsO$|Li}yegDIouP)Djdi&>>-~8a!Zz=YZ*Z%mkr(FEU<6vj`jklOe)?k#fUS(@!prfDJ~$8ik9 +z&@@d^l%(*2*kgIB$AYDbhAe0zhl|CDZybe!6< +z=7v#e+Ei5wS)NEzE{Y>T$ap^GxR_-lh6#GT0Zn@p+E8d9H-H~2zFzCJ95{Vy-KYnG3&^fh59tm3SZ4VW$4JMEyb1?7=2F{ +zY>hV+PLo(!WJIBNJRbM^{cgAGx^A=CtX8YGZJVZ9EEaWL&t|i#s>-sQOeW*;cr+Si +zS(c`09LHf820`HazU#V<<5-qu7>2Ivs;VlAB1uxe-xmZS#xOh%20PDNJ8omybHgk( +zeXMAiq(q|R3w@j8b(WQTj6l;Y)l~VS9L^_cmB-~UEYe_{_@l_p0w?jU*fT>%AK02_ +zDvmDOnp9?f9@|-9#-28?W!DfbRnTQFN&PT#27%@JhV7_^C2NMLXnn-!&^g+ys7w@AL~&9l>+cR%^# +z-WNBn!S$D4_zRmyU;X~ZryqX&=TA?szxc~IP +zijq}9lo(E+7!GVrG8Ivmcw8=Dx9zL>{4|>#%koeZLz?d5coT-}Am}}B<+`11FHE!1 +z^|_{1iZYYsQj#X3my{8FaYp$z?VB5*0@{Yw!?LU +zeTAzjcKPczJ`2jxJa# +zugjbwv69G~&*$UucsLw}Vc6|!TrRt=YumPIn!2uMv)ObyolGWqo@ZH> +zBuNxSVHgHM;CY_wy0&ebrfC?4rfI6G%CbBfjYLsQFpAFO@xk}EuGibn!nA7Ln5ud% +ztFa^p;>h6zgX0v26=|BI`lejg#bTBi?A0fu4!QHQnr#KW@zI`4%W8VAm +z)8Bv1HlKVHNI%`a!TY~GV;=wgg5de>2N(Y+PrkngP~3hTJ$~U5+W=hOzq$J5v#-AU +E5Bp+lwg3PC + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.png +new file mode 100644 +index 0000000000000000000000000000000000000000..411693d82027f226fdd98706121a6d056f37e040 +GIT binary patch +literal 1163 +zcmd^-!K>p`6vmH^ka1$kB8z}gB1Ei^MT8)c$s)X$_lVEP%P<*?kVV7@1+&N^N`x!| +zW>KU_gbq{*l0_F;l(CBlT~w?xi;9IQSg>G_E=KI4V1>6BMC5p#f5XeY=W_4i{LbZm +z-zT>&&CZQyZva5&;`OuJWWP?<)7P(&_}ZsmJ_m3OZoPTuoE!y?<`~MdEJWmao@H5@ +zrYVY&RY8;(PM{bLY)vv1QI~j}%^poASL5+vG};%%uHSFdbQ8y`FkA+~!t>^?+t~Kh +zG;3WSYg(x&BUvsaX&{QZAY?qBa9qr?A;a`&+NUUwq8y5{0Zae`01rESxWRUbn>nr< +zT-LZKaX!Q*e>6#t<9J_&yJ4^$cA0F{E4nGEdKWQ1wC;9p+%M&6 +zDwH1EH>g+wqBXWH&gWQ`n5O9asOu;Q2yg^=2(SfM0W1I-fEu6#7yx7dF+dN%10a$S +zz4m)tE^#u!qQE#t$3aykE+QB*35GBTfK=xIA%OE=-$RSrIW9|VQXG3&XqfR=F?WcV +zU60xN^vb2~+b}a>YCL`?ZV?;A0x?815k*9(b*NMr%Fq{yIlG3;t0F7&G->hJN*aI+ +zAOdgzv2!}T_Rs~^WyB}&PTtz +z`os5~?_PN3sT2SFkLO?M{?*(&x%-|!?tJ?s^Y-8Ga(An%arof<)31Mh`Ncnf{N}Tt +d{yF{P=I3pf{qX0P-XavZIKMpm>hztD{{`a~asU7T + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.png +new file mode 100644 +index 0000000000000000000000000000000000000000..5cd59fa7c3835f3f0db5b661c089afc0a32f32c1 +GIT binary patch +literal 1178 +zcmd^7L963b6h1PGJYIMNsTjsAB4nhC2w4OP7$Gy}J>xTvm&arv3_&7hkwwJ7M94tE +zfLRnNnni^!GLS_VSrjc8q+r1=#z&N*U35{fV!;uMyhRtY7wn3%R@;jM6oXjInQStm#}Qy>4Xdu(6mQUE=AcCWdRrf +zIsjg6@yQA|Ev{y`Y_P3yUgB(kP5x}0?nm*i47US+-FKI{y~wP2YBsSkj`UHemA+bd +zO3#rqTS_c3G`gNH*cxvtoF=id*bxP0zu)h6yX|(n*=$y;)nc(|+jc&mPp8wSX~yGm +zUDs7r4Tr0mio!7TecyFm$8jvnG7Ll4byZarMUf<_+wBU1kYE(; +zgJA1(ITJ9e~2t;e#Y;ZQivcxn+&qGZ^o=1Q^z!QKqzye?n&;Zl` +zB|sk_1Bd|v02hErM)cb4ux)WX#-hMDM%zY3Aub{`WDy#|K?q294iEy^*K@BnxSnBK +zVw2*?#X`l5dm6J>5wi`LwMQ=;>ahh=119?Ocj6kcK`anML<3Pkgj$12fq?`)fta(a +zOPnHfB#tH{o?A%;kN^Y#7JwuHD;;+xrlb{@u&khrAgsgi*T0V519$;GxqEJt(*HWX +zR{s{sSG{q1eCOW7-(LIa=NIACgUgFgPyTuT{_ECPkN)`a)M<1PipWnK9)T&>;ObFog +Date: Fri, 20 Jan 2023 21:03:21 +0100 +Subject: [PATCH 21/51] - 4 non-letter characters for Chex. + +--- + .../filter/game-chex/fonts/defsmallfont/2012.lmp | Bin 0 -> 104 bytes + .../filter/game-chex/fonts/defsmallfont/2012.png | Bin 0 -> 897 bytes + .../filter/game-chex/fonts/defsmallfont/2013.lmp | Bin 0 -> 116 bytes + .../filter/game-chex/fonts/defsmallfont/2026.lmp | Bin 0 -> 128 bytes + 4 files changed, 0 insertions(+), 0 deletions(-) + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.png + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2013.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2026.lmp + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..c9b6cf5af5440c069fc7fd70d22da78d2a2c56a8 +GIT binary patch +literal 104 +vcmd;JU}j)o`1fA}NE!gK1rR#`u?G+b0C5BmCjc=6b1ew`2hoKj(ja{R!ciZ2 + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.png b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.png +new file mode 100644 +index 0000000000000000000000000000000000000000..4ffc36ccaceed43e8d9aa10ace07100e8e8eac9b +GIT binary patch +literal 897 +zcmW+!F{q?w5T4`;UrrttLJYC6u-L-F5DNVL-?h7F#UD;tGp}Y_Y{cEVj6WEw4wlVlr3LlE?y +zw{hLhwpXUv==xIADn(hyaw$nOQ7i-@=lPW55|)h^CZuVfqCARnD9Q#f0Sq$V`G~Lf +zI1aeq;I6}=!M?)H9J}I8n_ZU4sfv#C;4t%cg|p4=KC`;SY-3{?=~bYWzB+Z4+>ujT +zip+^`h>k8;DzD3&BC(RlTrQW>>2y3E$8p^6_uK7u7>2&@*XwoHb#2==O;gwPVzHRd +z=d;q3o~{;oQ>OJauJUM}1+&B}A~y@{)VE^S +z2p!$GRM$`(U9O9uOr0XKQeO`p#WN*a6AgvW@*qy!FtWYCbX?7}72T9neS(;rNB6KX +zURLrd6Dp6L8dM_P`2fceHyf-f%rf+S)O8dD1h@da0yqF{0eXNApaG}=W&k-r0uTat +z0OVxkUZ)cd1GX)eB_;_v4yr0~5s@K}$Pf)8K&lIX2*A1Pdmizy!J)z~!=;C%hB^N_ +z;m$F044H#ZZ(Zu84Qmrt#@jjZfY>3Hh!LWRC?Z0mL#@JGhN(!*IWc5j6S=q(UY4$9)9`5|D%0m`Tzg` + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2013.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2013.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..b3bf1609d834f80fd5163627ee672735563d6ba4 +GIT binary patch +literal 116 +ycmd;NU}j)o`1fB2NSXk#4G_Bku@4Z30C5ZurvPyd5Hm2>g1~^l5LW;(19L41{0GscP`VgOlOqlQ +DdNL=O + +literal 0 +HcmV?d00001 + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0022-Fixed-global-TerrainDef-array-not-being-exported-cor.patch b/games-fps/gzdoom/files/0022-Fixed-global-TerrainDef-array-not-being-exported-cor.patch new file mode 100644 index 0000000..4d2b923 --- /dev/null +++ b/games-fps/gzdoom/files/0022-Fixed-global-TerrainDef-array-not-being-exported-cor.patch @@ -0,0 +1,28 @@ +From a68f62ba53f654033c00f0478db7d30aa3856d53 Mon Sep 17 00:00:00 2001 +From: Boondorl <59555366+Boondorl@users.noreply.github.com> +Date: Fri, 20 Jan 2023 16:09:20 -0500 +Subject: [PATCH 22/51] Fixed global TerrainDef array not being exported + correctly + +--- + src/scripting/thingdef_data.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp +index 890637a37..acc039c5a 100644 +--- a/src/scripting/thingdef_data.cpp ++++ b/src/scripting/thingdef_data.cpp +@@ -720,6 +720,10 @@ void InitThingdef() + teamstruct->Size = sizeof(FTeam); + teamstruct->Align = alignof(FTeam); + ++ auto terraindefstruct = NewStruct("TerrainDef", nullptr, true); ++ terraindefstruct->Size = sizeof(FTerrainDef); ++ terraindefstruct->Align = alignof(FTerrainDef); ++ + PStruct *pstruct = NewStruct("PlayerInfo", nullptr, true); + pstruct->Size = sizeof(player_t); + pstruct->Align = alignof(player_t); +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0023-convert-characters-to-Doom-patch-format.patch b/games-fps/gzdoom/files/0023-convert-characters-to-Doom-patch-format.patch new file mode 100644 index 0000000..6a719af --- /dev/null +++ b/games-fps/gzdoom/files/0023-convert-characters-to-Doom-patch-format.patch @@ -0,0 +1,340 @@ +From 0489ca2af443075419606ce3b0c8cd460d1feacb Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Fri, 20 Jan 2023 23:23:50 +0100 +Subject: [PATCH 23/51] - convert characters to Doom patch format. + +--- + .../filter/doom.id/fonts/defsmallfont/0122.lmp | Bin 0 -> 136 bytes + .../filter/doom.id/fonts/defsmallfont/0122.png | Bin 1162 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/012E.lmp | Bin 0 -> 90 bytes + .../filter/doom.id/fonts/defsmallfont/012E.png | Bin 1140 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/0136.lmp | Bin 0 -> 149 bytes + .../filter/doom.id/fonts/defsmallfont/0136.png | Bin 1164 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/013B.lmp | Bin 0 -> 125 bytes + .../filter/doom.id/fonts/defsmallfont/013B.png | Bin 1158 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/013D.lmp | Bin 0 -> 131 bytes + .../filter/doom.id/fonts/defsmallfont/013D.png | Bin 1152 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/0172.lmp | Bin 0 -> 142 bytes + .../filter/doom.id/fonts/defsmallfont/0172.png | Bin 1163 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/040D.lmp | Bin 137 -> 146 bytes + .../filter/doom.id/fonts/defsmallfont/040D.png | Bin 1178 -> 0 bytes + .../filter/doom.id/fonts/defsmallfont/0419.lmp | Bin 138 -> 152 bytes + .../game-chex/fonts/defsmallfont/0400.lmp | Bin 0 -> 142 bytes + .../game-chex/fonts/defsmallfont/2012.png | Bin 897 -> 0 bytes + 17 files changed, 0 insertions(+), 0 deletions(-) + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.lmp + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.lmp + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.lmp + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.lmp + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.lmp + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.png + create mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.lmp + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.png + delete mode 100644 wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.png + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0400.lmp + delete mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/2012.png + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0122.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..057c1ef0f7ca1076f83eb9ec90081a02999dbcef +GIT binary patch +literal 136 +zcmXYn(FuSs3`CBBqEKaEidDh!7!2 +z-~}0ETmnupMU)g%q!@IH6eCVC$|55S>=c6x7-WPMr;4;F?md@#59fC- +z_xrxOcV-?Ry>bKq$ESBr&dGk2te3A|A@S{p-@OWO1@3)t|28=a9L+J5Wm$;G^E}J4 +zG)+?!C98rcF`Pg#9N3y>KH<2SWkZJP(zH)e9z{76WdoQ11_182_+*Xk0@pKK +zHMpp8UgB(kP5yM89!Bx547Y<|)Av@nv&`&yYBjMrj*L;Lmw{IJYR^?NM^0=hG&{Z_ +zI=Wz~ye@N!#7ZJ_I2?An-FCZe+jhNPFPF>3Vlki3r_*WEG~@BOuIs9*hQr}tFzEOD +zd7fukmLy3OMPV2QLEw3w>$-t5>2yRsj%y?AF +zlT;`@wr5bW1Vn3WTb#|XEHO>d_fgkT5D?%1@C0B3umqR`GypX~3D5_~0AheHfCoS% +zBYN$2xLDwLj75QQjE;kW +zG21S)@#&>YJ+fhH!o+y~PTU|ihy`MZXd;S;Q0q{sFp!}q5_5J8nO8+t=4sO6xs@~k +z89)T!0LUd^W#G=jl$7EMRuz;HgmoA`{`>fSfEVDi^D~E}{@3Gs?H`GJ)y>nBTlYWz +zt8>7_rtqyGCy9w@$=|ndgrHa-nskNM@QfO{^0Sa@fW{Ymlwsg +dm(G8E{jJW8?Vq1~d5b{c^!C}w5AS_^@h=+(ZxjFk + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/012E.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..c4a7effd7e58b66089b904ced7d69a60789ee5ea +GIT binary patch +literal 90 +zcmZQ&;A8*+86egGVlyCi0pcJaW?jMi3282vuVPS{?2|_G} +zFolK16c!d!SQs({AyW*jfh{bCFvS!TVll-oOfkh28}f=kPVR30j9kwB!R4IqJDl(P +z;pwgM=<31TlDxxfD3r~`P~yl5wG5DB1);@B5wWt{tbftfgVp +znzm5YQkLhEl#Aj_5Hg-mIWA_|Xfz5KW``iKQiP=U*6Y7gVD}6Qhl&K@9wiH`pV2nLour=OP +zI89<@aU=@N`FuVekB7ry7>3<$x7lp^zVEtjwOX}p+cZsG*Hu-`=kuZ{X0utAWoeqm +zaU6zW5Cp#OyRPdvj%8VfVd%Q9s;Z(Wk|d4CV?hvN48!wea`3#Z<93$4G|WoV3q{K$ +zB@!iH7~34Lv#iXF1e#{4uFhB0bU9D!Jg%l;nFdAT&muPqoW!?c&kP-XVr!nMIJ#_W +zQkD66Y-fQPd)ma7T|=}~L6^BC^~1=S1eWU?wxb%BtQn%BjS-{M;Oy7>i&9!9eCdv+ +zIu(gPw8mk;^%~0(lLS2vH4S+l0nPv~0rmhJfDWJqr~yiV89)jU0Zaf~03sRD>v+Vz +z$ELwN$0$PEMnxemA}}Nf48b4(q&fo#0PHusrvdkC>`QDDT)3F4m~yWp_7pOQ3A6X; +zjYGY#U}eBkf7>VS5nIF@F+emB1w^Pds1zt9m +z30UcPG%+EixP@&6We7nX1mE1>lB9Rw>u0z2e`Ieu{C}>?`JW$=Q3*HKpWJ=>hyOeC +z;Ogq{RrsJNe|`1U)i2MVe|(Ys^Vb(2zW)$@zIn{t<=?#`>2UMp_WGw!zx@7Rnwn^! + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..ae3589e31da1cd1f373d95e5d85c5ba07e151391 +GIT binary patch +literal 149 +zcmXww-4Q@Q420uvaFux57X_$52P#m34z%OkU^ExIjGg(C>?Ua}nADM;3}hq|naM&{ +wVl{rb=2HUPT3|~t?%KKqwWM;>W?aT}F=6zbUfAj73g7@rHvYQhN~^c}0~$Rg>i_@% + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0136.png +deleted file mode 100644 +index ab1bc61c19152955ac127820f689f97edaca41ae..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 1164 +zcmd^-v8(G;9LIlhhg@#BbjT1iV3dFzqC^RjAw#&Pmv~>~=DwGw0fR&cSS3S-2oW*_ +z3|OQ?h9X5WWatni+*dF|hoT)GTBKlyf&~jkcw&VP9o}%=exCRK4G-u14(I&%eSU}Y +z{eFFOZJeLIbOr$DSMT;7ko}abv(pn2e|+)yJ-`Xvy!Y^u9C?;zJCtdfh{$mq!!R^W +zQxqjBydZX1p6ak*siGkZn#kd7c30O=CzHc?ywCG?FxVx@CW=-;u=M?f>&_jgv8<_K +zRGKzX)k2oXl9Y?$P!KYnPdP4T*@$6+PNz@P9!0qnWmA*|U;yX&#xI)*>;R$f!eo5@?05=AJTepG5OS(afKx~{9Lswj#iN!@N&5QG@R@YwISp0{?~g=J3-v()sF +zqGgg2iIOjLZI0JjR_-tYO|#UZ%4g+ZI!>!RE(c+e2BX9uMs5~3iEqW889I93);v>j +zblKLVGV}A;&H^*`w7xC7hG?mRE^|rhhmq3{EY~+|M>Q;2Gekw}B1VUuvz_aY3u&70 +zh06?dDiVQcjk_Jr=U5b&Bka0GY)umxBFEC3pS3ZMWO0;B*DKp(&bAd(Ti +z_Iq3|v92-CF^bT(QBjDC2!>38Aq)Z_)fqqlU_a}7*x`1L%L1DOCobkHrrgtrJ%pXM +z-`RTf%Ap=xFf(APKYu4~5gWuDF+emB1w^PcC>0n9Z(>49aSiJdiV%V-2!8$R{2ssy@cDylo235N<5vA!BwwXo^)4QM@%tOA +z`)BaVY473({OsO$|Li}yegDIouP)Djdi&>>-~8a!Zz=YZ*Z%mkr(FEJQ3Od@c%)|5|^)GJSczrqNVT0I3OFNC3ozWx3H*SQ~f + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013B.png +deleted file mode 100644 +index f441d09a5fd26b62561c43424e14d19ea20c006b..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 1158 +zcmd^-!K>U<6vj`jklOe)?k#fUS(@!prfDJ~$8ik9 +z&@@d^l%(*2*kgIB$AYDbhAe0zhl|CDZybe!6< +z=7v#e+Ei5wS)NEzE{Y>T$ap^GxR_-lh6#GT0Zn@p+E8d9H-H~2zFzCJ95{Vy-KYnG3&^fh59tm3SZ4VW$4JMEyb1?7=2F{ +zY>hV+PLo(!WJIBNJRbM^{cgAGx^A=CtX8YGZJVZ9EEaWL&t|i#s>-sQOeW*;cr+Si +zS(c`09LHf820`HazU#V<<5-qu7>2Ivs;VlAB1uxe-xmZS#xOh%20PDNJ8omybHgk( +zeXMAiq(q|R3w@j8b(WQTj6l;Y)l~VS9L^_cmB-~UEYe_{_@l_p0w?jU*fT>%AK02_ +zDvmDOnp9?f9@|-9#-28?W!DfbRnTQFN&PT#27%@JhV7_^C2NMLXnn-!&^g+ys7w@AL~&9l>+cR%^# +z-WNBn!S$D4_zRmyU;X~ZryqX&=TA?szxc~t_|L$uufJu-jvc%7^}*~-TeoiA +f0c8W#?A#1wvoP!HgJ_Ui5P-3_ZbGmjGW!1kYU3aE + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.png b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/013D.png +deleted file mode 100644 +index 96045927b9d5a299400298521ec53fd0ef0958b3..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 1152 +zcmd^7F{`9j6h6rYd|7!|SV&@FK$0meEG#T6%*MBv7sGQ|7c49c2s?!V3j+o$Tw*}N +z1Pn|ug@wfw7LrUJ7E?@Nv5+YyWQr+fSr?|*kSQiG#X`0ToZQ{Nk<0n+<=(^j&f$LF +z4-an4%ex=m1%S)z&#xYm^MZi7xI^}Li+{fcxC0Nqd~}~&1&-zz%Cam(IP +zijq}9lo(E+7!GVrG8Ivmcw8=Dx9zL>{4|>#%koeZLz?d5coT-}Am}}B<+`11FHE!1 +z^|_{1iZYYsQj#X3my{8FaYp$z?VB5*0@{Yw!?LU +zeTAzjcKPczJ`2jxJa# +zugjbwv69G~&*$UucsLw}Vc6|!TrRt=YumPIn!2uMv)ObyolGWqo@ZH> +zBuNxSVHgHM;CY_wy0&ebrfC?4rfI6G%CbBfjYLsQFpAFO@xk}EuGibn!nA7Ln5ud% +ztFa^p;>h6zgX0v26=|BI`lejg#bTBi?A0fu4!QHQnr#KW@zI`4%W8VAm +z)8Bv1HlKVHNI%`a!TY~GV;=wgg5de>2N(Y+PrkngP~3hTJ$~U5+W=hOzq$J5v#-AU +E5Bp+lwg3PC + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0172.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..54b92066e9176728d8a77f546965dca6c2459277 +GIT binary patch +literal 142 +zcmd;J;A8*+4InlGVp|~g1maL2P6FZrAg%*q23CCt_|L$mufKiU_Fek={~6fz^*3$Z +rx)sI-s@S|8B+da=yLmg9!>O;o1*B*TjJIt&NHp`6vmH^ka1$kB8z}gB1Ei^MT8)c$s)X$_lVEP%P<*?kVV7@1+&N^N`x!| +zW>KU_gbq{*l0_F;l(CBlT~w?xi;9IQSg>G_E=KI4V1>6BMC5p#f5XeY=W_4i{LbZm +z-zT>&&CZQyZva5&;`OuJWWP?<)7P(&_}ZsmJ_m3OZoPTuoE!y?<`~MdEJWmao@H5@ +zrYVY&RY8;(PM{bLY)vv1QI~j}%^poASL5+vG};%%uHSFdbQ8y`FkA+~!t>^?+t~Kh +zG;3WSYg(x&BUvsaX&{QZAY?qBa9qr?A;a`&+NUUwq8y5{0Zae`01rESxWRUbn>nr< +zT-LZKaX!Q*e>6#t<9J_&yJ4^$cA0F{E4nGEdKWQ1wC;9p+%M&6 +zDwH1EH>g+wqBXWH&gWQ`n5O9asOu;Q2yg^=2(SfM0W1I-fEu6#7yx7dF+dN%10a$S +zz4m)tE^#u!qQE#t$3aykE+QB*35GBTfK=xIA%OE=-$RSrIW9|VQXG3&XqfR=F?WcV +zU60xN^vb2~+b}a>YCL`?ZV?;A0x?815k*9(b*NMr%Fq{yIlG3;t0F7&G->hJN*aI+ +zAOdgzv2!}T_Rs~^WyB}&PTtz +z`os5~?_PN3sT2SFkLO?M{?*(&x%-|!?tJ?s^Y-8Ga(An%arof<)31Mh`Ncnf{N}Tt +d{yF{P=I3pf{qX0P-XavZIKMpm>hztD{{`a~asU7T + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/040D.lmp +index 30f1c79d8f49a678ca7efb9830d7c4b131673e9c..2f5ee22b76a1ce965e7ff13818670940834bf02b 100644 +GIT binary patch +literal 146 +zcmYL>%ME}q3`0YUpmY*$J}>|?umKaW00Xd3|JxNuLc-E>97~B4FCtb}`bKtgkds{G +xCJz}WeCl=vN~VA=Mq6!Ci6Lm?0ZyPMS|1iBpb>7y(Nj*fanY+7V=kKi_b-_HCt?5q + +literal 137 +zcmYL>%ME}q3`0{6&{4SgzyK`30xZA)48TxH`q{3ys1lZ5WIIZtL=g$Ha&BZN2RX?_ +rZt{?6#!w3jkP`(oiEKTa>IelW&hFbNDlxTvm&arv3_&7hkwwJ7M94tE +zfLRnNnni^!GLS_VSrjc8q+r1=#z&N*U35{fV!;uMyhRtY7wn3%R@;jM6oXjInQStm#}Qy>4Xdu(6mQUE=AcCWdRrf +zIsjg6@yQA|Ev{y`Y_P3yUgB(kP5x}0?nm*i47US+-FKI{y~wP2YBsSkj`UHemA+bd +zO3#rqTS_c3G`gNH*cxvtoF=id*bxP0zu)h6yX|(n*=$y;)nc(|+jc&mPp8wSX~yGm +zUDs7r4Tr0mio!7TecyFm$8jvnG7Ll4byZarMUf<_+wBU1kYE(; +zgJA1(ITJ9e~2t;e#Y;ZQivcxn+&qGZ^o=1Q^z!QKqzye?n&;Zl` +zB|sk_1Bd|v02hErM)cb4ux)WX#-hMDM%zY3Aub{`WDy#|K?q294iEy^*K@BnxSnBK +zVw2*?#X`l5dm6J>5wi`LwMQ=;>ahh=119?Ocj6kcK`anML<3Pkgj$12fq?`)fta(a +zOPnHfB#tH{o?A%;kN^Y#7JwuHD;;+xrlb{@u&khrAgsgi*T0V519$;GxqEJt(*HWX +zR{s{sSG{q1eCOW7-(LIa=NIACgUgFgPyTuT{_ECPkN)`a)M<1PipWnK9)T&>;ObFog6^n9U+-0;-`ITeH<-JPY`$qj%o3kW%>hK>;*C12jMb6hKdLuI|DFMZ(fp-nG|Wyofki=^N~DzzG-J +r@W3?dsOA>coG8^M9yewSVF=6;@xF~|Ej=~PQY;nG^JbQEpZ~Wn%e5vA + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0400.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0400.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..5a41b45e3e0ce65d909ec41c2881c7d0186de6cd +GIT binary patch +literal 142 +zcmXAh%MFAu3`7k9El>$Z&eT8$TftsQLI~1aXdIrkBRy-zzriLm3pP_1SYd-N{NR8a +y`XJZS^-?Vt&RTDT4>|6+cxRG!DMv(XMyV*(R5Pg^*pA9d1iv~}8UMY1LeC4VL-?h7F#UD;tGp}Y_Y{cEVj6WEw4wlVlr3LlE?y +zw{hLhwpXUv==xIADn(hyaw$nOQ7i-@=lPW55|)h^CZuVfqCARnD9Q#f0Sq$V`G~Lf +zI1aeq;I6}=!M?)H9J}I8n_ZU4sfv#C;4t%cg|p4=KC`;SY-3{?=~bYWzB+Z4+>ujT +zip+^`h>k8;DzD3&BC(RlTrQW>>2y3E$8p^6_uK7u7>2&@*XwoHb#2==O;gwPVzHRd +z=d;q3o~{;oQ>OJauJUM}1+&B}A~y@{)VE^S +z2p!$GRM$`(U9O9uOr0XKQeO`p#WN*a6AgvW@*qy!FtWYCbX?7}72T9neS(;rNB6KX +zURLrd6Dp6L8dM_P`2fceHyf-f%rf+S)O8dD1h@da0yqF{0eXNApaG}=W&k-r0uTat +z0OVxkUZ)cd1GX)eB_;_v4yr0~5s@K}$Pf)8K&lIX2*A1Pdmizy!J)z~!=;C%hB^N_ +z;m$F044H#ZZ(Zu84Qmrt#@jjZfY>3Hh!LWRC?Z0mL#@JGhN(!*IWc5j6S=q(UY4$9)9`5|D%0m`Tzg` + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0024-Mark-non-modifying-map-functions-as-const.patch b/games-fps/gzdoom/files/0024-Mark-non-modifying-map-functions-as-const.patch new file mode 100644 index 0000000..a07fab2 --- /dev/null +++ b/games-fps/gzdoom/files/0024-Mark-non-modifying-map-functions-as-const.patch @@ -0,0 +1,270 @@ +From bc6bf8c3b04fe074020b5de17f5b486bf61b2220 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Tue, 17 Jan 2023 16:27:52 -0300 +Subject: [PATCH 24/51] Mark non-modifying map functions as const + +--- + wadsrc/static/zscript/engine/maps.zs | 110 +++++++++++++++------------ + 1 file changed, 63 insertions(+), 47 deletions(-) + +diff --git a/wadsrc/static/zscript/engine/maps.zs b/wadsrc/static/zscript/engine/maps.zs +index d10ffe5d1..20ef85ab4 100644 +--- a/wadsrc/static/zscript/engine/maps.zs ++++ b/wadsrc/static/zscript/engine/maps.zs +@@ -5,11 +5,12 @@ struct Map_I32_I8 native + native void Move(Map_I32_I8 other); + native void Swap(Map_I32_I8 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native int Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,int value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, int value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -33,10 +34,11 @@ struct Map_I32_I16 native + native void Move(Map_I32_I16 other); + native void Swap(Map_I32_I16 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native int Get(int key); +- native bool CheckKey(int key); ++ native bool CheckKey(int key) const; ++ + native void Insert(int key,int value); + native void InsertNew(int key); + native void Remove(int key); +@@ -61,11 +63,12 @@ struct Map_I32_I32 native + native void Move(Map_I32_I32 other); + native void Swap(Map_I32_I32 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native int Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,int value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, int value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -89,11 +92,12 @@ struct Map_I32_F32 native + native void Move(Map_I32_F32 other); + native void Swap(Map_I32_F32 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native double Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,double value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, double value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -117,11 +121,12 @@ struct Map_I32_F64 native + native void Move(Map_I32_F64 other); + native void Swap(Map_I32_F64 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native double Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,double value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, double value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -145,11 +150,12 @@ struct Map_I32_Obj native + native void Move(Map_I32_Obj other); + native void Swap(Map_I32_Obj other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native Object Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,Object value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, Object value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -173,11 +179,12 @@ struct Map_I32_Ptr native + native void Move(Map_I32_Ptr other); + native void Swap(Map_I32_Ptr other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native voidptr Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,voidptr value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, voidptr value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -198,11 +205,12 @@ struct Map_I32_Str native + native void Move(Map_I32_Str other); + native void Swap(Map_I32_Str other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native String Get(int key); +- native bool CheckKey(int key); +- native void Insert(int key,String value); ++ native bool CheckKey(int key) const; ++ ++ native void Insert(int key, String value); + native void InsertNew(int key); + native void Remove(int key); + } +@@ -228,11 +236,12 @@ struct Map_Str_I8 native + native void Move(Map_Str_I8 other); + native void Swap(Map_Str_I8 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native int Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,int value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, int value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -256,11 +265,12 @@ struct Map_Str_I16 native + native void Move(Map_Str_I16 other); + native void Swap(Map_Str_I16 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native int Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,int value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, int value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -284,11 +294,12 @@ struct Map_Str_I32 native + native void Move(Map_Str_I32 other); + native void Swap(Map_Str_I32 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native int Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,int value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, int value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -312,11 +323,12 @@ struct Map_Str_F32 native + native void Move(Map_Str_F32 other); + native void Swap(Map_Str_F32 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native double Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,double value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, double value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -340,11 +352,12 @@ struct Map_Str_F64 native + native void Move(Map_Str_F64 other); + native void Swap(Map_Str_F64 other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native double Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,double value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, double value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -368,11 +381,12 @@ struct Map_Str_Obj native + native void Move(Map_Str_Obj other); + native void Swap(Map_Str_Obj other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native Object Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,Object value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, Object value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -396,11 +410,12 @@ struct Map_Str_Ptr native + native void Move(Map_Str_Ptr other); + native void Swap(Map_Str_Ptr other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native voidptr Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,voidptr value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, voidptr value); + native void InsertNew(String key); + native void Remove(String key); + } +@@ -424,11 +439,12 @@ struct Map_Str_Str native + native void Move(Map_Str_Str other); + native void Swap(Map_Str_Str other); + native void Clear(); +- native uint CountUsed(); ++ native uint CountUsed() const; + + native String Get(String key); +- native bool CheckKey(String key); +- native void Insert(String key,String value); ++ native bool CheckKey(String key) const; ++ ++ native void Insert(String key, String value); + native void InsertNew(String key); + native void Remove(String key); + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0025-Fix-iterator-invalidation-for-Map-Get.patch b/games-fps/gzdoom/files/0025-Fix-iterator-invalidation-for-Map-Get.patch new file mode 100644 index 0000000..9023192 --- /dev/null +++ b/games-fps/gzdoom/files/0025-Fix-iterator-invalidation-for-Map-Get.patch @@ -0,0 +1,32 @@ +From d09cfff738f53f65efdeb1f39ce5ce1db81ee747 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Tue, 17 Jan 2023 16:33:41 -0300 +Subject: [PATCH 25/51] Fix iterator invalidation for Map::Get + +--- + src/common/scripting/core/maps.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/common/scripting/core/maps.cpp b/src/common/scripting/core/maps.cpp +index 68eab6d3d..bfc2b676d 100644 +--- a/src/common/scripting/core/maps.cpp ++++ b/src/common/scripting/core/maps.cpp +@@ -125,6 +125,7 @@ template expand_types_vm MapGet(M * self,expa + { + typename M::ValueType n {}; + self->Insert(key,n); ++ self->info->rev++; // invalidate iterators + return n; + } + } +@@ -139,6 +140,7 @@ template void MapGetString(M * self,expand_types_vmInsert(key,out); ++ self->info->rev++; // invalidate iterators + } + } + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0026-Add-Missing-Read-Barriers-to-Map-Get-Functions.patch b/games-fps/gzdoom/files/0026-Add-Missing-Read-Barriers-to-Map-Get-Functions.patch new file mode 100644 index 0000000..0dea12d --- /dev/null +++ b/games-fps/gzdoom/files/0026-Add-Missing-Read-Barriers-to-Map-Get-Functions.patch @@ -0,0 +1,59 @@ +From 7f0b52de6fcddf98dc07ca3aa1c34e8b03e0416c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Wed, 18 Jan 2023 21:05:47 -0300 +Subject: [PATCH 26/51] Add Missing Read Barriers to Map Get Functions + +--- + src/common/scripting/core/maps.cpp | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/src/common/scripting/core/maps.cpp b/src/common/scripting/core/maps.cpp +index bfc2b676d..b6ae925c6 100644 +--- a/src/common/scripting/core/maps.cpp ++++ b/src/common/scripting/core/maps.cpp +@@ -118,8 +118,16 @@ template unsigned int MapCountUsed(M * self) + template expand_types_vm MapGet(M * self,expand_types_vm key) + { + typename M::ValueType * v = self->CheckKey(key); +- if (v) { +- return *v; ++ if (v) ++ { ++ if constexpr(std::is_same_v) ++ { ++ return GC::ReadBarrier(*v); ++ } ++ else ++ { ++ return *v; ++ } + } + else + { +@@ -149,7 +157,6 @@ template int MapCheckKey(M * self, expand_types_vmCheckKey(key) != nullptr; + } + +- + //========================================================================== + // + // MapInsert +@@ -240,7 +247,14 @@ template void MapIteratorGetKeyString(I * self, FString &out) + + template expand_types_vm MapIteratorGetValue(I * self) + { +- return self->GetValue(); ++ if constexpr(std::is_same_v) ++ { ++ return GC::ReadBarrier(self->GetValue()); ++ } ++ else ++ { ++ return self->GetValue(); ++ } + } + + template void MapIteratorGetValueString(I * self, FString &out) +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0027-cleanup-of-the-Chex-Quest-small-font.patch b/games-fps/gzdoom/files/0027-cleanup-of-the-Chex-Quest-small-font.patch new file mode 100644 index 0000000..249cca3 --- /dev/null +++ b/games-fps/gzdoom/files/0027-cleanup-of-the-Chex-Quest-small-font.patch @@ -0,0 +1,1076 @@ +From dde1288fb120f6ace3e09163fc0d9c6db64964b6 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sat, 21 Jan 2023 21:29:45 +0100 +Subject: [PATCH 27/51] - cleanup of the Chex Quest small font. + +This no longer bases its diacritcal characters on Doom's font, it also fills in all characters already present in Doom's small font. +--- + .../game-chex/fonts/defsmallfont/00C0.lmp | Bin 131 -> 146 bytes + .../game-chex/fonts/defsmallfont/00C1.lmp | Bin 131 -> 146 bytes + .../game-chex/fonts/defsmallfont/00C2.lmp | Bin 147 -> 147 bytes + .../game-chex/fonts/defsmallfont/00C3.lmp | Bin 147 -> 164 bytes + .../game-chex/fonts/defsmallfont/00C4.lmp | Bin 143 -> 149 bytes + .../game-chex/fonts/defsmallfont/00C5.lmp | Bin 131 -> 143 bytes + .../game-chex/fonts/defsmallfont/00C6.lmp | Bin 165 -> 183 bytes + .../game-chex/fonts/defsmallfont/00C7.lmp | Bin 145 -> 149 bytes + .../game-chex/fonts/defsmallfont/00C8.lmp | Bin 133 -> 148 bytes + .../game-chex/fonts/defsmallfont/00C9.lmp | Bin 129 -> 148 bytes + .../game-chex/fonts/defsmallfont/00CA.lmp | Bin 141 -> 149 bytes + .../game-chex/fonts/defsmallfont/00CB.lmp | Bin 137 -> 147 bytes + .../game-chex/fonts/defsmallfont/00CC.lmp | Bin 84 -> 84 bytes + .../game-chex/fonts/defsmallfont/00CD.lmp | Bin 84 -> 84 bytes + .../game-chex/fonts/defsmallfont/00CE.lmp | Bin 120 -> 94 bytes + .../game-chex/fonts/defsmallfont/00CF.lmp | Bin 118 -> 124 bytes + .../game-chex/fonts/defsmallfont/00D0.lmp | Bin 130 -> 142 bytes + .../game-chex/fonts/defsmallfont/00D1.lmp | Bin 148 -> 164 bytes + .../game-chex/fonts/defsmallfont/00D2.lmp | Bin 127 -> 136 bytes + .../game-chex/fonts/defsmallfont/00D3.lmp | Bin 127 -> 136 bytes + .../game-chex/fonts/defsmallfont/00D4.lmp | Bin 140 -> 141 bytes + .../game-chex/fonts/defsmallfont/00D5.lmp | Bin 140 -> 162 bytes + .../game-chex/fonts/defsmallfont/00D6.lmp | Bin 138 -> 147 bytes + .../game-chex/fonts/defsmallfont/00D8.lmp | Bin 130 -> 134 bytes + .../game-chex/fonts/defsmallfont/00D9.lmp | Bin 129 -> 148 bytes + .../game-chex/fonts/defsmallfont/00DA.lmp | Bin 129 -> 148 bytes + .../game-chex/fonts/defsmallfont/00DB.lmp | Bin 136 -> 149 bytes + .../game-chex/fonts/defsmallfont/00DC.lmp | Bin 134 -> 147 bytes + .../game-chex/fonts/defsmallfont/00DD.lmp | Bin 125 -> 134 bytes + .../game-chex/fonts/defsmallfont/0100.lmp | Bin 140 -> 150 bytes + .../game-chex/fonts/defsmallfont/0102.lmp | Bin 140 -> 158 bytes + .../game-chex/fonts/defsmallfont/0104.lmp | Bin 145 -> 140 bytes + .../game-chex/fonts/defsmallfont/0106.lmp | Bin 129 -> 153 bytes + .../game-chex/fonts/defsmallfont/0108.lmp | Bin 141 -> 154 bytes + .../game-chex/fonts/defsmallfont/010A.lmp | Bin 0 -> 147 bytes + .../game-chex/fonts/defsmallfont/010C.lmp | Bin 132 -> 156 bytes + .../game-chex/fonts/defsmallfont/010E.lmp | Bin 132 -> 143 bytes + .../game-chex/fonts/defsmallfont/0110.lmp | Bin 0 -> 142 bytes + .../game-chex/fonts/defsmallfont/0112.lmp | Bin 138 -> 148 bytes + .../game-chex/fonts/defsmallfont/0114.lmp | Bin 138 -> 154 bytes + .../game-chex/fonts/defsmallfont/0116.lmp | Bin 0 -> 142 bytes + .../game-chex/fonts/defsmallfont/0118.lmp | Bin 144 -> 142 bytes + .../game-chex/fonts/defsmallfont/011A.lmp | Bin 132 -> 151 bytes + .../game-chex/fonts/defsmallfont/011C.lmp | Bin 141 -> 143 bytes + .../game-chex/fonts/defsmallfont/011E.lmp | Bin 0 -> 152 bytes + .../game-chex/fonts/defsmallfont/0120.lmp | Bin 0 -> 136 bytes + .../game-chex/fonts/defsmallfont/0122.lmp | Bin 0 -> 136 bytes + .../game-chex/fonts/defsmallfont/0124.lmp | Bin 142 -> 149 bytes + .../game-chex/fonts/defsmallfont/012A.lmp | Bin 0 -> 100 bytes + .../game-chex/fonts/defsmallfont/012E.lmp | Bin 0 -> 80 bytes + .../game-chex/fonts/defsmallfont/0134.lmp | Bin 159 -> 137 bytes + .../game-chex/fonts/defsmallfont/0136.lmp | Bin 0 -> 145 bytes + .../game-chex/fonts/defsmallfont/013B.lmp | Bin 0 -> 126 bytes + .../game-chex/fonts/defsmallfont/013D.lmp | Bin 0 -> 132 bytes + .../game-chex/fonts/defsmallfont/0141.lmp | Bin 122 -> 140 bytes + .../game-chex/fonts/defsmallfont/0143.lmp | Bin 133 -> 146 bytes + .../game-chex/fonts/defsmallfont/0145.lmp | Bin 0 -> 140 bytes + .../game-chex/fonts/defsmallfont/0147.lmp | Bin 136 -> 149 bytes + .../game-chex/fonts/defsmallfont/0150.lmp | Bin 134 -> 152 bytes + .../game-chex/fonts/defsmallfont/0152.lmp | Bin 178 -> 178 bytes + .../game-chex/fonts/defsmallfont/0154.lmp | Bin 137 -> 150 bytes + .../game-chex/fonts/defsmallfont/0158.lmp | Bin 140 -> 153 bytes + .../game-chex/fonts/defsmallfont/015A.lmp | Bin 118 -> 130 bytes + .../game-chex/fonts/defsmallfont/015C.lmp | Bin 127 -> 131 bytes + .../game-chex/fonts/defsmallfont/015E.lmp | Bin 122 -> 124 bytes + .../game-chex/fonts/defsmallfont/0160.lmp | Bin 121 -> 133 bytes + .../game-chex/fonts/defsmallfont/0162.lmp | Bin 124 -> 129 bytes + .../game-chex/fonts/defsmallfont/0164.lmp | Bin 132 -> 135 bytes + .../game-chex/fonts/defsmallfont/016A.lmp | Bin 0 -> 148 bytes + .../game-chex/fonts/defsmallfont/016C.lmp | Bin 130 -> 154 bytes + .../game-chex/fonts/defsmallfont/016E.lmp | Bin 130 -> 149 bytes + .../game-chex/fonts/defsmallfont/0170.lmp | Bin 136 -> 156 bytes + .../game-chex/fonts/defsmallfont/0172.lmp | Bin 0 -> 142 bytes + .../game-chex/fonts/defsmallfont/0174.lmp | Bin 0 -> 155 bytes + .../game-chex/fonts/defsmallfont/0176.lmp | Bin 0 -> 135 bytes + .../game-chex/fonts/defsmallfont/0178.lmp | Bin 126 -> 133 bytes + .../game-chex/fonts/defsmallfont/0179.lmp | Bin 120 -> 138 bytes + .../game-chex/fonts/defsmallfont/017B.lmp | Bin 119 -> 132 bytes + .../game-chex/fonts/defsmallfont/017D.lmp | Bin 123 -> 141 bytes + .../game-chex/fonts/defsmallfont/0218.lmp | Bin 0 -> 124 bytes + .../game-chex/fonts/defsmallfont/021A.lmp | Bin 0 -> 130 bytes + .../game-chex/fonts/defsmallfont/040D.lmp | Bin 138 -> 146 bytes + .../game-chex/fonts/defsmallfont/0419.lmp | Bin 138 -> 152 bytes + .../game-chex/fonts/defsmallfont/1E80.lmp | Bin 0 -> 154 bytes + .../game-chex/fonts/defsmallfont/1E82.lmp | Bin 0 -> 154 bytes + .../game-chex/fonts/defsmallfont/1EF2.lmp | Bin 0 -> 134 bytes + .../game-chex/fonts/defsmallfont/font.inf | 2 ++ + 87 files changed, 2 insertions(+) + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010A.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0110.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0116.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/011E.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0120.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0122.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/012A.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/012E.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0136.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/013B.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/013D.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0145.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/016A.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0172.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0174.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0176.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0218.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/021A.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1E80.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1E82.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1EF2.lmp + create mode 100644 wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/font.inf + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C0.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C0.lmp +index 884bcaa95e8150c95793ce867f4ebb5cbc8b92fb..aa99a481e5b79b7f86e5cf7093b311efa88d7086 100644 +GIT binary patch +literal 146 +zcmd;J;9_84U}n$&lEy%655$2$oB+gmKwJ&P?Lf@JRtp9Hnb~V=i$S2a_CEs?NE9qm +mR$NvF65*g2@*ua$;`Ttm26}u2RX?_ +oyhl^%2jET#C=zO7$?P)<1^ahmzi|^I&F!QcfgEGxPW{tV9ut}>&j0`b + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C1.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C1.lmp +index 2aa1be2edcb787d47b33e8817cd8b44f2ffe6b46..385ae4d1dd5025a546f8b7a5a26353bd2f1e7462 100644 +GIT binary patch +literal 146 +zcmd;J;9_84U}n$&lEy%655(R;909~>KwJvM?Lf@JRtp9Hnb~V=i$S2a7Q!woE-M4F +mnK*zdih&Ra{xfpc)|SJ03|zIfMLJQ3k5n9+uXp@J4JiQ|8x(Ap1L0@R!{*V>;h{{RaoD#ZW* + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C2.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C2.lmp +index 7e52626d678d4e46afdebc1ce32d17daaa10b8c2..c5555b8e898039ac346d3c0cd88057bd472ec070 100644 +GIT binary patch +literal 147 +zcmd;J;9_84U}n$&lEy%655&Ge90SDJKwJgH9YD;&Rtp9Hnb~V=i$S2a_CF&hNVK@D +jxU3AwW8eaE%4>^(5D38BBA_f17bFW+4AlxX2+4c^CA>1A + +literal 147 +zcmX|((FwpH5JOLD!BIMa3v_`l&;|PG$sGv!>)tj>@!*9EBuSD)B*;O{LtxkjK2=}?Y?Q@#;1HN!DyZ`_I + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C3.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C3.lmp +index 110a3b03e82d5b21341ede3b61427bcc1e6d06e5..15386ed73636960d7b410a9c0336f9fd056cb8b7 100644 +GIT binary patch +literal 164 +zcmd;J;9_84U}n$&l9oX10mR`zoCd_DK->bvlYy9#sTK%W*gzx*{Ab_-lI69-?vmF~HZfa8{o4HB>{_?)=HPxSrGzbhH(h)tt{cH$FvkD@ + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C4.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C4.lmp +index 523ad846671423775f2f8623636d7b220ee30699..ee368cab69d1a9bf28a378bb9b3665304b64c147 100644 +GIT binary patch +literal 149 +zcmd;J;9_84U}n$&lEy&n0K|Sk90SCeKwJ*Qtw7AeRtp9HnK*!~Vi2gU{m;l*TU%ON +eTvl9G2IUpkf*=q;6+$^!6+#VRVgxEjvH<{iYch}k + +literal 143 +zcmX|(-3fp&41^P`*in3S0~c@s2XKIdQ_dL-M3W8|BE4;*^~O}TKf(1UoOW0 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C5.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C5.lmp +index 2aa1be2edcb787d47b33e8817cd8b44f2ffe6b46..7942a0ae5b6849ba6682286e1d2bdc8728491a4f 100644 +GIT binary patch +literal 143 +zcmYj}u?>JQ3B?&8Vs_XAO2Fp~fP + +literal 131 +zcmYj}u?>JQ3k5n9+uXp@J4JiQ|8x(Ap1L0@R!{*V>;h{{RaoD#ZW* + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C6.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C6.lmp +index e57b956d2c1e6e1be0bfe712bce25280bd08c2ff..9c8787c87228b7c58dbd27cd11097116a7708153 100644 +GIT binary patch +literal 183 +zcmd;PU}pdU6Ckz+Vs9W02jXNP&IjUZAZ`cZ$v`|Gh*twKBU>#L{AXaVtt|$D+FA&^ +nthlTU#;yg5Vq+t#LDE}NSyEXFS6^CN0%cd!R@Rn7*)V$nbF4ng + +literal 165 +zcmd;LU}pdU10c2nVpkvz1majA&IIC8AZ`TWULc+c#7wNU5b&Rot+uwRq@<*__CEuA +vZEbl;d3iaMT~u2NQUn%9VV5D)mz9^57eUpO))v*4LD?m><+a67Hq0sjxp+6h + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C7.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00C7.lmp +index 4e04a428007221bb696d6f8a702e92fcc5d447aa..7db6990a89602e2334128d063f55164e039d6320 100644 +GIT binary patch +literal 149 +zcmXAf(FuSs3vokti$YMs{+LlU(E> +rFNrgT)Xv2Os052Wsik_7ft!U+voI|{LvcexVtZU{tGnTE{vYTE9=NLF{4>sI7&t%ZkfDY$gt% +rlHw{L1acTTYirAEi@~t=KLb~7Z4pos#$^H-1~R7#3?b$~E%*-rHkmRw + +literal 129 +zcmXYp$qj%o3V8P5P8`vXEFv9{XY;ZtZ +oi@BRtDi>0Bh^LHJJxy|V+=7%9b4h>LNLF{4>sIC3a$O#fIE(1a! +kkAVxwDX%TA0zxRa2q+7N2w5l>qP40P1Z%;DLT&gD0FbCNxBvhE + +literal 141 +zcmXYp(FuSs3`A2A>?jW4050GHF5m!Zs}%;EHy5-{(6c`82a~lf!~g&Q + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00CB.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00CB.lmp +index 663367e721c6a608487e61c44dbe44475719dfd2..9d1884202ce60aafc1063c15ca850cf7bd30585b 100644 +GIT binary patch +literal 147 +zcmd;J;9_84U}n$&k|sdx2*mzC91Fx*KwJUDZ9vS-UJC>NnK*#VVi2gU{m;l*TU%ON +jTn25QVis0fa&%UU6*|7(x|7&HoPoBDONC + +literal 137 +zcmX|((FuSs3`7$x*irm*0vB)r2XFx)4K>2eu2+!;-jRcsWXU3;GBX#ll8x--ASVGy +o12~T=b4)>`Tzg` + +literal 84 +zcmZQ&;9y{2U}TU1lFC4A0K~RH>>`Tzg` + +literal 84 +zcmZQ&;9y{2U}TU1lIlQg48#sV>i91g^coV5t>pMeX=DX%R9f!bOyx2U$Z7zChPpez*p +KXJi7g{sRCRL>|%r + +literal 120 +zcmXAh!3}^w2m~R1D8-jg8?XTzumOK^$(fjJ?K+2>46qv@EX>SprY^9;20I*ZLV~-b +f*Cwft9#SJ1!ZhX^mFX;8nMAdQE7k2o_<#BUJ_jXZ + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00CF.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00CF.lmp +index 0a46b3bb137e854b56f55382c60d8bec672dd3a2..c421a71dda2d3503a5f267d3dd1cdafece0589b2 100644 +GIT binary patch +literal 124 +zcmd;J;9_84U}n$&lKMbw4#ciN90bJiK%5K2r9jNYR0{(@_s2&2qx<`4zK%4=@1whQmSX*2BpMklywiHBj)YcXQ1wi0G +cBRh~R2Lc$ou&4+q304GD3=dbkIo`-SknI +kfE5W`vwo3Oy#*rT9U+L`T2UYGl2r@48-bFo`oYf7e$}BV_y7O^ + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D1.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D1.lmp +index 900a80f45247e973c4b50749355e387ec44c97ae..980757e8562c5ec81287f67585323aa8583979a7 100644 +GIT binary patch +literal 164 +zcmd;J;9_84U}n$&l9oX10mR`zoCd_DK->bvlYy9#sTK%W*gzx*{Ab_-lI69;|ZGIpA&lQdo!845RAE7YI*mUKl>dqRR910 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D2.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D2.lmp +index 29bb39ffa358f14e06b0a8e0a557bc23aa558c1f..860ba274756c38d0cc6b910375478a6cedc387ff 100644 +GIT binary patch +literal 136 +zcmX|(K?;B{5Cd0hvGye%J^KcK;0wH3SWf|eu2WGLW=R4`vTSC-M*ajdEU>}`4kyH* +mdRG^vQVPo28iXG2?oX1X9ZOtoGf2np+C=PB{avAi`gU)^$}C?1 + +literal 127 +zcmd;J;9y{2U}Vq$lKMbw2gKe$909~BK%5W66+q0wR0{j6& + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D3.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D3.lmp +index e1b3e850bbb185381aadfae69926f7777d730a6c..4da412af143d74cf4c54a84098fe4e53f58139c4 100644 +GIT binary patch +literal 136 +zcmXwx%ME}q3`0XhMd>6QIkNy0umKYgDV!{^d2#qedeQU2E>cBAW#XU7LRPYoojAEj +oR>ZYF17=1`h1uLaLN@{@XhD+-9FM*+MO6pDS@my)P1?VE1KZpzPXGV_ + +literal 127 +zcmd;J;9y{2U}Vq$lKMbw0mRNg><`2-K%5E06+q0wR0{JQ3S5-#=qk))~GJT + +literal 140 +zcmYj}!3lss3`| +pDM@M@nl9_4B1JrVmR#Zf3U_I(#id|EY@e+t_M_U!Gi(0;_XcB_EouM& + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D5.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D5.lmp +index b16fd6e5a7fbc5265fbb199bff9a6c85d1837ca8..9b1b69a209df362714b1a7f5a40dee912d892c51 100644 +GIT binary patch +literal 162 +zcmd;J;9_84U}n$&l4d~c4#Z(VoC?GxK->((Q-GL}sTK%WnL%Xje+Cd;Ue3Z=TU%UQ +r3=-g~tt|p_%F4=+xjfMOQ_p*J>H + +literal 140 +zcmYj}(FuSs3`8#?w4*qH1Gs<-xPaf%O0aO?=Ji_r5blLsl1oGcV3<^Av4~Y{Vi#H5 +p!i?lNsIVfCMG_U!U2RIQ$(cO5v?0A2jk>v5PVZ--MZf&-?*nF5Ep-3@ + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D6.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D6.lmp +index 681436fec67905c344a4ee3decd202db36a91f05..359d4599531bdcad225963bca3e8e3b669cddeda 100644 +GIT binary patch +literal 147 +zcmXwy!3}^g3N86ZcX9Ri#ZU(4l4)PC@02+@|==JT#`vW7!M5hRJA+7ayfPFTVf) + +literal 138 +zcmYj}feC;>3?jW4050GF4&VSk9|jEP?<4 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D8.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00D8.lmp +index 17639fa7b749ef7c3e8dc04d244d368ba076b038..673c1acc3d91cadf714363d4a4834bb33dcd7ef8 100644 +GIT binary patch +literal 134 +zcmX|((FuSs3`A3lwxhT}za78<9KZqmNICE$v&TzO11~(n<*F2kSxF-s*~vjpa*>-% +k*NLF{4>sIC3azyuNoiIf2W +jScI##wg{pY#AW2Htt|(0K|Cf7AQPq+rmGAnfowhiC6+Q; + +literal 129 +zcmd;J;9y{2U}Vq$l7>KR3&dVP91g_EK%57}6+q0yQVRzE8Q4K|d0AC$?SBRiAgi{h +kv=qiE0!kH^17#S&svvA8w%Xbfh#Dr=+S;;mkZQPj0LG3f_5c6? + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DA.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DA.lmp +index 254af0dbe17cc9cb3c50fa62fc70feeaeca0190e..12354cb750081e7467e7091a8fad41c0b4d40ae8 100644 +GIT binary patch +literal 148 +zcmd;J;9_84U}n$&k|sdx0K~pP91X--KwJaF9YD;?UJC>NLF{4>sIC3a!~qm80|F3- +jk+Zh89IOn)W8kW-ErMtQbD2PFWW69ZNNX8TF|zppK4mgW + +literal 129 +zcmd;J;9y{2U}Vq$l7>KR4a9Ch90bJiK%4`_6+q0yQVRzEnOJLU%gd^2YyUH`)z%i3 +lmV%g!>|n{_av+<51E>JVg>#B(OCYKkz^cm1!J1*_0RXrtDdhkF + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DB.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DB.lmp +index 77b2f76a0ecdbe1d2d4ce242a6af1db91aaf8390..e50d77b03dad37a1a0df2872fc5490843f3ccbd9 100644 +GIT binary patch +literal 149 +zcmd;J;9_84U}n$&k|sdx0K|Sk91FxbKwJ&Poj}aYUJC>NLF{4>sIC3a$O#fI0|F3_ +bfeXkf2P=eei@>~E7#ApuskIEK71;s+m`F3e + +literal 136 +zcmYj}(FuSs3`DOVVn^}Y0bIZZT)+hyO`&kEUawZrzzZC?mxu@;VA7t&B37}9T_kad +lFtAU>NIJ6@vLcekbe=t!wT|WI;{FRwIo_K5LeEY4zTW(0EkytT + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DC.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DC.lmp +index f1f5eb227b1a7a7e7e1e0ee7459ed7c888ea4c06..2c778c014ca67384c19c32ff6cc42a85aff86e6f 100644 +GIT binary patch +literal 147 +zcmd;J;9_84U}n$&k|sdx2*mzC91Fx*KwJUDZ9vS-UJC>NnK*#VVi2gU{m;l*TU%ON +f1_Ur3kOs*E<-iJI9Ed_>ZN*@1WylJFivI%uDdIA* + +literal 134 +zcmd;J;9y{2U}Vq$l14ym2gKe$91g_EKwJRCH9*YBS_=XH8Q5!UOKZ!^s%mThGjP<_ +l7S|S)mV!8pKnWlyE=Oa76qVMNKoo&=7uS}RgEhd-1OTGAEL{Kq + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DD.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/00DD.lmp +index 47a47dc981790510c8a788f5943e2823cfd68ca9..4cbf5f9bd230f684b43c2ca4410a93036c61128a 100644 +GIT binary patch +literal 134 +zcmXYp!3}^g3qW};r+$-70P7ZRCo4iEC +oW15WasuU^Hno-gWv-=aiM=0)B+|`UBQfQgtk^V2~QE#oaeSw22(f|Me + +literal 125 +zcmd;J;9y{2U}Vq$k_JF*3B;~I90bJiK%4`_r9jNYTnhsKnOJIT3rm0uMs^^#u(%W? +i$iPusTMps^2{5M!!~sfyIkmM#5M>~}MP)!ym|*}5GAGyo + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0100.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0100.lmp +index c2b210ae0a836e5d543bb863bfa933203f788854..65cbc975a59d678f9ce6ce3e32bfc95947fb9168 100644 +GIT binary patch +literal 150 +zcmd;J;9_84U}n$&lEy&n0K|Sk90SBzKwJUDZ9vSzRtp9HnK*!~Vi2gU{m;l*TU%CJ +gTvl9G2IUpkf*=rp10gRiUeh9if$xrR$$5AH0~XCyY+@IOI7Jq> +oaE@ISW82eAUMZ0ko(!~P_8Mzek$(A^z)-#pSz?TewO3vB0eH_YQvd(} + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0102.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0102.lmp +index 2677c491efc88dd19dae62ce99349669eca448ab..0e2f7121e960a41c32a19305aa482800f00f0c03 100644 +GIT binary patch +literal 158 +zcmd;J;9_84U}n$&lEy&n3dA8moCL%LKwJmJy+F*uRtp9H8JIvUX7<|JVi2gU{m;Nv +iTU!R?mKB!)ssD_eKsFcx)nVsBRl+pF%mJH>WEB7*X*L@G + +literal 140 +zcmZXM!3}^g3iPp$v40$B0zF2U}9!(-*Dtnx&OL;d)*msJbxKg_E49eZXgXW!TrAur_N|I4TR3^@uEMz4c*~v+6 +v(suY{?rN=oX#}#1J|v!VDaAuG02k;SlO8x;8})C3|5By`c*$iRDUXyr>Gv_@ + +literal 129 +zcmYj}u?>JQ3LzbVK7 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0108.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0108.lmp +index 7121c4d62b45a93b7a22173d408b4fa460068497..90c05e96c0baa3c72137ce07429dc15cfd1abd6e 100644 +GIT binary patch +literal 154 +zcmXwx%ME}q3`2v;x07(@%mi$}2AruBRHRJ6(B*{+OD~P>sG~#?2{JPmSYd-54!Gfg +uwzI0@Th7_6G?Pckg_DT6EUD^mPg=k5wy&+(5NgtVKWYtlN}xdAqw)e!6*FW2 + +literal 141 +zcmYj}(FuS+3`1KHyipv$0bIZZT)=P1dEh}locxT{4@+NYXh^bTW^SW&60=yuDmIbD +pCEQ8&orKK>vXEze?nHtWcnu&69Pud%?XeLne^Z&Gq`AtzX*ZNcF2eu- + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010A.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010A.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..063d00cb7f6a17bb52f42c0e692f06da71babe2e +GIT binary patch +literal 147 +zcmXwwyA6Oa3`89T#Agy}Y6f5eCSU?0ETwSA-sYKzlb(I&lSi3FB+J5FVS^nGIN^o| +py55>RT&>m2^I%p&_%uabRP|4n;Q~+JFK)=~klETI%Oj#_k-yQ-FYo{W + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010C.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010C.lmp +index 3a1e5d973f97408ed318e13eccb4726182411468..cc9a82ade6eeb040555456f090a9b61bbad799ec 100644 +GIT binary patch +literal 156 +zcmYL<-3fp|41){jA2*55KD&V%xPh-8RElH-XRfKI82H*W=^$A|l8l@anaM&{vXPTq +rq-jy*;mizh$xl>5?|A@4RlgHEXakoHh!*J6pRm-LaCu@w#RKIx!cR10 + +literal 132 +zcmX|&OAdfA2t=_qhNE=n)(dz6FW?2-Sp1|-=InKdM#3Y!45+AxbdoqnGLe}qWF;FZ +nBnGfrAAwT2h`Lv^S8@i-?EI1&JG^=3$uItM02h-mxOlY(DlIE4 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010E.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/010E.lmp +index 3cd7c8cbf7b846f01cc4be57123b115411e98f81..807bc5b38f550b8b4fe6e17d4de7e755c1192678 100644 +GIT binary patch +literal 143 +zcmXwx+YNv)2t_fqQ9FqPIDs3ufg2c0TTS$SJ9fSGL2`ftfmWP|80nb@GLnhRWFa6I +vF%59yiClH1?ua1(SsZ19NA&(v)|Er@Z^MB@sqbl0)kLc;kW%TaDKC+4cakvR + +literal 132 +zcmX|(!3}^g3NnK*#VVi2gU{m;l*TU%CJ +gTn2N8MwgAVi2gU1#`=5Ym3W( +f5X!ABsx7VpLL_c&F%TjYBXNO-Re@pce`H$#u3|Pe + +literal 138 +zcmX|((FuSs3`Aos(oy_#0~c@s7jS{5rB*l`y@x1gj8xCHLXbh1-Pw?<`#QvY99kaEkOVP + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0116.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0116.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..8124e9a4fe743116fc238f467403e33535088496 +GIT binary patch +literal 142 +zcmd;J;9_84U}n$&k|sdx0K`5(90kM~KwJjIO+d`dUJC>NLF{4>sI7&t%ZkfDY(`Fy +dlHw{Lgz}1Ni@^{s2jziGr~*TX2~eZ|0{|iwFhl?V + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0118.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0118.lmp +index f524889f91dcf371a9795c6d9f76cb2bf5921dd9..419300a4b0afb026eb6cd0b3c9d727e93834976e 100644 +GIT binary patch +literal 142 +zcmd;J;A8*+4InlFVh14h0pbWCP6gs(AZ`R=2KHJQ_zz+igFtO9gk4r#24`0lSAp3a +bKs6v(1yaNb<&>90c~!L#2$TaVgn|D65za6k + +literal 144 +zcmXZU!3lsc429vU6zeV?Jv)E{IDi9qunjfJySuf%U;-cffi^=(!Dgh1W?E>ajdr@} +qp|*p~+eAR?#R@$uA5y&~bG(Zd74Hl|u};7V1>gUR-4pu}{q_gjQ7=3I + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/011A.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/011A.lmp +index cc5aac045d61b48c88b26be8d3bad02d5fd3c57d..2757bdc5a0ffb4b2b1f626015be3da0c9e82e227 100644 +GIT binary patch +literal 151 +zcmd;J;9_84U}n$&k|sdx0L1=490$a?KwJaF-9XIDUJC>NLF{4>sIC3azy%gAE(1a+ +hw;U*21%xo!qS|6GgeV5dB5{GbtH7`pY%J7{{{a50G`Ii& + +literal 132 +zcmX|((FuSs5JS&eq@(!fuM4<<3%Gz^y_R}HX0JIB1Mj#Hk|aq)2AO#mvXYJLwrkrE<~WS?i&o_Y;A=EM + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0120.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0120.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..02947b75a84ad7a02af5362dd4a100408aed62a5 +GIT binary patch +literal 136 +zcmXww%L#x$3`8UA;-?aio-M!%tiTGyz#bM;`}zhn@WLC08ErPRWD9?V4R$!-gbNp +l>M*r{zNUMJ`_*-h6^eF5jrEgJv; + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0124.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0124.lmp +index ff278602074ebec2721c39f69fa94d57b73083f7..0150b6daabe497c931b038d8d640996a4f74044c 100644 +GIT binary patch +literal 149 +zcmd;J;9_84U}n$&k|sdx1jKN8971BVi2gU{m;M!c@P1U1u6$~AzI5o04NDE6lM&v1puWVGs^$~ + +literal 142 +zcmd;J;9y{2U}Vq$k|sdx2*iFs91X-7KwJvMO+d`ZUJC>N88~Wd%W6x2ptcswDXuLC +l0x+kz7^Doy2Fa9_A#p%@%1g^Dpn9rmi%N=sivJ^<3;-usFg^eP + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/012A.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/012A.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..948372cd0c87efbcbc32fbc456bed0c50323ea67 +GIT binary patch +literal 100 +zcmZQ$;9_84U}jJNl4?L~0>n;0900^|K+MEgTU+~|k+Zh849EZjFt50_3C0%8WvS_JqH;*~)_Z7rBr3<9;qP##!mJ&^nl0NfK9^8f$< + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0134.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0134.lmp +index c6790f0cd50e143b6c64fdd6ec0404b674ab1cc4..9c24bbb4853f20cd77d1b2d707b3804b405eb38a 100644 +GIT binary patch +literal 137 +zcmd;J;9_84U}n$&k_JF*0mKeK><7fLK%4`_)j-V7TnhsKL3A+^&Bz22hKVw80XgL$ +c5wIcZUe2XFx=Z~^aV4<^02Hx?gFKA;qe4VD_kBxbRQRczuAm$06{ +pB4U`^-8aJDIFUSA@ + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/013B.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/013B.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..07690c69d2cb4062bde449b32fa97a1e59f8bc65 +GIT binary patch +literal 126 +zcmXwv!3lsc6hl8)vE9T09KZ#fz_V8`l^%r5USCiHkGw!~lyGKPV1*5KIN*c^G3igY +cS4ZlRrABZ@c|TP*D~-NgwuJeR2HszLKT+N&hyVZp + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/013D.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/013D.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..a71a9d0601a11b06279bd6f8030691f91de36846 +GIT binary patch +literal 132 +zcmd;JU}pdU4InlFVh14h0pbWCP5|N@Ag%yn2KHJQ_zz+igFtO9m|X@0Fg8dLh|R(b +Up<()9^2KGfwLk>c2Q~0N07M}xY5)KL + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0141.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0141.lmp +index 989c1eb45475336b112c584eb9b2b1eb3296fa83..0cde44e5ea8c606161afac30531f4c71af063dac 100644 +GIT binary patch +literal 140 +zcmd;NU}pdU9UwLaVtXL=2I6oaP6pyUAg%%879eJ3ss)1o4D2AP1kNr70jPKx5Wv{A +frM0ynHX~bYZ5fmaHi3m1!UNGjiT@xP2>t^A62&Zg + +literal 122 +zcmd;JU}pdU4InlEVrw9F2jXBLjtAl_AT9!8CgxfY_|L!wqKd#w_S)K#ii(OVkT8&4 +dR9aeE0c8VKR2Bo-j9}%pASMgY1Q-p{4gi?MCVT(@ + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0143.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0143.lmp +index 61955342bf2e6f44b5f35c1ee158835b8404acfc..4b009b879b0491f49511a7158280e9483e0089a1 100644 +GIT binary patch +literal 146 +zcmd;J;9_84U}n$&lEy%655(R;909~>KwJvM?Lf@JRtp9Hnb~V=i$S2a7R)XyE-Nbo +qvY9wQD$0PuKn^2kZEZP>`=5cUwzdeNi-8HG24oIUCs;2t!gv7C3^6VM + +literal 133 +zcmX|(K@NZ*3cokNk%hUEjqKzgC%H%^ +p!-#L1oq(dMz^hSHrka`Snk%!30}>^cUOeLMeJ?-=%DZO&mk(}7E7kx2 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0145.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0145.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..cdf3593377468d80f31026dae011369c9981edd3 +GIT binary patch +literal 140 +zcmYL>u?>Jg3M;t4d2tYis{AaDc>0 +pO3N$2oT8%I+UkmGpb%K593)o-mnkU&$wT!N7ncIn{bz!k3IO^EEjj=I + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0150.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0150.lmp +index be16428719dc8b7a07c8da6d0096ec8aa1a7fa7b..4985bfe6bcdc8cfb47525854ea8797942454c8cd 100644 +GIT binary patch +literal 152 +zcmXwy$qj%o3byNu52!2)W2QDN|DWm)@o){h?KjZ&GWx@&i%NTGHnunrBqVMtxZ{}^{S$!wSL>a +D7neMA + +literal 178 +zcmXxd!3lsc429vUNDr>#(X#_MfCG5bG};t$aR3K!0N2!4Ndq7Jln3pcclml4V1x-~ +zSYU?}F1X==y3u@Z)vBhLP|l->sq`u;tG(wA)p0jc{$L5vDjJh1+L2uQ4;rB?$p8QV + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0158.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0158.lmp +index 4735a98014436a5c58d36e77858a60763267aeb6..0a9b55c882bffe46c9fc11a5a862bfff403cac01 100644 +GIT binary patch +literal 153 +zcmX|(iwS@*3`Bz!DxJgu+`tXozzxJeg~H(g4qfl+=fX>J(FuSs3`AoiRy&9P4&VY#;07*WpoPNC9P}(4Ms66K;iW&Nx)6B+i(dj-?F)<;rdrTVr(m6 + +literal 118 +zcmXYnu?>JQ39{0^$J`0@*-W5Qn`Mr~{-A$VM0j0CBJ>QUCw| + +literal 122 +zcmZQ);9vj&6(H6JVjCd#1mZ9tP6pz9AZBE%g@XSK9JRHTWtFuRKmjnPtgN)Qu(qTG +e%qglZt1T{pa!P6|O3J{>*nxV$x`0{`MgagA3Mfhd + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0160.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0160.lmp +index 90fa7ae4504c868ef466056b86a008eeb29889d7..c59edb28f9652e31def3de221eab16c91d02322b 100644 +GIT binary patch +literal 133 +zcmZQ);9_84U}jJOlKMbw2gJTW90SDJKwJgHENrz<@SlMT%&ID`sx7On1#`=5Ym3W@ +fYm1@W+9Dtm!3D{J~kTYs*S& +g3&9+qcx_QdZ82P?q@n~U57kpxSyl<;Fu{!i0P+$i;Q#;t + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0162.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0162.lmp +index 641ea31dca12a58a2f8d9afe6915be467363fa42..f0a560993c643f87df4a5bce3429da7ef12fd851 100644 +GIT binary patch +literal 129 +zcmd;J;A8*+4InlEVp|~g2I5E{P6OgXAg%;r2Ig82_z$9sYirpV!5mI72gs}fNr8AE +aP*MWoaR7N`KmbztejtAl#AT9x72Ig82_z$8BKr{!Kh6(~Xg{44HTU-p0 +XDJm{11_Cgr1gr?E7svsd0Wu2!*;gkf + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0164.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0164.lmp +index 57d4d0ad4eaddd9ac395ef9d76ebff32ca3bfef6..a0f3e9e1a5000fcb31bcb2cc0a98ba0dc4d0d45b 100644 +GIT binary patch +literal 135 +zcmd;J;9_84U}n$&k_JF*4a8nR90|l3KwJ*Q^+3$bTnhsK8Q8#dF^I`kTU%aR3uJ-- +am|I&^TMPn7vSmO3lSL>783z)E84Cd287%n# + +literal 132 +zcmd;J;9y{2U}Vq$k_JF*3&dVP91g@OKwJXEH9*Y7TnhsK85n^ih*JRKa8y))SzsBC +h+S-!Z!qU=GxJ+SDQ88Q(8%P=i{)4mwnP3{k2LR+ADRBS* + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/016A.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/016A.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..6a4c3fa513e58651c7472c68c2e0ac2f13b8e233 +GIT binary patch +literal 148 +zcmd;J;9_84U}n$&k|sdx2*mzC91FzRKwJsL?Lf@TUJC>NnK*#VVi2gU{m;l*TU%CJ +a1_Ur3kOs*^<N8MwgAVi2gU1#`=5Ys-KD +b#;q-asDR3%ae<1F^#YZG^p*h?BijN1wjwq> + +literal 130 +zcmd;J;9y{2U}Vq$l7>KR1H_&{916sVK%57}l|anIQVRzE8QFkzd0AC$?SBRiAgi{h +kv=qc)WUs9)tF0|Ahq6ncY>=Yj+7hTDkmj;-kb1a*0O|lLUjP6A + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/016E.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/016E.lmp +index b234e501f747a92a41406df08248ef9dc9cce5d7..7c059abd34717ee85fafc065387ad7282630ceac 100644 +GIT binary patch +literal 149 +zcmd;J;9_84U}n$&k|sdx0K|Sk91FxbKwJ&Poj}aYUJC>NLF{4>sIC3a$O#fI0|F3_ +bfvdK*6rv8o1*!oufB;DrQ)?MeE3yRulYBF$ + +literal 130 +zcmd;J;9y{2U}Vq$l7>KR4a6Qm916rqK%5W6l|anIQVRzEnOJLU%gd^2YyUHFfJBN) +iOCg-1q9P!-xEw4~R0O199FVdSh%%7wvT~3HxPbuU#VSGo + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0170.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0170.lmp +index 00bd29b6f0d257f7cc046303367bc08f63f9b821..04f00c74e6aeceee64831375627b4849f797a450 100644 +GIT binary patch +literal 156 +zcmd;J;9_84U}n$&k|sdx2*mzC90$a?KwJ&PT|mstUJC>NnK*#VVi2gU{m;l*TU%aR +j1_U4;16OTr5kw)33)O~D3)2Zz3({H!(#ixKR4aDw190J6NK%57}RY1(dQVRzEnOJLU%gd^2YyUH{14W8T +oOF?V~j@sH%Ah)<2%qcDgDTZ=DG9^%D>>!!4a$HR&IIBzAZ`L;2KHJQ_zz+igFtQVe+G`)+A<&jvVj~< +ch??TsDr8=92~;6e6Hp=01dy&WkOY#+03)q1EC2ui + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0174.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0174.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..381fe388f78e3a8455677dbfe9aa804acf19a798 +GIT binary patch +literal 155 +zcmX|)K?;B{3+!dn6N?$wF3g +vl8f9#Thu9<05bzh(?#O$VI))U5ggSjumOpe{SE$e^ZzY-!bBx&LVdqH2(>fq + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0176.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0176.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..e784101c4b9ab42c9f3d73d2a7e2005f066d49f7 +GIT binary patch +literal 135 +zcmYL>!3}^w2m~=0qgRQ)^J@imU^+KX>^^GO)`AW+@_~vZ8Nb2M0L81#a*H +m)nIiUBg`O%h29++P73HFeTpw-$D>(oF + +literal 126 +zcmd;J;9y{2U}Vq$k_JF*1;p+^91O(qK%4`_WkAfxTnhsK8CYv;OKZzPERNdR;@UzW +g6Ubp?2T{f4APFeDtQ4xKw6+MM2&A_dtQTe)06O(3Z2$lO + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0179.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0179.lmp +index e740a85c149de2ffded68ae96c48969bc8d09619..9ff01b43cc06ecafff6954be5c9a02f92ad74bb1 100644 +GIT binary patch +literal 138 +zcmZ9E!3}^w2n5&Tae8&wfd$xr71)7aNzRAa+HujJgn_UNR5SpFS#=Ss*u*XlaSJnM +n)USnA(v>30D8uPJhhZWw={@a0BTt$A-42xek+%|(_`Q7qgYGSV + +literal 120 +zcmZQ);9y{2U}R7MlKMbw1;lPZ91O$>K%5K2Ol-AK@E^o1tt~69t^Lo)4iqe@Ehz!A +i88|?~MO9VBP)xKn_SpSrt$dgb6X|KLDV5CinmV + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/017D.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/017D.lmp +index 37667c6ef9b425416488917d8bf85f559b67b089..d4ba2d882618156b3baf57eb739cad48bbe00af4 100644 +GIT binary patch +literal 141 +zcmZQ);9_84U}jJOlEy&n1jKVE3K^sa*B#-YfEZN +hO2C}j+Va|>s;XkROi@{FAylTewyX-Mt@b~XSpY(FD9!)? + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0218.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/0218.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..9d6f3b7b68f23c9aa931a578805ed5dabb68dd28 +GIT binary patch +literal 124 +zcmYL>!3lss3o{hWZ}!oY5lO|fdJ6&h@?!vQB;FwJ^3 +fY>~o4ox!jwd3U+uOL*6vi9( + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/021A.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/021A.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..d7da55c2903098eeb383c8821d1ad2686eb4737b +GIT binary patch +literal 130 +zcmd;J;A8*+4InlEVp|~g2I5E{P6Og1Ag%&p2Ig82_z$9sYirpV!5mI72gs}fNr8AE +bP+J1xaR7N`Kmb%ME}q3`0YUpmY*$J}>|?umKaW00Xd3|JxNuLc-E>97~B4FCtb}`bKtgkds{G +xCJz}WeCl=vN~VA=Mq6!Ci6Lm?0ZyPMS|1iBpb>7y(Nj*fanY+7V=kKi_b-_HCt?5q + +literal 138 +zcmYL>(G7qg3`C0`$|(N3fD5>Q3;0i=5J=k{8mHVSC904ZyXy@CNH(Vj7D<>WWERO)*LRMj%8`<~oH4mCIc + +literal 138 +zcmd;J;9y{2U}Vq$lEy%655zt|90|l}KwJ#O^+3$XRtp9H8QE)Vi$S2a_CEs$P_(S9 +fthfxy0SbcH5ScOv8>$SZ2c#dUr3|En31KV%SHmtM + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1E80.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1E80.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..c11c5aa7322617d15a6e4d1a4d65be2ce1f9e822 +GIT binary patch +literal 154 +zcmXwyF$#b{3VNV9j%_l0 + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1E82.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1E82.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..008105ac8816a837d4a1dc2109681bff105b4073 +GIT binary patch +literal 154 +zcmXwyF%Ez*2t~12O+AaNvj^}5Ucu2O=-{87J#qciNb<-BK9FP(5tWg7A~RXYN;Yzl +yn><8Y)F>K(oHI~D&yJb7ZW3^~;q*!r*nvo^eU0EV^#yJlE!x#HRl3cp`k%a|r80N` + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1EF2.lmp b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/1EF2.lmp +new file mode 100644 +index 0000000000000000000000000000000000000000..208ffd9e7daed3b7a78c85c50ae34928bcdfee71 +GIT binary patch +literal 134 +zcmXYp!3}^g3aIa(|J2}WnZt@aU +o#55fNGYU!JbpqV!BPqZY%KO7G0}q|K^O$l-qx?&H+FNUFA80x%;s5{u + +literal 0 +HcmV?d00001 + +diff --git a/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/font.inf b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/font.inf +new file mode 100644 +index 000000000..b3c8f4978 +--- /dev/null ++++ b/wadsrc_extra/static/filter/game-chex/fonts/defsmallfont/font.inf +@@ -0,0 +1,2 @@ ++FontHeight 9 ++ +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0028-refactor-add-some-logs-to-help-understand-what-is-ha.patch b/games-fps/gzdoom/files/0028-refactor-add-some-logs-to-help-understand-what-is-ha.patch new file mode 100644 index 0000000..449c031 --- /dev/null +++ b/games-fps/gzdoom/files/0028-refactor-add-some-logs-to-help-understand-what-is-ha.patch @@ -0,0 +1,44 @@ +From 083b99557f0b0808088a53f5ea5efca040eb25e9 Mon Sep 17 00:00:00 2001 +From: Emanuele Disco +Date: Tue, 24 Jan 2023 11:01:26 +0900 +Subject: [PATCH 28/51] refactor: add some logs to help understand what is + happening during soundfont selection. + +It helps understand what soundfont is currently used + +refs: https://github.com/ZDoom/ZMusic/pull/44 +--- + src/common/audio/music/i_soundfont.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/common/audio/music/i_soundfont.cpp b/src/common/audio/music/i_soundfont.cpp +index f05f0cb76..af1c5634c 100644 +--- a/src/common/audio/music/i_soundfont.cpp ++++ b/src/common/audio/music/i_soundfont.cpp +@@ -45,6 +45,7 @@ + #include "findfile.h" + #include "i_interface.h" + #include "configfile.h" ++#include "printf.h" + + //========================================================================== + // +@@ -447,6 +448,7 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all + // an empty name will pick the first one in a compatible format. + if (allowed & sfi.type && (name == nullptr || *name == 0 || !sfi.mName.CompareNoCase(name) || !sfi.mNameExt.CompareNoCase(name))) + { ++ DPrintf(DMSG_NOTIFY, "Found compatible soundfont %s\n", sfi.mNameExt.GetChars()); + return &sfi; + } + } +@@ -455,6 +457,7 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all + { + if (allowed & sfi.type) + { ++ DPrintf(DMSG_NOTIFY, "Unable to find %s soundfont. Falling back to %s\n", name, sfi.mNameExt.GetChars()); + return &sfi; + } + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0029-Added-check-for-invalid-class-on-in-VM-instantiation.patch b/games-fps/gzdoom/files/0029-Added-check-for-invalid-class-on-in-VM-instantiation.patch new file mode 100644 index 0000000..fa4ec25 --- /dev/null +++ b/games-fps/gzdoom/files/0029-Added-check-for-invalid-class-on-in-VM-instantiation.patch @@ -0,0 +1,25 @@ +From 79f306ee58a7276d2bf81253540f36995bedb77a Mon Sep 17 00:00:00 2001 +From: CandiceJoy +Date: Tue, 24 Jan 2023 14:23:04 -0600 +Subject: [PATCH 29/51] Added check for invalid class on in-VM instantiation + +Signed-off-by: CandiceJoy +--- + src/common/scripting/core/scopebarrier.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/common/scripting/core/scopebarrier.cpp b/src/common/scripting/core/scopebarrier.cpp +index f4d584c7b..a6c5a2370 100644 +--- a/src/common/scripting/core/scopebarrier.cpp ++++ b/src/common/scripting/core/scopebarrier.cpp +@@ -211,6 +211,7 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name) + // these are for vmexec.h + void FScopeBarrier::ValidateNew(PClass* cls, int outerside) + { ++ if (cls->VMType == nullptr) ThrowAbortException(X_OTHER,"Cannot instantiate invalid class %s", cls->TypeName.GetChars()); + int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ScopeFlags); + if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context" + ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside)); +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0030-Fixed-a-bug-where-calling-an-invalid-virtual-functio.patch b/games-fps/gzdoom/files/0030-Fixed-a-bug-where-calling-an-invalid-virtual-functio.patch new file mode 100644 index 0000000..c5c9836 --- /dev/null +++ b/games-fps/gzdoom/files/0030-Fixed-a-bug-where-calling-an-invalid-virtual-functio.patch @@ -0,0 +1,25 @@ +From c0945a116a60e7248bc3356a13b2fa0b49d42db1 Mon Sep 17 00:00:00 2001 +From: CandiceJoy +Date: Thu, 26 Jan 2023 07:39:58 -0600 +Subject: [PATCH 30/51] Fixed a bug where calling an invalid virtual function + would cause a crash. + +--- + src/common/scripting/vm/vmexec.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h +index 6716509da..f303304b8 100644 +--- a/src/common/scripting/vm/vmexec.h ++++ b/src/common/scripting/vm/vmexec.h +@@ -849,6 +849,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) + return 0; + } + auto p = o->GetClass(); ++ if(p->Virtuals.Size() <= 0) ThrowAbortException(X_OTHER,"Attempted to call an invalid virtual function in class %s",p->TypeName.GetChars()); + assert(C < p->Virtuals.Size()); + reg.a[a] = p->Virtuals[C]; + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0031-GLES-Fix-first-wipe.patch b/games-fps/gzdoom/files/0031-GLES-Fix-first-wipe.patch new file mode 100644 index 0000000..625a7bd --- /dev/null +++ b/games-fps/gzdoom/files/0031-GLES-Fix-first-wipe.patch @@ -0,0 +1,25 @@ +From 6e4521b749d497be67617095786f283afdb3d35c Mon Sep 17 00:00:00 2001 +From: Emile Belanger +Date: Sun, 29 Jan 2023 15:56:14 +0000 +Subject: [PATCH 31/51] GLES: Fix first wipe + +--- + src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +index f60cda5e1..5a94ba0bd 100644 +--- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp ++++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +@@ -124,6 +124,8 @@ void HWViewpointBuffer::Clear() + + if (needNewPipeline) + { ++ mLastMappedIndex = UINT_MAX; ++ + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0032-Mark-const-methods-as-const-in-pseudo-generics.patch b/games-fps/gzdoom/files/0032-Mark-const-methods-as-const-in-pseudo-generics.patch new file mode 100644 index 0000000..6310d08 --- /dev/null +++ b/games-fps/gzdoom/files/0032-Mark-const-methods-as-const-in-pseudo-generics.patch @@ -0,0 +1,64 @@ +From 547904ce9a4804a6ccdf7c0ccc7dedfaa60985c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Wed, 14 Jun 2023 20:14:13 -0300 +Subject: [PATCH 32/51] Mark const methods as const in pseudo-generics + +--- + src/common/scripting/core/types.cpp | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp +index 838275dad..8a4c5bcab 100644 +--- a/src/common/scripting/core/types.cpp ++++ b/src/common/scripting/core/types.cpp +@@ -2239,7 +2239,7 @@ enum OverrideFunctionArgType { + OFN_ARG_KEY_VAL, + }; + +-template ++template + void CreateOverrideFunction(MT *self, FName name) + { + auto Fn = Create(self->BackingType, name); +@@ -2294,7 +2294,7 @@ void CreateOverrideFunction(MT *self, FName name) + argnames.Push(NAME_Value); + } + +- Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native,SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM); ++ Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native | ExtraFlags, SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM); + self->FnOverrides.Insert(name, Fn); + } + +@@ -2304,11 +2304,11 @@ PMap::PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class) + mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName()); + Size = sizeof(ZSFMap); + Align = alignof(ZSFMap); +- CreateOverrideFunction(this, NAME_Get); +- CreateOverrideFunction(this, NAME_CheckKey); +- CreateOverrideFunction(this, NAME_Insert); +- CreateOverrideFunction(this, NAME_InsertNew); +- CreateOverrideFunction(this, NAME_Remove); ++ CreateOverrideFunction< OFN_RET_VAL , OFN_ARG_KEY > (this, NAME_Get); ++ CreateOverrideFunction< OFN_RET_BOOL , OFN_ARG_KEY , VARF_ReadOnly> (this, NAME_CheckKey); ++ CreateOverrideFunction< OFN_RET_VOID , OFN_ARG_KEY_VAL > (this, NAME_Insert); ++ CreateOverrideFunction< OFN_RET_VOID , OFN_ARG_KEY > (this, NAME_InsertNew); ++ CreateOverrideFunction< OFN_RET_VOID , OFN_ARG_KEY > (this, NAME_Remove); + } + + //========================================================================== +@@ -2770,9 +2770,9 @@ PMapIterator::PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int + mDescriptiveName.Format("MapIterator<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName()); + Size = sizeof(ZSFMap); + Align = alignof(ZSFMap); +- CreateOverrideFunction(this, NAME_GetKey); +- CreateOverrideFunction(this, NAME_GetValue); +- CreateOverrideFunction(this, NAME_SetValue); ++ CreateOverrideFunction(this, NAME_GetKey); ++ CreateOverrideFunction(this, NAME_GetValue); ++ CreateOverrideFunction(this, NAME_SetValue); + } + + //========================================================================== +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0033-Fixing-GLES-mode-to-work-on-real-GLES-hardware-and-O.patch b/games-fps/gzdoom/files/0033-Fixing-GLES-mode-to-work-on-real-GLES-hardware-and-O.patch new file mode 100644 index 0000000..37611f6 --- /dev/null +++ b/games-fps/gzdoom/files/0033-Fixing-GLES-mode-to-work-on-real-GLES-hardware-and-O.patch @@ -0,0 +1,474 @@ +From adcb59e00e3f5a4e623be4b0b629b4bd8dfe933f Mon Sep 17 00:00:00 2001 +From: Emile Belanger +Date: Sat, 4 Feb 2023 22:20:05 +0000 +Subject: [PATCH 33/51] Fixing GLES mode to work on real GLES hardware and + OpenGL 2 again + +--- + src/common/rendering/gles/gles_buffers.cpp | 10 +- + src/common/rendering/gles/gles_hwtexture.cpp | 59 +++---- + .../rendering/gles/gles_renderstate.cpp | 2 +- + src/common/rendering/gles/gles_system.cpp | 153 +++++++++++------- + src/common/rendering/gles/gles_system.h | 70 +++++--- + 5 files changed, 172 insertions(+), 122 deletions(-) + +diff --git a/src/common/rendering/gles/gles_buffers.cpp b/src/common/rendering/gles/gles_buffers.cpp +index cf7b8ae97..7f56f737f 100644 +--- a/src/common/rendering/gles/gles_buffers.cpp ++++ b/src/common/rendering/gles/gles_buffers.cpp +@@ -234,8 +234,7 @@ void GLBuffer::Resize(size_t newsize) + + void GLBuffer::GPUDropSync() + { +-#if !(USE_GLES2) // Only applicable when running on desktop for now +- if (gles.useMappedBuffers && glFenceSync && glClientWaitSync) ++ if (gles.glesMode > GLES_MODE_GLES && gles.useMappedBuffers && glFenceSync && glDeleteSync) + { + if (mGLSync != NULL) + { +@@ -244,13 +243,11 @@ void GLBuffer::GPUDropSync() + + mGLSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } +-#endif + } + + void GLBuffer::GPUWaitSync() + { +-#if !(USE_GLES2) // Only applicable when running on desktop for now +- if (gles.useMappedBuffers && glFenceSync && glClientWaitSync) ++ if (gles.glesMode > GLES_MODE_GLES && gles.useMappedBuffers && glDeleteSync && glClientWaitSync) + { + GLenum status = glClientWaitSync(mGLSync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000 * 1000 * 50); // Wait for a max of 50ms... + +@@ -263,7 +260,6 @@ void GLBuffer::GPUWaitSync() + + mGLSync = NULL; + } +-#endif + } + + +@@ -318,7 +314,7 @@ void GLVertexBuffer::Bind(int *offsets) + glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.normalize, (GLsizei)mStride, (void*)(intptr_t)ofs); + else + { +- if (gles.gles3Features) ++ if (gles.glesMode >= GLES_MODE_OGL3) + glVertexAttribIPointer(i, attrinf.size, attrinf.format, (GLsizei)mStride, (void*)(intptr_t)ofs); + } + } +diff --git a/src/common/rendering/gles/gles_hwtexture.cpp b/src/common/rendering/gles/gles_hwtexture.cpp +index 43425ce7d..3f07c65d6 100644 +--- a/src/common/rendering/gles/gles_hwtexture.cpp ++++ b/src/common/rendering/gles/gles_hwtexture.cpp +@@ -130,44 +130,47 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int + + int sourcetype; + +- +-#if USE_GLES2 +- if (glTextureBytes == 1) ++ if (gles.glesMode == GLES_MODE_GLES) + { +- glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +- sourcetype = GL_ALPHA; +- texformat = GL_ALPHA; +- } +- else +- { +- sourcetype = GL_BGRA; +- texformat = GL_BGRA; +- } +-#else +- if (glTextureBytes == 1) +- { +- glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +- sourcetype = GL_RED; +- texformat = GL_RED; ++ if (glTextureBytes == 1) ++ { ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ++ sourcetype = GL_ALPHA; ++ texformat = GL_ALPHA; ++ } ++ else ++ { ++ sourcetype = GL_BGRA; // These two must be the same ++ texformat = GL_BGRA; ++ } + } + else + { +- sourcetype = GL_BGRA; +- texformat = GL_RGBA; ++ if (glTextureBytes == 1) //Use Red channel instread becuase Alpha does not work in OpenGL, swizzle later ++ { ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ++ sourcetype = GL_RED; ++ texformat = GL_RED; ++ } ++ else ++ { ++ sourcetype = GL_BGRA; ++ texformat = GL_RGBA; ++ } + } +-#endif + + glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer); + +-#if !(USE_GLES2) +- // The shader is using the alpha channel instead of red, this work on GLES but not on GL +- // So the texture uses GL_RED and this swizzels the red channel into the alpha channel +- if (glTextureBytes == 1) ++ if (gles.glesMode != GLES_MODE_GLES) + { +- GLint swizzleMask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; +- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); ++ // The shader is using the alpha channel instead of red, this work on GLES but not on GL ++ // So the texture uses GL_RED and this swizzels the red channel into the alpha channel ++ if (glTextureBytes == 1) ++ { ++ GLint swizzleMask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED }; ++ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); ++ } + } +-#endif + + if (deletebuffer && buffer) free(buffer); + +diff --git a/src/common/rendering/gles/gles_renderstate.cpp b/src/common/rendering/gles/gles_renderstate.cpp +index 87cf2681e..5995fd3b6 100644 +--- a/src/common/rendering/gles/gles_renderstate.cpp ++++ b/src/common/rendering/gles/gles_renderstate.cpp +@@ -346,7 +346,7 @@ bool FGLRenderState::ApplyShader() + activeShader->cur->muLightRange.Set(range); + } + +- if (gles.gles3Features) ++ if (gles.glesMode >= GLES_MODE_OGL3) + { + // Upload bone data + // NOTE, this is pretty inefficient, it will be reloading the same data over and over in a single frame +diff --git a/src/common/rendering/gles/gles_system.cpp b/src/common/rendering/gles/gles_system.cpp +index 22ba8cad6..bb7d61687 100644 +--- a/src/common/rendering/gles/gles_system.cpp ++++ b/src/common/rendering/gles/gles_system.cpp +@@ -12,50 +12,16 @@ EXTERN_CVAR(Bool, gl_customshader); + void setGlVersion(double glv); + + +-#if USE_GLES2 ++#if USE_GLAD_LOADER + + PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange = NULL; + PFNGLUNMAPBUFFEROESPROC glUnmapBuffer = NULL; + PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL; ++PFNGLFENCESYNCPROC glFenceSync = NULL; ++PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL; ++PFNGLDELETESYNCPROC glDeleteSync = NULL; + +-#ifdef __ANDROID__ +-#include +- +-static void* LoadGLES2Proc(const char* name) +-{ +- static void *glesLib = NULL; +- +- if(!glesLib) +- { +- int flags = RTLD_LOCAL | RTLD_NOW; +- +- glesLib = dlopen("libGLESv2_CM.so", flags); +- if(!glesLib) +- { +- glesLib = dlopen("libGLESv2.so", flags); +- } +- if(!glesLib) +- { +- glesLib = dlopen("libGLESv2.so.2", flags); +- } +- } +- +- void * ret = NULL; +- ret = dlsym(glesLib, name); +- +- if(!ret) +- { +- //LOGI("Failed to load: %s", name); +- } +- else +- { +- //LOGI("Loaded %s func OK", name); +- } +- +- return ret; +-} +- +-#elif defined _WIN32 ++#if defined _WIN32 + + #include + +@@ -80,9 +46,38 @@ static void* LoadGLES2Proc(const char* name) + } + } + ++#else ++ ++#include ++ ++static void* LoadGLES2Proc(const char* name) ++{ ++ static void* glesLib = NULL; ++ ++ if (!glesLib) ++ { ++ int flags = RTLD_LOCAL | RTLD_NOW; ++ ++ glesLib = dlopen("libGLESv2_CM.so", flags); ++ if (!glesLib) ++ { ++ glesLib = dlopen("libGLESv2.so", flags); ++ } ++ if (!glesLib) ++ { ++ glesLib = dlopen("libGLESv2.so.2", flags); ++ } ++ } ++ ++ void* ret = NULL; ++ ret = dlsym(glesLib, name); ++ ++ return ret; ++} ++ + #endif + +-#endif // USE_GLES2 ++#endif // USE_GLAD_LOADER + + static TArray m_Extensions; + +@@ -126,7 +121,7 @@ namespace OpenGLESRenderer + void InitGLES() + { + +-#if USE_GLES2 ++#if USE_GLAD_LOADER + + if (!gladLoadGLES2Loader(&LoadGLES2Proc)) + { +@@ -136,6 +131,10 @@ namespace OpenGLESRenderer + glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC)LoadGLES2Proc("glMapBufferRange"); + glUnmapBuffer = (PFNGLUNMAPBUFFEROESPROC)LoadGLES2Proc("glUnmapBuffer"); + glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)LoadGLES2Proc("glVertexAttribIPointer"); ++ ++ glFenceSync = (PFNGLFENCESYNCPROC)LoadGLES2Proc("glFenceSync"); ++ glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)LoadGLES2Proc("glClientWaitSync"); ++ glDeleteSync = (PFNGLDELETESYNCPROC)LoadGLES2Proc("glDeleteSync"); + #else + static bool first = true; + +@@ -161,48 +160,78 @@ namespace OpenGLESRenderer + { + Printf(" %s\n", m_Extensions[i].GetChars()); + } ++ const char* glVersionStr = (const char*)glGetString(GL_VERSION); ++ double glVersion = strtod(glVersionStr, NULL); + ++ Printf("GL Version parsed = %f\n", glVersion); + + gles.flags = RFL_NO_CLIP_PLANES; + + gles.useMappedBuffers = gles_use_mapped_buffer; + gles.forceGLSLv100 = gles_force_glsl_v100; + gles.maxlights = gles_max_lights_per_surface; ++ gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); + + gles.modelstring = (char*)glGetString(GL_RENDERER); + gles.vendorstring = (char*)glGetString(GL_VENDOR); + +- gl_customshader = false; ++ ++ gl_customshader = false; // Disable user shaders for GLES renderer + + GLint maxTextureSize[1]; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); +- + gles.max_texturesize = maxTextureSize[0]; + + Printf("GL_MAX_TEXTURE_SIZE: %d\n", gles.max_texturesize); + +-#if USE_GLES2 +- gles.gles3Features = false; // Enales IQM bones +- gles.shaderVersionString = "100"; + +- gles.depthStencilAvailable = CheckExtension("GL_OES_packed_depth_stencil"); +- gles.npotAvailable = CheckExtension("GL_OES_texture_npot"); +- gles.depthClampAvailable = CheckExtension("GL_EXT_depth_clamp"); +- gles.anistropicFilterAvailable = CheckExtension("GL_EXT_texture_filter_anisotropic"); +-#else +- gles.gles3Features = true; +- gles.shaderVersionString = "330"; +- gles.depthStencilAvailable = true; +- gles.npotAvailable = true; +- gles.useMappedBuffers = true; +- gles.depthClampAvailable = true; +- gles.anistropicFilterAvailable = true; +-#endif ++ // Check if running on a GLES device, version string will start with 'OpenGL ES' ++ if (!strncmp(glVersionStr, "OpenGL ES", strlen("OpenGL ES"))) ++ { ++ gles.glesMode = GLES_MODE_GLES; ++ } ++ else // Else runnning on Desktop, check OpenGL version is 3 or above ++ { ++ if (glVersion > 3.29) ++ gles.glesMode = GLES_MODE_OGL3; // 3.3 or above ++ else ++ gles.glesMode = GLES_MODE_OGL2; // Below 3.3 ++ } + +- gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); + +- const char* glversion = (const char*)glGetString(GL_VERSION); +- setGlVersion( strtod(glversion, NULL)); ++ if (gles.glesMode == GLES_MODE_GLES) ++ { ++ Printf("GLES choosing mode: GLES_MODE_GLES\n"); + ++ gles.shaderVersionString = "100"; ++ gles.depthStencilAvailable = CheckExtension("GL_OES_packed_depth_stencil"); ++ gles.npotAvailable = CheckExtension("GL_OES_texture_npot"); ++ gles.depthClampAvailable = CheckExtension("GL_EXT_depth_clamp"); ++ gles.anistropicFilterAvailable = CheckExtension("GL_EXT_texture_filter_anisotropic"); ++ } ++ else if (gles.glesMode == GLES_MODE_OGL2) ++ { ++ Printf("GLES choosing mode: GLES_MODE_OGL2\n"); ++ ++ gles.shaderVersionString = "100"; ++ gles.depthStencilAvailable = true; ++ gles.npotAvailable = true; ++ gles.useMappedBuffers = true; ++ gles.depthClampAvailable = true; ++ gles.anistropicFilterAvailable = true; ++ } ++ else if (gles.glesMode == GLES_MODE_OGL3) ++ { ++ Printf("GLES choosing mode: GLES_MODE_OGL3\n"); ++ ++ gles.shaderVersionString = "330"; ++ gles.depthStencilAvailable = true; ++ gles.npotAvailable = true; ++ gles.useMappedBuffers = true; ++ gles.depthClampAvailable = true; ++ gles.anistropicFilterAvailable = true; ++ } ++ ++ setGlVersion(glVersion); + } + } +diff --git a/src/common/rendering/gles/gles_system.h b/src/common/rendering/gles/gles_system.h +index 481c132d0..0edec6282 100644 +--- a/src/common/rendering/gles/gles_system.h ++++ b/src/common/rendering/gles/gles_system.h +@@ -23,32 +23,47 @@ + #include + #include + +-#define USE_GLES2 0 // For Desktop PC leave as 0, it will use the exisiting OpenGL context creationg code but run with the GLES2 renderer +- // Set to 1 for when comipling for a real GLES device ++#define USE_GLAD_LOADER 0 // Set to 1 to use the GLAD loader, otherwise use noramal GZDoom loader for PC + +-#if (USE_GLES2) ++#if (USE_GLAD_LOADER) + #include "glad/glad.h" + +-// Below are used extensions for GLES +-typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +-GLAPI PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange; +- +-typedef GLboolean(APIENTRYP PFNGLUNMAPBUFFEROESPROC)(GLenum target); +-GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer; +- +-typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +-GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; +- +-#define GL_DEPTH24_STENCIL8 0x88F0 +-#define GL_MAP_PERSISTENT_BIT 0x0040 +-#define GL_MAP_READ_BIT 0x0001 +-#define GL_MAP_WRITE_BIT 0x0002 +-#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +-#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +-#define GL_BGRA 0x80E1 +-#define GL_DEPTH_CLAMP 0x864F +-#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +-#define GL_INT_2_10_10_10_REV 0x8D9F ++ // Below are used extensions for GLES ++ typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); ++ GLAPI PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange; ++ ++ typedef GLboolean(APIENTRYP PFNGLUNMAPBUFFEROESPROC)(GLenum target); ++ GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer; ++ ++ typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); ++ GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; ++ ++ typedef GLsync(APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags); ++ GLAPI PFNGLFENCESYNCPROC glFenceSync; ++ ++ typedef GLenum(APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); ++ GLAPI PFNGLCLIENTWAITSYNCPROC glClientWaitSync; ++ ++ typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync); ++ GLAPI PFNGLDELETESYNCPROC glDeleteSync; ++ ++ #define GL_DEPTH24_STENCIL8 0x88F0 ++ #define GL_MAP_PERSISTENT_BIT 0x0040 ++ #define GL_MAP_READ_BIT 0x0001 ++ #define GL_MAP_WRITE_BIT 0x0002 ++ #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 ++ #define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 ++ #define GL_BGRA 0x80E1 ++ #define GL_DEPTH_CLAMP 0x864F ++ #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE ++ #define GL_INT_2_10_10_10_REV 0x8D9F ++ #define GL_RED 0x1903 ++ #define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 ++ #define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 ++ #define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 ++ #define GL_ALREADY_SIGNALED 0x911A ++ #define GL_CONDITION_SATISFIED 0x911C ++ + #else + #include "gl_load/gl_load.h" + #endif +@@ -66,6 +81,13 @@ GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; + + namespace OpenGLESRenderer + { ++ enum ++ { ++ GLES_MODE_GLES = 0, ++ GLES_MODE_OGL2 = 1, ++ GLES_MODE_OGL3 = 2, ++ }; ++ + struct RenderContextGLES + { + unsigned int flags; +@@ -77,7 +99,7 @@ namespace OpenGLESRenderer + bool forceGLSLv100; + bool depthClampAvailable; + bool anistropicFilterAvailable; +- bool gles3Features; ++ int glesMode; + const char* shaderVersionString; + int max_texturesize; + char* vendorstring; +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0034-Fix-Software-Slope-Rendering-for-non-1.2-pixel-ratio.patch b/games-fps/gzdoom/files/0034-Fix-Software-Slope-Rendering-for-non-1.2-pixel-ratio.patch new file mode 100644 index 0000000..eb7636a --- /dev/null +++ b/games-fps/gzdoom/files/0034-Fix-Software-Slope-Rendering-for-non-1.2-pixel-ratio.patch @@ -0,0 +1,26 @@ +From fad3284bde35899cb24189cba60fae7ca56ce9ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Fri, 17 Feb 2023 16:11:39 -0300 +Subject: [PATCH 34/51] Fix Software Slope Rendering for non-1.2 pixel ratios + +--- + src/rendering/swrenderer/viewport/r_viewport.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/rendering/swrenderer/viewport/r_viewport.cpp b/src/rendering/swrenderer/viewport/r_viewport.cpp +index aa455cf06..63606d467 100644 +--- a/src/rendering/swrenderer/viewport/r_viewport.cpp ++++ b/src/rendering/swrenderer/viewport/r_viewport.cpp +@@ -172,6 +172,9 @@ namespace swrenderer + + WallTMapScale2 = IYaspectMul / CenterX * 1.2 / ypixelstretch; + ++ // [RicardoLuis0] adjust IYaspectMul for map stretch -- fixes slope rendering on maps that define pixelratio ++ IYaspectMul *= 1.2 / ypixelstretch; ++ + // thing clipping + fillshort(screenheightarray, viewwidth, (short)viewheight); + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0035-Improve-Services.patch b/games-fps/gzdoom/files/0035-Improve-Services.patch new file mode 100644 index 0000000..ef32376 --- /dev/null +++ b/games-fps/gzdoom/files/0035-Improve-Services.patch @@ -0,0 +1,191 @@ +From ab19c639264fca169dac6f0052dce38bc1c2dab5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sat, 18 Feb 2023 23:28:54 -0300 +Subject: [PATCH 35/51] Improve Services + +--- + src/common/scripting/interface/vmnatives.cpp | 7 +++ + src/gamedata/info.cpp | 27 +++++++++++ + wadsrc/static/zscript/engine/base.zs | 1 + + wadsrc/static/zscript/engine/service.zs | 49 ++++++-------------- + 4 files changed, 48 insertions(+), 36 deletions(-) + +diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp +index a29a6b711..f268b6e07 100644 +--- a/src/common/scripting/interface/vmnatives.cpp ++++ b/src/common/scripting/interface/vmnatives.cpp +@@ -53,6 +53,8 @@ + #include "s_soundinternal.h" + #include "i_time.h" + ++#include "maps.h" ++ + //========================================================================== + // + // status bar exports +@@ -1114,7 +1116,12 @@ DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder); + DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, loop); + DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, handle); + ++extern ZSMap AllServices; ++ + DEFINE_GLOBAL_NAMED(PClass::AllClasses, AllClasses) ++ ++DEFINE_GLOBAL(AllServices) ++ + DEFINE_GLOBAL(Bindings) + DEFINE_GLOBAL(AutomapBindings) + DEFINE_GLOBAL(generic_ui) +diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp +index 22ad8d42b..ed516a1cf 100644 +--- a/src/gamedata/info.cpp ++++ b/src/gamedata/info.cpp +@@ -54,6 +54,7 @@ + #include "g_levellocals.h" + #include "texturemanager.h" + #include "d_main.h" ++#include "maps.h" + + extern void LoadActors (); + extern void InitBotStuff(); +@@ -64,6 +65,7 @@ FRandom FState::pr_statetics("StateTics"); + + cycle_t ActionCycles; + ++void InitServices(); + + //========================================================================== + // +@@ -368,6 +370,18 @@ static void LoadAltHudStuff() + // + //========================================================================== + ++ZSMap AllServices; ++ ++static void MarkServices(){ ++ ++ ZSMap::Iterator it(AllServices); ++ ZSMap::Pair *pair; ++ while (it.NextPair(pair)) ++ { ++ GC::Mark(pair->Value); ++ } ++} ++ + void PClassActor::StaticInit() + { + sprites.Clear(); +@@ -402,6 +416,19 @@ void PClassActor::StaticInit() + } + } + ++ PClass * cls = PClass::FindClass("Service"); ++ for(PClass * clss : PClass::AllClasses) ++ { ++ if(clss != cls && cls->IsAncestorOf(clss)) ++ { ++ DObject * obj = clss->CreateNew(); ++ obj->ObjectFlags |= OF_Transient; ++ AllServices.Insert(clss->TypeName, obj); ++ } ++ } ++ ++ GC::AddMarkerFunc(&MarkServices); ++ + LoadAltHudStuff(); + InitBotStuff(); + +diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs +index cd2269661..43b998541 100644 +--- a/wadsrc/static/zscript/engine/base.zs ++++ b/wadsrc/static/zscript/engine/base.zs +@@ -181,6 +181,7 @@ struct Vector3 + struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this. + { + native readonly Array AllClasses; ++ native internal readonly Map AllServices; + native readonly bool multiplayer; + native @KeyBindings Bindings; + native @KeyBindings AutomapBindings; +diff --git a/wadsrc/static/zscript/engine/service.zs b/wadsrc/static/zscript/engine/service.zs +index 5f834a809..50981ad80 100644 +--- a/wadsrc/static/zscript/engine/service.zs ++++ b/wadsrc/static/zscript/engine/service.zs +@@ -54,6 +54,10 @@ class Service abstract + { + return null; + } ++ ++ static Service Find(class serviceName){ ++ return AllServices.GetIfExists(serviceName.GetClassName()); ++ } + } + + /** +@@ -88,54 +92,27 @@ class ServiceIterator + static ServiceIterator Find(String serviceName) + { + let result = new("ServiceIterator"); +- +- result.mServiceName = serviceName; +- result.mClassIndex = 0; +- result.FindNextService(); +- ++ result.mServiceName = serviceName.MakeLower(); ++ result.it.Init(AllServices); + return result; + } + + /** + * Gets the service and advances the iterator. + * +- * @returns service instance, or NULL if no more servers found. +- * +- * @note Each ServiceIterator will return new instances of services. ++ * @returns service instance, or NULL if no more services found. + */ + Service Next() + { +- uint classesNumber = AllClasses.Size(); +- Service result = (mClassIndex == classesNumber) +- ? NULL +- : Service(new(AllClasses[mClassIndex])); +- +- ++mClassIndex; +- FindNextService(); +- +- return result; +- } +- +- private void FindNextService() +- { +- uint classesNumber = AllClasses.size(); +- while (mClassIndex < classesNumber && !ServiceNameContains(AllClasses[mClassIndex], mServiceName)) ++ while(it.Next()) + { +- ++mClassIndex; ++ String cName = it.GetKey(); ++ if(cName.MakeLower().IndexOf(mServiceName) != -1); ++ return it.GetValue(); + } ++ return null; + } + +- private static bool ServiceNameContains(class aClass, String substring) +- { +- if (!(aClass is "Service")) return false; +- +- String className = aClass.GetClassName(); +- String lowerClassName = className.MakeLower(); +- String lowerSubstring = substring.MakeLower(); +- bool result = lowerClassName.IndexOf(lowerSubstring) != -1; +- return result; +- } +- ++ private MapIterator it; + private String mServiceName; +- private uint mClassIndex; + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0036-fixed-typo-in-string-label.patch b/games-fps/gzdoom/files/0036-fixed-typo-in-string-label.patch new file mode 100644 index 0000000..ee9ef49 --- /dev/null +++ b/games-fps/gzdoom/files/0036-fixed-typo-in-string-label.patch @@ -0,0 +1,25 @@ +From 3c25b83096cda917250ef3d45dde3af297413ec1 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sun, 19 Feb 2023 12:47:16 +0100 +Subject: [PATCH 36/51] - fixed typo in string label. + +--- + src/g_game.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/g_game.cpp b/src/g_game.cpp +index 4a3398fde..c960bab26 100644 +--- a/src/g_game.cpp ++++ b/src/g_game.cpp +@@ -2015,7 +2015,7 @@ void G_DoLoadGame () + } + else + { +- LoadGameError("TXT_IOTHERENGINESG", engine.GetChars()); ++ LoadGameError("TXT_OTHERENGINESG", engine.GetChars()); + } + return; + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0037-Update-service.zs.patch b/games-fps/gzdoom/files/0037-Update-service.zs.patch new file mode 100644 index 0000000..ee5796c --- /dev/null +++ b/games-fps/gzdoom/files/0037-Update-service.zs.patch @@ -0,0 +1,26 @@ +From e160c86c1fac9fcc1336fd81c772af5ad588be1e Mon Sep 17 00:00:00 2001 +From: Rachael Alexanderson <18584402+madame-rachelle@users.noreply.github.com> +Date: Sun, 19 Feb 2023 10:14:36 -0500 +Subject: [PATCH 37/51] Update service.zs + +remove erroneous semicolon +--- + wadsrc/static/zscript/engine/service.zs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/wadsrc/static/zscript/engine/service.zs b/wadsrc/static/zscript/engine/service.zs +index 50981ad80..26102b0a2 100644 +--- a/wadsrc/static/zscript/engine/service.zs ++++ b/wadsrc/static/zscript/engine/service.zs +@@ -107,7 +107,7 @@ class ServiceIterator + while(it.Next()) + { + String cName = it.GetKey(); +- if(cName.MakeLower().IndexOf(mServiceName) != -1); ++ if(cName.MakeLower().IndexOf(mServiceName) != -1) + return it.GetValue(); + } + return null; +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0038-Allow-GAMEINFO-LOAD-to-load-directories.patch b/games-fps/gzdoom/files/0038-Allow-GAMEINFO-LOAD-to-load-directories.patch new file mode 100644 index 0000000..7ce9144 --- /dev/null +++ b/games-fps/gzdoom/files/0038-Allow-GAMEINFO-LOAD-to-load-directories.patch @@ -0,0 +1,34 @@ +From 698d335ff71d4ad4c830d566ab445ee43aa7c815 Mon Sep 17 00:00:00 2001 +From: John Stebbins +Date: Thu, 23 Feb 2023 07:32:58 -0700 +Subject: [PATCH 38/51] Allow GAMEINFO LOAD to load directories + +Addresses part of enhancement issue #2011 +--- + src/d_main.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/d_main.cpp b/src/d_main.cpp +index 5bf8e8928..b34c480ff 100644 +--- a/src/d_main.cpp ++++ b/src/d_main.cpp +@@ -1773,6 +1773,7 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char + FScanner sc; + FString iwad; + int pos = 0; ++ bool isDir; + + const char *lastSlash = strrchr (fn, '/'); + +@@ -1806,7 +1807,7 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char + { + checkpath = sc.String; + } +- if (!FileExists(checkpath)) ++ if (!DirEntryExists(checkpath, &isDir)) + { + pos += D_AddFile(pwads, sc.String, true, pos, GameConfig); + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0039-fixed-bad-character-offset.patch b/games-fps/gzdoom/files/0039-fixed-bad-character-offset.patch new file mode 100644 index 0000000..69ae324 --- /dev/null +++ b/games-fps/gzdoom/files/0039-fixed-bad-character-offset.patch @@ -0,0 +1,21 @@ +From 5b7dd42431b471113b82b1f72aa0f918bc8da641 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sat, 4 Mar 2023 10:46:37 +0100 +Subject: [PATCH 39/51] - fixed bad character offset. + +--- + .../filter/doom.id/fonts/defsmallfont/0419.lmp | Bin 152 -> 152 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +diff --git a/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0419.lmp b/wadsrc_extra/static/filter/doom.id/fonts/defsmallfont/0419.lmp +index c48e80d4f5e61683385155fc0ded67d91f17acf5..a861df892f13a777b2118a848b230b9cc2d595a8 100644 +GIT binary patch +delta 15 +WcmbQiID?U$gMo{Ifq{7<`$PZ~6ashv + +delta 15 +VcmbQiID?U$gMo_y2qv;m1OOBW0(AfY + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0040-Fixed-incorrect-parameter-type-in-A_CheckForResurrec.patch b/games-fps/gzdoom/files/0040-Fixed-incorrect-parameter-type-in-A_CheckForResurrec.patch new file mode 100644 index 0000000..cf84ca3 --- /dev/null +++ b/games-fps/gzdoom/files/0040-Fixed-incorrect-parameter-type-in-A_CheckForResurrec.patch @@ -0,0 +1,26 @@ +From 9f13bb10d03bac86c19621f828d035b915182faf Mon Sep 17 00:00:00 2001 +From: CandiceJoy +Date: Fri, 17 Mar 2023 05:51:06 -0500 +Subject: [PATCH 40/51] Fixed incorrect parameter type in + A_CheckForResurrection. + +--- + src/scripting/vmthunks_actors.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp +index facbc59e3..25b082e23 100644 +--- a/src/scripting/vmthunks_actors.cpp ++++ b/src/scripting/vmthunks_actors.cpp +@@ -1627,7 +1627,7 @@ int CheckForResurrection(AActor *self, FState* state, int sound) + DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_CheckForResurrection, CheckForResurrection) + { + PARAM_SELF_PROLOGUE(AActor); +- PARAM_STATE(state); ++ PARAM_POINTER(state, FState); + PARAM_INT(sound); + ACTION_RETURN_BOOL(CheckForResurrection(self, state, sound)); + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0041-Fix-TArray-allocating-0-bytes-in-constructor.patch b/games-fps/gzdoom/files/0041-Fix-TArray-allocating-0-bytes-in-constructor.patch new file mode 100644 index 0000000..1d87ab4 --- /dev/null +++ b/games-fps/gzdoom/files/0041-Fix-TArray-allocating-0-bytes-in-constructor.patch @@ -0,0 +1,29 @@ +From d028abc06403377b564623479bd830d8174455ac Mon Sep 17 00:00:00 2001 +From: RaveYard +Date: Sun, 19 Mar 2023 01:43:24 +0100 +Subject: [PATCH 41/51] Fix TArray allocating 0 bytes in constructor + +--- + src/common/utility/tarray.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h +index a7decd4f3..8d7037db2 100644 +--- a/src/common/utility/tarray.h ++++ b/src/common/utility/tarray.h +@@ -222,9 +222,9 @@ public: + explicit TArray (size_t max, bool reserve = false) + { + Most = (unsigned)max; +- Count = (unsigned)(reserve? max : 0); +- Array = (T *)M_Malloc (sizeof(T)*max); +- if (reserve && Count > 0) ++ Count = (unsigned)(reserve ? max : 0); ++ Array = max > 0 ? (T *)M_Malloc (sizeof(T)*max) : nullptr; ++ if (Count > 0) + { + ConstructEmpty(0, Count - 1); + } +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0042-Use-simpler-constructor-for-TArray-in-FBlockThingsIt.patch b/games-fps/gzdoom/files/0042-Use-simpler-constructor-for-TArray-in-FBlockThingsIt.patch new file mode 100644 index 0000000..4f6c261 --- /dev/null +++ b/games-fps/gzdoom/files/0042-Use-simpler-constructor-for-TArray-in-FBlockThingsIt.patch @@ -0,0 +1,35 @@ +From e77c9f5a0e8ccc71b726050625082ada156b2672 Mon Sep 17 00:00:00 2001 +From: RaveYard +Date: Sun, 19 Mar 2023 03:41:27 +0100 +Subject: [PATCH 42/51] Use simpler constructor for TArray in + FBlockThingsIterator + +--- + src/playsim/p_maputl.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/playsim/p_maputl.cpp b/src/playsim/p_maputl.cpp +index aca40e741..f883cbc91 100644 +--- a/src/playsim/p_maputl.cpp ++++ b/src/playsim/p_maputl.cpp +@@ -889,7 +889,7 @@ void FMultiBlockLinesIterator::Reset() + //=========================================================================== + + FBlockThingsIterator::FBlockThingsIterator(FLevelLocals *l) +-: DynHash(0) ++: DynHash() + { + Level = l; + minx = maxx = 0; +@@ -899,7 +899,7 @@ FBlockThingsIterator::FBlockThingsIterator(FLevelLocals *l) + } + + FBlockThingsIterator::FBlockThingsIterator(FLevelLocals *l, int _minx, int _miny, int _maxx, int _maxy) +-: DynHash(0) ++: DynHash() + { + Level = l; + minx = _minx; +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0043-Fix-possible-memory-corruption-in-TArray-Delete-inde.patch b/games-fps/gzdoom/files/0043-Fix-possible-memory-corruption-in-TArray-Delete-inde.patch new file mode 100644 index 0000000..875a650 --- /dev/null +++ b/games-fps/gzdoom/files/0043-Fix-possible-memory-corruption-in-TArray-Delete-inde.patch @@ -0,0 +1,26 @@ +From f658338e869b47321af57838518b7346d8d495df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Wed, 22 Mar 2023 04:54:29 -0300 +Subject: [PATCH 43/51] Fix possible memory corruption in + `TArray::Delete(index, count)` + +--- + src/common/utility/tarray.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h +index 8d7037db2..cc13050b5 100644 +--- a/src/common/utility/tarray.h ++++ b/src/common/utility/tarray.h +@@ -453,6 +453,8 @@ public: + + void Delete (unsigned int index, int deletecount) + { ++ if(index >= Count) return; ++ + if (index + deletecount > Count) + { + deletecount = Count - index; +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0044-updated-RapidJson-library.patch b/games-fps/gzdoom/files/0044-updated-RapidJson-library.patch new file mode 100644 index 0000000..244b120 --- /dev/null +++ b/games-fps/gzdoom/files/0044-updated-RapidJson-library.patch @@ -0,0 +1,10357 @@ +From de043145d0d663f0e68157e236ad19621af0fb92 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sun, 26 Mar 2023 08:46:23 +0200 +Subject: [PATCH 44/51] - updated RapidJson library. + +This still needed the Nan hotfix to be reapplied. The problem hasn't been addressed yet. :( +--- + src/common/thirdparty/rapidjson/allocators.h | 534 ++++- + .../rapidjson/cursorstreamwrapper.h | 78 + + src/common/thirdparty/rapidjson/document.h | 789 +++++-- + .../thirdparty/rapidjson/encodedstream.h | 4 +- + src/common/thirdparty/rapidjson/encodings.h | 88 +- + src/common/thirdparty/rapidjson/error/en.h | 118 +- + src/common/thirdparty/rapidjson/error/error.h | 146 +- + .../thirdparty/rapidjson/filereadstream.h | 6 +- + .../thirdparty/rapidjson/filewritestream.h | 6 +- + src/common/thirdparty/rapidjson/fwd.h | 4 +- + .../rapidjson/internal/biginteger.h | 25 +- + .../thirdparty/rapidjson/internal/clzll.h | 71 + + .../thirdparty/rapidjson/internal/diyfp.h | 59 +- + .../thirdparty/rapidjson/internal/dtoa.h | 18 +- + .../thirdparty/rapidjson/internal/ieee754.h | 6 +- + .../thirdparty/rapidjson/internal/itoa.h | 84 +- + .../thirdparty/rapidjson/internal/meta.h | 11 +- + .../thirdparty/rapidjson/internal/pow10.h | 2 +- + .../thirdparty/rapidjson/internal/regex.h | 246 +- + .../thirdparty/rapidjson/internal/stack.h | 12 +- + .../thirdparty/rapidjson/internal/strfunc.h | 27 +- + .../thirdparty/rapidjson/internal/strtod.h | 122 +- + .../thirdparty/rapidjson/internal/swap.h | 2 +- + .../thirdparty/rapidjson/istreamwrapper.h | 89 +- + .../thirdparty/rapidjson/memorybuffer.h | 2 +- + .../thirdparty/rapidjson/memorystream.h | 2 +- + .../thirdparty/rapidjson/ostreamwrapper.h | 2 +- + src/common/thirdparty/rapidjson/pointer.h | 194 +- + .../thirdparty/rapidjson/prettywriter.h | 58 +- + src/common/thirdparty/rapidjson/rapidjson.h | 220 +- + src/common/thirdparty/rapidjson/reader.h | 677 ++++-- + src/common/thirdparty/rapidjson/schema.h | 1996 ++++++++++++++--- + src/common/thirdparty/rapidjson/stream.h | 54 +- + .../thirdparty/rapidjson/stringbuffer.h | 6 +- + src/common/thirdparty/rapidjson/uri.h | 481 ++++ + src/common/thirdparty/rapidjson/writer.h | 169 +- + 36 files changed, 5147 insertions(+), 1261 deletions(-) + create mode 100644 src/common/thirdparty/rapidjson/cursorstreamwrapper.h + create mode 100644 src/common/thirdparty/rapidjson/internal/clzll.h + create mode 100644 src/common/thirdparty/rapidjson/uri.h + +diff --git a/src/common/thirdparty/rapidjson/allocators.h b/src/common/thirdparty/rapidjson/allocators.h +index 98affe03f..ddcf4781b 100644 +--- a/src/common/thirdparty/rapidjson/allocators.h ++++ b/src/common/thirdparty/rapidjson/allocators.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -16,6 +16,14 @@ + #define RAPIDJSON_ALLOCATORS_H_ + + #include "rapidjson.h" ++#include "internal/meta.h" ++ ++#include ++#include ++ ++#if RAPIDJSON_HAS_CXX11 ++#include ++#endif + + RAPIDJSON_NAMESPACE_BEGIN + +@@ -52,6 +60,19 @@ concept Allocator { + \endcode + */ + ++ ++/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY ++ \ingroup RAPIDJSON_CONFIG ++ \brief User-defined kDefaultChunkCapacity definition. ++ ++ User can define this as any \c size that is a power of 2. ++*/ ++ ++#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY ++#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024) ++#endif ++ ++ + /////////////////////////////////////////////////////////////////////////////// + // CrtAllocator + +@@ -64,19 +85,26 @@ public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. +- return std::malloc(size); ++ return RAPIDJSON_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); ++ RAPIDJSON_FREE(originalPtr); + return NULL; + } +- return std::realloc(originalPtr, newSize); ++ return RAPIDJSON_REALLOC(originalPtr, newSize); ++ } ++ static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } ++ ++ bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { ++ return true; ++ } ++ bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { ++ return false; + } +- static void Free(void *ptr) { std::free(ptr); } + }; + + /////////////////////////////////////////////////////////////////////////////// +@@ -100,16 +128,64 @@ public: + */ + template + class MemoryPoolAllocator { ++ //! 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. ++ }; ++ ++ struct SharedData { ++ ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation. ++ BaseAllocator* ownBaseAllocator; //!< base allocator created by this object. ++ size_t refcount; ++ bool ownBuffer; ++ }; ++ ++ static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData)); ++ static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader)); ++ ++ static inline ChunkHeader *GetChunkHead(SharedData *shared) ++ { ++ return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA); ++ } ++ static inline uint8_t *GetChunkBuffer(SharedData *shared) ++ { ++ return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER; ++ } ++ ++ static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. ++ + public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) ++ static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ ++ explicit + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : +- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) ++ chunk_capacity_(chunkSize), ++ baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), ++ shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) + { ++ RAPIDJSON_ASSERT(baseAllocator_ != 0); ++ RAPIDJSON_ASSERT(shared_ != 0); ++ if (baseAllocator) { ++ shared_->ownBaseAllocator = 0; ++ } ++ else { ++ shared_->ownBaseAllocator = baseAllocator_; ++ } ++ shared_->chunkHead = GetChunkHead(shared_); ++ shared_->chunkHead->capacity = 0; ++ shared_->chunkHead->size = 0; ++ shared_->chunkHead->next = 0; ++ shared_->ownBuffer = true; ++ shared_->refcount = 1; + } + + //! Constructor with user-supplied buffer. +@@ -123,41 +199,101 @@ public: + \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) ++ chunk_capacity_(chunkSize), ++ baseAllocator_(baseAllocator), ++ shared_(static_cast(AlignBuffer(buffer, size))) + { +- RAPIDJSON_ASSERT(buffer != 0); +- RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); +- chunkHead_ = reinterpret_cast(buffer); +- chunkHead_->capacity = size - sizeof(ChunkHeader); +- chunkHead_->size = 0; +- chunkHead_->next = 0; ++ RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); ++ shared_->chunkHead = GetChunkHead(shared_); ++ shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; ++ shared_->chunkHead->size = 0; ++ shared_->chunkHead->next = 0; ++ shared_->ownBaseAllocator = 0; ++ shared_->ownBuffer = false; ++ shared_->refcount = 1; + } + ++ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : ++ chunk_capacity_(rhs.chunk_capacity_), ++ baseAllocator_(rhs.baseAllocator_), ++ shared_(rhs.shared_) ++ { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); ++ ++shared_->refcount; ++ } ++ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT ++ { ++ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); ++ ++rhs.shared_->refcount; ++ this->~MemoryPoolAllocator(); ++ baseAllocator_ = rhs.baseAllocator_; ++ chunk_capacity_ = rhs.chunk_capacity_; ++ shared_ = rhs.shared_; ++ return *this; ++ } ++ ++#if RAPIDJSON_HAS_CXX11_RVALUE_REFS ++ MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : ++ chunk_capacity_(rhs.chunk_capacity_), ++ baseAllocator_(rhs.baseAllocator_), ++ shared_(rhs.shared_) ++ { ++ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); ++ rhs.shared_ = 0; ++ } ++ MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT ++ { ++ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); ++ this->~MemoryPoolAllocator(); ++ baseAllocator_ = rhs.baseAllocator_; ++ chunk_capacity_ = rhs.chunk_capacity_; ++ shared_ = rhs.shared_; ++ rhs.shared_ = 0; ++ return *this; ++ } ++#endif ++ + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ +- ~MemoryPoolAllocator() { ++ ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT { ++ if (!shared_) { ++ // do nothing if moved ++ return; ++ } ++ if (shared_->refcount > 1) { ++ --shared_->refcount; ++ return; ++ } + Clear(); +- RAPIDJSON_DELETE(ownBaseAllocator_); ++ BaseAllocator *a = shared_->ownBaseAllocator; ++ if (shared_->ownBuffer) { ++ baseAllocator_->Free(shared_); ++ } ++ RAPIDJSON_DELETE(a); + } + +- //! Deallocates all memory chunks, excluding the user-supplied buffer. +- void Clear() { +- while (chunkHead_ && chunkHead_ != userBuffer_) { +- ChunkHeader* next = chunkHead_->next; +- baseAllocator_->Free(chunkHead_); +- chunkHead_ = next; ++ //! Deallocates all memory chunks, excluding the first/user one. ++ void Clear() RAPIDJSON_NOEXCEPT { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); ++ for (;;) { ++ ChunkHeader* c = shared_->chunkHead; ++ if (!c->next) { ++ break; ++ } ++ shared_->chunkHead = c->next; ++ baseAllocator_->Free(c); + } +- if (chunkHead_ && chunkHead_ == userBuffer_) +- chunkHead_->size = 0; // Clear user buffer ++ shared_->chunkHead->size = 0; + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ +- size_t Capacity() const { ++ size_t Capacity() const RAPIDJSON_NOEXCEPT { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t capacity = 0; +- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) ++ for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } +@@ -165,25 +301,35 @@ public: + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ +- size_t Size() const { ++ size_t Size() const RAPIDJSON_NOEXCEPT { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t size = 0; +- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) ++ for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + size += c->size; + return size; + } + ++ //! Whether the allocator is shared. ++ /*! \return true or false. ++ */ ++ bool Shared() const RAPIDJSON_NOEXCEPT { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); ++ return shared_->refcount > 1; ++ } ++ + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); +- if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) ++ if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity)) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + +- void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; +- chunkHead_->size += size; ++ void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; ++ shared_->chunkHead->size += size; + return buffer; + } + +@@ -192,6 +338,7 @@ public: + if (originalPtr == 0) + return Malloc(newSize); + ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (newSize == 0) + return NULL; + +@@ -203,10 +350,10 @@ public: + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space +- if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { ++ if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); +- if (chunkHead_->size + increment <= chunkHead_->capacity) { +- chunkHead_->size += increment; ++ if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) { ++ shared_->chunkHead->size += increment; + return originalPtr; + } + } +@@ -222,50 +369,325 @@ public: + } + + //! Frees a memory block (concept Allocator) +- static void Free(void *ptr) { (void)ptr; } // Do nothing ++ static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (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 */; ++ //! Compare (equality) with another MemoryPoolAllocator ++ bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { ++ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); ++ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); ++ return shared_ == rhs.shared_; ++ } ++ //! Compare (inequality) with another MemoryPoolAllocator ++ bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { ++ return !operator==(rhs); ++ } + ++private: + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) +- ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); +- if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { ++ shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); ++ if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; +- chunk->next = chunkHead_; +- chunkHead_ = chunk; ++ chunk->next = shared_->chunkHead; ++ shared_->chunkHead = chunk; + return true; + } + else + return false; + } + +- 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. +- }; ++ static inline void* AlignBuffer(void* buf, size_t &size) ++ { ++ RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); ++ const uintptr_t mask = sizeof(void*) - 1; ++ const uintptr_t ubuf = reinterpret_cast(buf); ++ if (RAPIDJSON_UNLIKELY(ubuf & mask)) { ++ const uintptr_t abuf = (ubuf + mask) & ~mask; ++ RAPIDJSON_ASSERT(size >= abuf - ubuf); ++ buf = reinterpret_cast(abuf); ++ size -= abuf - ubuf; ++ } ++ return buf; ++ } + +- 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. ++ SharedData *shared_; //!< The shared data of the allocator ++}; ++ ++namespace internal { ++ template ++ struct IsRefCounted : ++ public FalseType ++ { }; ++ template ++ struct IsRefCounted::Type> : ++ public TrueType ++ { }; ++} ++ ++template ++inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) ++{ ++ RAPIDJSON_NOEXCEPT_ASSERT(old_n <= std::numeric_limits::max() / sizeof(T) && new_n <= std::numeric_limits::max() / sizeof(T)); ++ return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); ++} ++ ++template ++inline T *Malloc(A& a, size_t n = 1) ++{ ++ return Realloc(a, NULL, 0, n); ++} ++ ++template ++inline void Free(A& a, T *p, size_t n = 1) ++{ ++ static_cast(Realloc(a, p, n, 0)); ++} ++ ++#ifdef __GNUC__ ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited ++#endif ++ ++template ++class StdAllocator : ++ public std::allocator ++{ ++ typedef std::allocator allocator_type; ++#if RAPIDJSON_HAS_CXX11 ++ typedef std::allocator_traits traits_type; ++#else ++ typedef allocator_type traits_type; ++#endif ++ ++public: ++ typedef BaseAllocator BaseAllocatorType; ++ ++ StdAllocator() RAPIDJSON_NOEXCEPT : ++ allocator_type(), ++ baseAllocator_() ++ { } ++ ++ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : ++ allocator_type(rhs), ++ baseAllocator_(rhs.baseAllocator_) ++ { } ++ ++ template ++ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : ++ allocator_type(rhs), ++ baseAllocator_(rhs.baseAllocator_) ++ { } ++ ++#if RAPIDJSON_HAS_CXX11_RVALUE_REFS ++ StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : ++ allocator_type(std::move(rhs)), ++ baseAllocator_(std::move(rhs.baseAllocator_)) ++ { } ++#endif ++#if RAPIDJSON_HAS_CXX11 ++ using propagate_on_container_move_assignment = std::true_type; ++ using propagate_on_container_swap = std::true_type; ++#endif ++ ++ /* implicit */ ++ StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : ++ allocator_type(), ++ baseAllocator_(allocator) ++ { } ++ ++ ~StdAllocator() RAPIDJSON_NOEXCEPT ++ { } ++ ++ template ++ struct rebind { ++ typedef StdAllocator other; ++ }; ++ ++ typedef typename traits_type::size_type size_type; ++ typedef typename traits_type::difference_type difference_type; ++ ++ typedef typename traits_type::value_type value_type; ++ typedef typename traits_type::pointer pointer; ++ typedef typename traits_type::const_pointer const_pointer; ++ ++#if RAPIDJSON_HAS_CXX11 ++ ++ typedef typename std::add_lvalue_reference::type &reference; ++ typedef typename std::add_lvalue_reference::type>::type &const_reference; ++ ++ pointer address(reference r) const RAPIDJSON_NOEXCEPT ++ { ++ return std::addressof(r); ++ } ++ const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT ++ { ++ return std::addressof(r); ++ } ++ ++ size_type max_size() const RAPIDJSON_NOEXCEPT ++ { ++ return traits_type::max_size(*this); ++ } ++ ++ template ++ void construct(pointer p, Args&&... args) ++ { ++ traits_type::construct(*this, p, std::forward(args)...); ++ } ++ void destroy(pointer p) ++ { ++ traits_type::destroy(*this, p); ++ } ++ ++#else // !RAPIDJSON_HAS_CXX11 ++ ++ typedef typename allocator_type::reference reference; ++ typedef typename allocator_type::const_reference const_reference; ++ ++ pointer address(reference r) const RAPIDJSON_NOEXCEPT ++ { ++ return allocator_type::address(r); ++ } ++ const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT ++ { ++ return allocator_type::address(r); ++ } ++ ++ size_type max_size() const RAPIDJSON_NOEXCEPT ++ { ++ return allocator_type::max_size(); ++ } ++ ++ void construct(pointer p, const_reference r) ++ { ++ allocator_type::construct(p, r); ++ } ++ void destroy(pointer p) ++ { ++ allocator_type::destroy(p); ++ } ++ ++#endif // !RAPIDJSON_HAS_CXX11 ++ ++ template ++ U* allocate(size_type n = 1, const void* = 0) ++ { ++ return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n); ++ } ++ template ++ void deallocate(U* p, size_type n = 1) ++ { ++ RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n); ++ } ++ ++ pointer allocate(size_type n = 1, const void* = 0) ++ { ++ return allocate(n); ++ } ++ void deallocate(pointer p, size_type n = 1) ++ { ++ deallocate(p, n); ++ } ++ ++#if RAPIDJSON_HAS_CXX11 ++ using is_always_equal = std::is_empty; ++#endif ++ ++ template ++ bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT ++ { ++ return baseAllocator_ == rhs.baseAllocator_; ++ } ++ template ++ bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT ++ { ++ return !operator==(rhs); ++ } ++ ++ //! rapidjson Allocator concept ++ static const bool kNeedFree = BaseAllocator::kNeedFree; ++ static const bool kRefCounted = internal::IsRefCounted::Value; ++ void* Malloc(size_t size) ++ { ++ return baseAllocator_.Malloc(size); ++ } ++ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) ++ { ++ return baseAllocator_.Realloc(originalPtr, originalSize, newSize); ++ } ++ static void Free(void *ptr) RAPIDJSON_NOEXCEPT ++ { ++ BaseAllocator::Free(ptr); ++ } ++ ++private: ++ template ++ friend class StdAllocator; // access to StdAllocator.* ++ ++ BaseAllocator baseAllocator_; + }; + ++#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17 ++template ++class StdAllocator : ++ public std::allocator ++{ ++ typedef std::allocator allocator_type; ++ ++public: ++ typedef BaseAllocator BaseAllocatorType; ++ ++ StdAllocator() RAPIDJSON_NOEXCEPT : ++ allocator_type(), ++ baseAllocator_() ++ { } ++ ++ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : ++ allocator_type(rhs), ++ baseAllocator_(rhs.baseAllocator_) ++ { } ++ ++ template ++ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : ++ allocator_type(rhs), ++ baseAllocator_(rhs.baseAllocator_) ++ { } ++ ++ /* implicit */ ++ StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT : ++ allocator_type(), ++ baseAllocator_(baseAllocator) ++ { } ++ ++ ~StdAllocator() RAPIDJSON_NOEXCEPT ++ { } ++ ++ template ++ struct rebind { ++ typedef StdAllocator other; ++ }; ++ ++ typedef typename allocator_type::value_type value_type; ++ ++private: ++ template ++ friend class StdAllocator; // access to StdAllocator.* ++ ++ BaseAllocator baseAllocator_; ++}; ++#endif ++ ++#ifdef __GNUC__ ++RAPIDJSON_DIAG_POP ++#endif ++ + RAPIDJSON_NAMESPACE_END + + #endif // RAPIDJSON_ENCODINGS_H_ +diff --git a/src/common/thirdparty/rapidjson/cursorstreamwrapper.h b/src/common/thirdparty/rapidjson/cursorstreamwrapper.h +new file mode 100644 +index 000000000..fd6513db1 +--- /dev/null ++++ b/src/common/thirdparty/rapidjson/cursorstreamwrapper.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. ++// ++// 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_CURSORSTREAMWRAPPER_H_ ++#define RAPIDJSON_CURSORSTREAMWRAPPER_H_ ++ ++#include "stream.h" ++ ++#if defined(__GNUC__) ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(effc++) ++#endif ++ ++#if defined(_MSC_VER) && _MSC_VER <= 1800 ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(4702) // unreachable code ++RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated ++#endif ++ ++RAPIDJSON_NAMESPACE_BEGIN ++ ++ ++//! Cursor stream wrapper for counting line and column number if error exists. ++/*! ++ \tparam InputStream Any stream that implements Stream Concept ++*/ ++template > ++class CursorStreamWrapper : public GenericStreamWrapper { ++public: ++ typedef typename Encoding::Ch Ch; ++ ++ CursorStreamWrapper(InputStream& is): ++ GenericStreamWrapper(is), line_(1), col_(0) {} ++ ++ // counting line and column number ++ Ch Take() { ++ Ch ch = this->is_.Take(); ++ if(ch == '\n') { ++ line_ ++; ++ col_ = 0; ++ } else { ++ col_ ++; ++ } ++ return ch; ++ } ++ ++ //! Get the error line number, if error exists. ++ size_t GetLine() const { return line_; } ++ //! Get the error column number, if error exists. ++ size_t GetColumn() const { return col_; } ++ ++private: ++ size_t line_; //!< Current Line ++ size_t col_; //!< Current Column ++}; ++ ++#if defined(_MSC_VER) && _MSC_VER <= 1800 ++RAPIDJSON_DIAG_POP ++#endif ++ ++#if defined(__GNUC__) ++RAPIDJSON_DIAG_POP ++#endif ++ ++RAPIDJSON_NAMESPACE_END ++ ++#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ +diff --git a/src/common/thirdparty/rapidjson/document.h b/src/common/thirdparty/rapidjson/document.h +index 9cab4e83d..2cd9a70a6 100644 +--- a/src/common/thirdparty/rapidjson/document.h ++++ b/src/common/thirdparty/rapidjson/document.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -24,33 +24,39 @@ + #include "encodedstream.h" + #include // placement new + #include +- +-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 +-RAPIDJSON_DIAG_OFF(4996) // deprecation of std::iterator ++#ifdef __cpp_lib_three_way_comparison ++#include + #endif + ++RAPIDJSON_DIAG_PUSH + #ifdef __clang__ + RAPIDJSON_DIAG_OFF(padded) + RAPIDJSON_DIAG_OFF(switch-enum) + RAPIDJSON_DIAG_OFF(c++98-compat) ++#elif defined(_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 __GNUC__ + RAPIDJSON_DIAG_OFF(effc++) +-#if __GNUC__ >= 6 +-RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions +-#endif + #endif // __GNUC__ + ++#ifdef GetObject ++// see https://github.com/Tencent/rapidjson/issues/1448 ++// a former included windows.h might have defined a macro called GetObject, which affects ++// GetObject defined here. This ensures the macro does not get applied ++#pragma push_macro("GetObject") ++#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED ++#undef GetObject ++#endif ++ + #ifndef RAPIDJSON_NOMEMBERITERATORCLASS +-#include // std::iterator, std::random_access_iterator_tag ++#include // std::random_access_iterator_tag + #endif + +-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +-#include // std::move ++#if RAPIDJSON_USE_MEMBERSMAP ++#include // std::multimap + #endif + + RAPIDJSON_NAMESPACE_BEGIN +@@ -62,6 +68,48 @@ class GenericValue; + template + class GenericDocument; + ++/*! \def RAPIDJSON_DEFAULT_ALLOCATOR ++ \ingroup RAPIDJSON_CONFIG ++ \brief Allows to choose default allocator. ++ ++ User can define this to use CrtAllocator or MemoryPoolAllocator. ++*/ ++#ifndef RAPIDJSON_DEFAULT_ALLOCATOR ++#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator> ++#endif ++ ++/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR ++ \ingroup RAPIDJSON_CONFIG ++ \brief Allows to choose default stack allocator for Document. ++ ++ User can define this to use CrtAllocator or MemoryPoolAllocator. ++*/ ++#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR ++#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator ++#endif ++ ++/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY ++ \ingroup RAPIDJSON_CONFIG ++ \brief User defined kDefaultObjectCapacity value. ++ ++ User can define this as any natural number. ++*/ ++#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY ++// number of objects that rapidjson::Value allocates memory for by default ++#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16 ++#endif ++ ++/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY ++ \ingroup RAPIDJSON_CONFIG ++ \brief User defined kDefaultArrayCapacity value. ++ ++ User can define this as any natural number. ++*/ ++#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY ++// number of array elements that rapidjson::Value allocates memory for by default ++#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16 ++#endif ++ + //! Name-value pair in a JSON object value. + /*! + This class was internal to GenericValue. It used to be a inner struct. +@@ -69,9 +117,45 @@ class GenericDocument; + https://code.google.com/p/rapidjson/issues/detail?id=64 + */ + template +-struct GenericMember { ++class GenericMember { ++public: + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. ++ ++#if RAPIDJSON_HAS_CXX11_RVALUE_REFS ++ //! Move constructor in C++11 ++ GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT ++ : name(std::move(rhs.name)), ++ value(std::move(rhs.value)) ++ { ++ } ++ ++ //! Move assignment in C++11 ++ GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT { ++ return *this = static_cast(rhs); ++ } ++#endif ++ ++ //! Assignment with move semantics. ++ /*! \param rhs Source of the assignment. Its name and value will become a null value after assignment. ++ */ ++ GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT { ++ if (RAPIDJSON_LIKELY(this != &rhs)) { ++ name = rhs.name; ++ value = rhs.value; ++ } ++ return *this; ++ } ++ ++ // swap() for std::sort() and other potential use in STL. ++ friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT { ++ a.name.Swap(b.name); ++ a.value.Swap(b.value); ++ } ++ ++private: ++ //! Copy constructor is not permitted. ++ GenericMember(const GenericMember& rhs); + }; + + /////////////////////////////////////////////////////////////////////////////// +@@ -99,16 +183,13 @@ struct GenericMember { + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ + template +-class GenericMemberIterator +- : public std::iterator >::Type> { ++class GenericMemberIterator { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; +- typedef std::iterator BaseType; + + public: + //! Iterator type itself +@@ -118,12 +199,21 @@ public: + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + ++ /** \name std::iterator_traits support */ ++ //@{ ++ typedef ValueType value_type; ++ typedef ValueType * pointer; ++ typedef ValueType & reference; ++ typedef std::ptrdiff_t difference_type; ++ typedef std::random_access_iterator_tag iterator_category; ++ //@} ++ + //! Pointer to (const) GenericMember +- typedef typename BaseType::pointer Pointer; ++ typedef pointer Pointer; + //! Reference to (const) GenericMember +- typedef typename BaseType::reference Reference; ++ typedef reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) +- typedef typename BaseType::difference_type DifferenceType; ++ typedef difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. +@@ -169,12 +259,16 @@ public: + + //! @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_; } ++ template bool operator==(const GenericMemberIterator& that) const { return ptr_ == that.ptr_; } ++ template bool operator!=(const GenericMemberIterator& that) const { return ptr_ != that.ptr_; } ++ template bool operator<=(const GenericMemberIterator& that) const { return ptr_ <= that.ptr_; } ++ template bool operator>=(const GenericMemberIterator& that) const { return ptr_ >= that.ptr_; } ++ template bool operator< (const GenericMemberIterator& that) const { return ptr_ < that.ptr_; } ++ template bool operator> (const GenericMemberIterator& that) const { return ptr_ > that.ptr_; } ++ ++#ifdef __cpp_lib_three_way_comparison ++ template std::strong_ordering operator<=>(const GenericMemberIterator& that) const { return ptr_ <=> that.ptr_; } ++#endif + //@} + + //! @name dereference +@@ -199,17 +293,19 @@ private: + // class-based member iterator implementation disabled, use plain pointers + + template +-struct GenericMemberIterator; ++class GenericMemberIterator; + + //! non-const GenericMemberIterator + template +-struct GenericMemberIterator { ++class GenericMemberIterator { ++public: + //! use plain pointer as iterator type + typedef GenericMember* Iterator; + }; + //! const GenericMemberIterator + template +-struct GenericMemberIterator { ++class GenericMemberIterator { ++public: + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; + }; +@@ -301,7 +397,7 @@ struct GenericStringRef { + */ + #endif + explicit GenericStringRef(const CharType* str) +- : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } ++ : s(str), length(NotNullStrLen(str)) {} + + //! Create constant string reference from pointer and length + #ifndef __clang__ // -Wdocumentation +@@ -313,7 +409,7 @@ struct GenericStringRef { + */ + #endif + GenericStringRef(const CharType* str, SizeType len) +- : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } ++ : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + +@@ -324,6 +420,14 @@ struct GenericStringRef { + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + + private: ++ SizeType NotNullStrLen(const CharType* str) { ++ RAPIDJSON_ASSERT(str != 0); ++ return internal::StrLen(str); ++ } ++ ++ /// Empty string - used when passing in a NULL pointer ++ static const Ch emptyString[]; ++ + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; +@@ -331,6 +435,9 @@ private: + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; + }; + ++template ++const CharType GenericStringRef::emptyString[] = { CharType() }; ++ + //! 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 +@@ -345,7 +452,7 @@ private: + */ + template + inline GenericStringRef StringRef(const CharType* str) { +- return GenericStringRef(str, internal::StrLen(str)); ++ return GenericStringRef(str); + } + + //! Mark a character pointer as constant string +@@ -435,6 +542,26 @@ struct TypeHelper { + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } + }; + ++#ifdef _MSC_VER ++RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int)); ++template ++struct TypeHelper { ++ static bool Is(const ValueType& v) { return v.IsInt(); } ++ static long Get(const ValueType& v) { return v.GetInt(); } ++ static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); } ++ static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); } ++}; ++ ++RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned)); ++template ++struct TypeHelper { ++ static bool Is(const ValueType& v) { return v.IsUint(); } ++ static unsigned long Get(const ValueType& v) { return v.GetUint(); } ++ static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); } ++ static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); } ++}; ++#endif ++ + template + struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt64(); } +@@ -508,7 +635,7 @@ struct TypeHelper { + 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; } ++ static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } + }; + + template +@@ -537,7 +664,7 @@ template class GenericObject; + \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 > ++template + class GenericValue { + public: + //! Name-value pair in an object. +@@ -591,11 +718,11 @@ public: + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { +- static const uint16_t defaultFlags[7] = { ++ static const uint16_t defaultFlags[] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; +- RAPIDJSON_ASSERT(type <= kNumberType); ++ RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. +@@ -608,10 +735,40 @@ public: + \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(). ++ \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + \see CopyFrom() + */ +- template< typename SourceAllocator > +- GenericValue(const GenericValue& rhs, Allocator & allocator); ++ template ++ GenericValue(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { ++ switch (rhs.GetType()) { ++ case kObjectType: ++ DoCopyMembers(rhs, allocator, copyConstStrings); ++ break; ++ case kArrayType: { ++ SizeType count = rhs.data_.a.size; ++ GenericValue* le = reinterpret_cast(allocator.Malloc(count * sizeof(GenericValue))); ++ const GenericValue* re = rhs.GetElementsPointer(); ++ for (SizeType i = 0; i < count; i++) ++ new (&le[i]) GenericValue(re[i], allocator, copyConstStrings); ++ data_.f.flags = kArrayFlag; ++ data_.a.size = data_.a.capacity = count; ++ SetElementsPointer(le); ++ } ++ break; ++ case kStringType: ++ if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) { ++ data_.f.flags = rhs.data_.f.flags; ++ data_ = *reinterpret_cast(&rhs.data_); ++ } ++ else ++ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); ++ break; ++ default: ++ data_.f.flags = rhs.data_.f.flags; ++ data_ = *reinterpret_cast(&rhs.data_); ++ break; ++ } ++ } + + //! Constructor for boolean value. + /*! \param b Boolean value +@@ -673,6 +830,9 @@ public: + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + ++ //! Constructor for float value. ++ explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast(f); 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)); } + +@@ -718,25 +878,30 @@ public: + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { +- if (Allocator::kNeedFree) { // Shortcut by Allocator's trait ++ // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release ++ // their Allocator if it's refcounted (e.g. MemoryPoolAllocator). ++ if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 && ++ internal::IsRefCounted::Value)) { + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); +- Allocator::Free(e); ++ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait ++ Allocator::Free(e); ++ } + } + break; + + case kObjectFlag: +- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) +- m->~Member(); +- Allocator::Free(GetMembersPointer()); ++ DoFreeMembers(); + break; + + case kCopyStringFlag: +- Allocator::Free(const_cast(GetStringPointer())); ++ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait ++ Allocator::Free(const_cast(GetStringPointer())); ++ } + break; + + default: +@@ -754,9 +919,15 @@ public: + /*! \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); ++ if (RAPIDJSON_LIKELY(this != &rhs)) { ++ // Can't destroy "this" before assigning "rhs", otherwise "rhs" ++ // could be used after free if it's an sub-Value of "this", ++ // hence the temporary danse. ++ GenericValue temp; ++ temp.RawAssign(rhs); ++ this->~GenericValue(); ++ RawAssign(temp); ++ } + return *this; + } + +@@ -801,12 +972,13 @@ public: + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying ++ \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + */ + template +- GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { ++ GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); + this->~GenericValue(); +- new (this) GenericValue(rhs, allocator); ++ new (this) GenericValue(rhs, allocator, copyConstStrings); + return *this; + } + +@@ -847,7 +1019,7 @@ public: + //! 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). ++ \note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { +@@ -906,6 +1078,7 @@ public: + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + ++#ifndef __cpp_impl_three_way_comparison + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ +@@ -930,6 +1103,7 @@ public: + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} ++#endif + + //!@name Type + //@{ +@@ -956,14 +1130,14 @@ public: + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) +- && (d < static_cast(std::numeric_limits::max())) ++ && (d < static_cast((std::numeric_limits::max)())) + && (u == static_cast(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast(i); +- return (d >= static_cast(std::numeric_limits::min())) +- && (d < static_cast(std::numeric_limits::max())) ++ return (d >= static_cast((std::numeric_limits::min)())) ++ && (d < static_cast((std::numeric_limits::max)())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless +@@ -980,8 +1154,8 @@ public: + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); +- if (a < static_cast(-std::numeric_limits::max()) +- || a > static_cast(std::numeric_limits::max())) ++ if (a < static_cast(-(std::numeric_limits::max)()) ++ || a > static_cast((std::numeric_limits::max)())) + return false; + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal +@@ -1016,6 +1190,9 @@ public: + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + ++ //! Get the capacity of object. ++ SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; } ++ + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + +@@ -1053,13 +1230,28 @@ public: + 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)]; ++#if RAPIDJSON_HAS_CXX11 ++ // Use thread-local storage to prevent races between threads. ++ // Use static buffer and placement-new to prevent destruction, with ++ // alignas() to ensure proper alignment. ++ alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)]; ++ return *new (buffer) GenericValue(); ++#elif defined(_MSC_VER) && _MSC_VER < 1900 ++ // There's no way to solve both thread locality and proper alignment ++ // simultaneously. ++ __declspec(thread) static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); ++#elif defined(__GNUC__) || defined(__clang__) ++ // This will generate -Wexit-time-destructors in clang, but that's ++ // better than having under-alignment. ++ __thread static GenericValue buffer; ++ return buffer; ++#else ++ // Don't know what compiler this is, so don't know how to ensure ++ // thread-locality. ++ static GenericValue buffer; ++ return buffer; ++#endif + } + } + template +@@ -1084,6 +1276,18 @@ public: + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + ++ //! Request the object to have enough capacity to store members. ++ /*! \param newCapacity The capacity that the object 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& MemberReserve(SizeType newCapacity, Allocator &allocator) { ++ RAPIDJSON_ASSERT(IsObject()); ++ DoReserveMembers(newCapacity, allocator); ++ return *this; ++ } ++ + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. +@@ -1154,11 +1358,7 @@ public: + MemberIterator FindMember(const GenericValue& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); +- MemberIterator member = MemberBegin(); +- for ( ; member != MemberEnd(); ++member) +- if (name.StringEqual(member->name)) +- break; +- return member; ++ return DoFindMember(name); + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + +@@ -1187,23 +1387,7 @@ public: + 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(allocator.Malloc(o.capacity * sizeof(Member)))); +- } +- else { +- SizeType oldCapacity = o.capacity; +- o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 +- SetMembersPointer(reinterpret_cast(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++; ++ DoAddMember(name, value, allocator); + return *this; + } + +@@ -1337,9 +1521,7 @@ public: + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); +- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) +- m->~Member(); +- data_.o.size = 0; ++ DoClearMembers(); + } + + //! Remove a member in object by its name. +@@ -1383,14 +1565,7 @@ public: + 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; ++ return DoRemoveMember(m); + } + + //! Remove a member from an object by iterator. +@@ -1422,13 +1597,7 @@ public: + 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(MemberEnd() - last) * sizeof(Member)); +- data_.o.size -= static_cast(last - first); +- return pos; ++ return DoEraseMembers(first, last); + } + + //! Erase a member in object by its name. +@@ -1457,7 +1626,9 @@ public: + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } ++ Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } ++ ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + +@@ -1629,8 +1800,8 @@ public: + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) +- itr->~GenericValue(); +- std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); ++ itr->~GenericValue(); ++ std::memmove(static_cast(pos), last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); + return pos; + } +@@ -1672,19 +1843,19 @@ public: + 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; } ++ GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast(f)); return *this; } + + //@} + + //!@name String + //@{ + +- const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } ++ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); } + + //! 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); } ++ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); } + + //! 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. +@@ -1711,7 +1882,7 @@ public: + \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; } ++ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string. +@@ -1719,7 +1890,15 @@ public: + \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); } ++ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); } ++ ++ //! Set this value as a string by copying from source string. ++ /*! \param s source string reference ++ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). ++ \return The value itself for fluent API. ++ \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length ++ */ ++ GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; } + + #if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. +@@ -1729,7 +1908,7 @@ public: + \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& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } ++ GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(StringRef(s), allocator); } + #endif + + //@} +@@ -1787,7 +1966,7 @@ public: + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; +- for (const GenericValue* v = Begin(); v != End(); ++v) ++ for (ConstValueIterator v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); +@@ -1823,25 +2002,26 @@ private: + + // 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, ++ // These casts are added to suppress the warning on MSVC about bitwise operations between enums of different types. ++ kTrueFlag = static_cast(kTrueType) | static_cast(kBoolFlag), ++ kFalseFlag = static_cast(kFalseType) | static_cast(kBoolFlag), ++ kNumberIntFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag), ++ kNumberUintFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag), ++ kNumberInt64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kInt64Flag), ++ kNumberUint64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kUint64Flag), ++ kNumberDoubleFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kDoubleFlag), ++ kNumberAnyFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag), ++ kConstStringFlag = static_cast(kStringType) | static_cast(kStringFlag), ++ kCopyStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag), ++ kShortStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag | kInlineStrFlag), + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + +- static const SizeType kDefaultArrayCapacity = 16; +- static const SizeType kDefaultObjectCapacity = 16; ++ static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY; ++ static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY; + + struct Flag { + #if RAPIDJSON_48BITPOINTER_OPTIMIZATION +@@ -1924,6 +2104,13 @@ private: + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + ++ static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) { ++ return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str); ++ } ++ static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) { ++ return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length; ++ } ++ + 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); } +@@ -1931,13 +2118,293 @@ private: + 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); } + ++#if RAPIDJSON_USE_MEMBERSMAP ++ ++ struct MapTraits { ++ struct Less { ++ bool operator()(const Data& s1, const Data& s2) const { ++ SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2); ++ int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2)); ++ return cmp < 0 || (cmp == 0 && n1 < n2); ++ } ++ }; ++ typedef std::pair Pair; ++ typedef std::multimap > Map; ++ typedef typename Map::iterator Iterator; ++ }; ++ typedef typename MapTraits::Map Map; ++ typedef typename MapTraits::Less MapLess; ++ typedef typename MapTraits::Pair MapPair; ++ typedef typename MapTraits::Iterator MapIterator; ++ ++ // ++ // Layout of the members' map/array, re(al)located according to the needed capacity: ++ // ++ // {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]} ++ // ++ // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed) ++ // ++ ++ static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) { ++ return RAPIDJSON_ALIGN(sizeof(Map*)) + ++ RAPIDJSON_ALIGN(sizeof(SizeType)) + ++ RAPIDJSON_ALIGN(capacity * sizeof(Member)) + ++ capacity * sizeof(MapIterator); ++ } ++ ++ static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) { ++ return *reinterpret_cast(reinterpret_cast(&map) + ++ RAPIDJSON_ALIGN(sizeof(Map*))); ++ } ++ ++ static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) { ++ return reinterpret_cast(reinterpret_cast(&map) + ++ RAPIDJSON_ALIGN(sizeof(Map*)) + ++ RAPIDJSON_ALIGN(sizeof(SizeType))); ++ } ++ ++ static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) { ++ return reinterpret_cast(reinterpret_cast(&map) + ++ RAPIDJSON_ALIGN(sizeof(Map*)) + ++ RAPIDJSON_ALIGN(sizeof(SizeType)) + ++ RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member))); ++ } ++ ++ static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) { ++ RAPIDJSON_ASSERT(members != 0); ++ return *reinterpret_cast(reinterpret_cast(members) - ++ RAPIDJSON_ALIGN(sizeof(SizeType)) - ++ RAPIDJSON_ALIGN(sizeof(Map*))); ++ } ++ ++ // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting.. ++ RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) { ++#if RAPIDJSON_HAS_CXX11 ++ MapIterator ret = std::move(rhs); ++#else ++ MapIterator ret = rhs; ++#endif ++ rhs.~MapIterator(); ++ return ret; ++ } ++ ++ Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) { ++ Map **newMap = static_cast(allocator.Malloc(GetMapLayoutSize(newCapacity))); ++ GetMapCapacity(*newMap) = newCapacity; ++ if (!oldMap) { ++ *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator); ++ } ++ else { ++ *newMap = *oldMap; ++ size_t count = (*oldMap)->size(); ++ std::memcpy(static_cast(GetMapMembers(*newMap)), ++ static_cast(GetMapMembers(*oldMap)), ++ count * sizeof(Member)); ++ MapIterator *oldIt = GetMapIterators(*oldMap), ++ *newIt = GetMapIterators(*newMap); ++ while (count--) { ++ new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count])); ++ } ++ Allocator::Free(oldMap); ++ } ++ return *newMap; ++ } ++ ++ RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { ++ return GetMapMembers(DoReallocMap(0, capacity, allocator)); ++ } ++ ++ void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { ++ ObjectData& o = data_.o; ++ if (newCapacity > o.capacity) { ++ Member* oldMembers = GetMembersPointer(); ++ Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0, ++ *&newMap = DoReallocMap(oldMap, newCapacity, allocator); ++ RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap)); ++ o.capacity = newCapacity; ++ } ++ } ++ ++ template ++ MemberIterator DoFindMember(const GenericValue& name) { ++ if (Member* members = GetMembersPointer()) { ++ Map* &map = GetMap(members); ++ MapIterator mit = map->find(reinterpret_cast(name.data_)); ++ if (mit != map->end()) { ++ return MemberIterator(&members[mit->second]); ++ } ++ } ++ return MemberEnd(); ++ } ++ ++ void DoClearMembers() { ++ if (Member* members = GetMembersPointer()) { ++ Map* &map = GetMap(members); ++ MapIterator* mit = GetMapIterators(map); ++ for (SizeType i = 0; i < data_.o.size; i++) { ++ map->erase(DropMapIterator(mit[i])); ++ members[i].~Member(); ++ } ++ data_.o.size = 0; ++ } ++ } ++ ++ void DoFreeMembers() { ++ if (Member* members = GetMembersPointer()) { ++ GetMap(members)->~Map(); ++ for (SizeType i = 0; i < data_.o.size; i++) { ++ members[i].~Member(); ++ } ++ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait ++ Map** map = &GetMap(members); ++ Allocator::Free(*map); ++ Allocator::Free(map); ++ } ++ } ++ } ++ ++#else // !RAPIDJSON_USE_MEMBERSMAP ++ ++ RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { ++ return Malloc(allocator, capacity); ++ } ++ ++ void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { ++ ObjectData& o = data_.o; ++ if (newCapacity > o.capacity) { ++ Member* newMembers = Realloc(allocator, GetMembersPointer(), o.capacity, newCapacity); ++ RAPIDJSON_SETPOINTER(Member, o.members, newMembers); ++ o.capacity = newCapacity; ++ } ++ } ++ ++ template ++ MemberIterator DoFindMember(const GenericValue& name) { ++ MemberIterator member = MemberBegin(); ++ for ( ; member != MemberEnd(); ++member) ++ if (name.StringEqual(member->name)) ++ break; ++ return member; ++ } ++ ++ void DoClearMembers() { ++ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) ++ m->~Member(); ++ data_.o.size = 0; ++ } ++ ++ void DoFreeMembers() { ++ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) ++ m->~Member(); ++ Allocator::Free(GetMembersPointer()); ++ } ++ ++#endif // !RAPIDJSON_USE_MEMBERSMAP ++ ++ void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { ++ ObjectData& o = data_.o; ++ if (o.size >= o.capacity) ++ DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator); ++ Member* members = GetMembersPointer(); ++ Member* m = members + o.size; ++ m->name.RawAssign(name); ++ m->value.RawAssign(value); ++#if RAPIDJSON_USE_MEMBERSMAP ++ Map* &map = GetMap(members); ++ MapIterator* mit = GetMapIterators(map); ++ new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size))); ++#endif ++ ++o.size; ++ } ++ ++ MemberIterator DoRemoveMember(MemberIterator m) { ++ ObjectData& o = data_.o; ++ Member* members = GetMembersPointer(); ++#if RAPIDJSON_USE_MEMBERSMAP ++ Map* &map = GetMap(members); ++ MapIterator* mit = GetMapIterators(map); ++ SizeType mpos = static_cast(&*m - members); ++ map->erase(DropMapIterator(mit[mpos])); ++#endif ++ MemberIterator last(members + (o.size - 1)); ++ if (o.size > 1 && m != last) { ++#if RAPIDJSON_USE_MEMBERSMAP ++ new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members])); ++ mit[mpos]->second = mpos; ++#endif ++ *m = *last; // Move the last one to this place ++ } ++ else { ++ m->~Member(); // Only one left, just destroy ++ } ++ --o.size; ++ return m; ++ } ++ ++ MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) { ++ ObjectData& o = data_.o; ++ MemberIterator beg = MemberBegin(), ++ pos = beg + (first - beg), ++ end = MemberEnd(); ++#if RAPIDJSON_USE_MEMBERSMAP ++ Map* &map = GetMap(GetMembersPointer()); ++ MapIterator* mit = GetMapIterators(map); ++#endif ++ for (MemberIterator itr = pos; itr != last; ++itr) { ++#if RAPIDJSON_USE_MEMBERSMAP ++ map->erase(DropMapIterator(mit[itr - beg])); ++#endif ++ itr->~Member(); ++ } ++#if RAPIDJSON_USE_MEMBERSMAP ++ if (first != last) { ++ // Move remaining members/iterators ++ MemberIterator next = pos + (last - first); ++ for (MemberIterator itr = pos; next != end; ++itr, ++next) { ++ std::memcpy(static_cast(&*itr), &*next, sizeof(Member)); ++ SizeType mpos = static_cast(itr - beg); ++ new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg])); ++ mit[mpos]->second = mpos; ++ } ++ } ++#else ++ std::memmove(static_cast(&*pos), &*last, ++ static_cast(end - last) * sizeof(Member)); ++#endif ++ o.size -= static_cast(last - first); ++ return pos; ++ } ++ ++ template ++ void DoCopyMembers(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings) { ++ RAPIDJSON_ASSERT(rhs.GetType() == kObjectType); ++ ++ data_.f.flags = kObjectFlag; ++ SizeType count = rhs.data_.o.size; ++ Member* lm = DoAllocMembers(count, allocator); ++ const typename GenericValue::Member* rm = rhs.GetMembersPointer(); ++#if RAPIDJSON_USE_MEMBERSMAP ++ Map* &map = GetMap(lm); ++ MapIterator* mit = GetMapIterators(map); ++#endif ++ for (SizeType i = 0; i < count; i++) { ++ new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); ++ new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); ++#if RAPIDJSON_USE_MEMBERSMAP ++ new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i))); ++#endif ++ } ++ data_.o.size = data_.o.capacity = count; ++ SetMembersPointer(lm); ++ } ++ + // 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(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); +- std::memcpy((void*)e, (void*)values, count * sizeof(GenericValue)); ++ std::memcpy(static_cast(e), values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); +@@ -1948,9 +2415,16 @@ private: + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { +- Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); ++ Member* m = DoAllocMembers(count, allocator); + SetMembersPointer(m); +- std::memcpy((void*)m, (void*)members, count * sizeof(Member)); ++ std::memcpy(static_cast(m), members, count * sizeof(Member)); ++#if RAPIDJSON_USE_MEMBERSMAP ++ Map* &map = GetMap(m); ++ MapIterator* mit = GetMapIterators(map); ++ for (SizeType i = 0; i < count; i++) { ++ new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i))); ++ } ++#endif + } + else + SetMembersPointer(0); +@@ -2021,12 +2495,13 @@ typedef GenericValue > Value; + \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 StackAllocator = CrtAllocator> ++template + class GenericDocument : public GenericValue { + public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. ++ typedef StackAllocator StackAllocatorType; //!< StackAllocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. +@@ -2039,7 +2514,7 @@ public: + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) +- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ++ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + //! Constructor +@@ -2052,7 +2527,7 @@ public: + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) +- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ++ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + #if RAPIDJSON_HAS_CXX11_RVALUE_REFS +@@ -2071,6 +2546,13 @@ public: + #endif + + ~GenericDocument() { ++ // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType() ++ // runs last and may access its elements or members which would be freed ++ // with an allocator like MemoryPoolAllocator (CrtAllocator does not ++ // free its data when destroyed, but MemoryPoolAllocator does). ++ if (ownAllocator_) { ++ ValueType::SetNull(); ++ } + Destroy(); + } + +@@ -2113,6 +2595,10 @@ public: + return *this; + } + ++ // Allow Swap with ValueType. ++ // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names. ++ using ValueType::Swap; ++ + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: +@@ -2244,7 +2730,7 @@ public: + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); +- MemoryStream ms(static_cast(str), length * sizeof(typename SourceEncoding::Ch)); ++ MemoryStream ms(reinterpret_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; +@@ -2281,7 +2767,7 @@ public: + //!@name Handling parse errors + //!@{ + +- //! Whether a parse error has occured in the last parsing. ++ //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. +@@ -2402,34 +2888,6 @@ private: + //! GenericDocument with UTF8 encoding + typedef GenericDocument > Document; + +-// defined here due to the dependency on GenericDocument +-template +-template +-inline +-GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) +-{ +- switch (rhs.GetType()) { +- case kObjectType: +- case kArrayType: { // perform deep copy via SAX Handler +- GenericDocument d(&allocator); +- rhs.Accept(d); +- RawAssign(*d.stack_.template Pop(1)); +- } +- break; +- case kStringType: +- if (rhs.data_.f.flags == kConstStringFlag) { +- data_.f.flags = rhs.data_.f.flags; +- data_ = *reinterpret_cast(&rhs.data_); +- } else { +- SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); +- } +- break; +- default: +- data_.f.flags = rhs.data_.f.flags; +- data_ = *reinterpret_cast(&rhs.data_); +- break; +- } +-} + + //! Helper class for accessing Value of array type. + /*! +@@ -2455,6 +2913,7 @@ public: + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + ++ operator ValueType&() const { return value_; } + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } +@@ -2510,7 +2969,9 @@ public: + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + ++ operator ValueType&() const { return value_; } + SizeType MemberCount() const { return value_.MemberCount(); } ++ SizeType MemberCapacity() const { return value_.MemberCapacity(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template ValueType& operator[](T* name) const { return value_[name]; } + template ValueType& operator[](const GenericValue& name) const { return value_[name]; } +@@ -2519,6 +2980,7 @@ public: + #endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } ++ GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } + #if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } +@@ -2544,7 +3006,7 @@ public: + 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 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +- void RemoveAllMembers() { return value_.RemoveAllMembers(); } ++ void RemoveAllMembers() { value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } + #if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } +@@ -2573,4 +3035,9 @@ private: + RAPIDJSON_NAMESPACE_END + RAPIDJSON_DIAG_POP + ++#ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED ++#pragma pop_macro("GetObject") ++#undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED ++#endif ++ + #endif // RAPIDJSON_DOCUMENT_H_ +diff --git a/src/common/thirdparty/rapidjson/encodedstream.h b/src/common/thirdparty/rapidjson/encodedstream.h +index 145068386..cf046b892 100644 +--- a/src/common/thirdparty/rapidjson/encodedstream.h ++++ b/src/common/thirdparty/rapidjson/encodedstream.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -200,7 +200,7 @@ private: + // 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); ++ int 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; +diff --git a/src/common/thirdparty/rapidjson/encodings.h b/src/common/thirdparty/rapidjson/encodings.h +index baa7c2b17..50ad18bdc 100644 +--- a/src/common/thirdparty/rapidjson/encodings.h ++++ b/src/common/thirdparty/rapidjson/encodings.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -17,7 +17,7 @@ + + #include "rapidjson.h" + +-#ifdef _MSC_VER ++#if defined(_MSC_VER) && !defined(__clang__) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data + RAPIDJSON_DIAG_OFF(4702) // unreachable code +@@ -144,9 +144,9 @@ struct UTF8 { + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +-#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +-#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +-#define TAIL() COPY(); TRANS(0x70) ++#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) ++#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) ++#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast(c); +@@ -157,48 +157,48 @@ struct UTF8 { + if (type >= 32) { + *codepoint = 0; + } else { +- *codepoint = (0xFF >> type) & static_cast(c); ++ *codepoint = (0xFFu >> type) & static_cast(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; ++ case 2: RAPIDJSON_TAIL(); return result; ++ case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; ++ case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; ++ case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; ++ case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; ++ case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; ++ case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +-#undef COPY +-#undef TRANS +-#undef TAIL ++#undef RAPIDJSON_COPY ++#undef RAPIDJSON_TRANS ++#undef RAPIDJSON_TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +-#define COPY() os.Put(c = is.Take()) +-#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +-#define TAIL() COPY(); TRANS(0x70) ++#define RAPIDJSON_COPY() os.Put(c = is.Take()) ++#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) ++#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + Ch c; +- COPY(); ++ RAPIDJSON_COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast(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; ++ case 2: RAPIDJSON_TAIL(); return result; ++ case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; ++ case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; ++ case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; ++ case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; ++ case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; ++ case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +-#undef COPY +-#undef TRANS +-#undef TAIL ++#undef RAPIDJSON_COPY ++#undef RAPIDJSON_TRANS ++#undef RAPIDJSON_TAIL + } + + static unsigned char GetRange(unsigned char c) { +@@ -283,7 +283,7 @@ struct UTF16 { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); +- os.Put((v & 0x3FF) | 0xDC00); ++ os.Put(static_cast((v & 0x3FF) | 0xDC00)); + } + } + +@@ -299,7 +299,7 @@ struct UTF16 { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); +- PutUnsafe(os, (v & 0x3FF) | 0xDC00); ++ PutUnsafe(os, static_cast((v & 0x3FF) | 0xDC00)); + } + } + +@@ -384,7 +384,7 @@ struct UTF16BE : UTF16 { + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 8; +- c |= static_cast(is.Take()); ++ c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + +@@ -620,28 +620,28 @@ struct AutoUTF { + #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template +- RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { ++ static RAPIDJSON_FORCEINLINE 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 +- RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { ++ static RAPIDJSON_FORCEINLINE 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 +- RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { ++ static RAPIDJSON_FORCEINLINE 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 +- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE 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); +@@ -658,7 +658,7 @@ template + struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template +- RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; +@@ -667,7 +667,7 @@ struct Transcoder { + } + + template +- RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; +@@ -677,7 +677,7 @@ struct Transcoder { + + //! Validate one Unicode codepoint from an encoded stream. + template +- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } + }; +@@ -690,26 +690,26 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + template + struct Transcoder { + template +- RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE 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 +- RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE 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 +- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { ++ static RAPIDJSON_FORCEINLINE 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) ++#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__)) + RAPIDJSON_DIAG_POP + #endif + +diff --git a/src/common/thirdparty/rapidjson/error/en.h b/src/common/thirdparty/rapidjson/error/en.h +index 2db838bff..c87b04eb1 100644 +--- a/src/common/thirdparty/rapidjson/error/en.h ++++ b/src/common/thirdparty/rapidjson/error/en.h +@@ -1,15 +1,15 @@ + // 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. ++// ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 ++// 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_ +@@ -39,13 +39,13 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro + + 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."); +@@ -65,6 +65,108 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro + } + } + ++//! Maps error code of validation into error message. ++/*! ++ \ingroup RAPIDJSON_ERRORS ++ \param validateErrorCode Error code obtained from validator. ++ \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* GetValidateError_En(ValidateErrorCode validateErrorCode) { ++ switch (validateErrorCode) { ++ case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); ++ case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error."); ++ ++ case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'."); ++ case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'."); ++ case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'."); ++ case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'."); ++ case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'."); ++ ++ case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'."); ++ case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'."); ++ case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression."); ++ ++ case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'."); ++ case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'."); ++ case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true."); ++ case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema."); ++ ++ case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'."); ++ case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'."); ++ case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'."); ++ case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema."); ++ case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema."); ++ case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors."); ++ ++ case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values."); ++ case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); ++ ++ case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); ++ case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'."); ++ case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); ++ case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); ++ case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); ++ ++ case kValidateErrorReadOnly: return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing."); ++ case kValidateErrorWriteOnly: return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading."); ++ ++ default: return RAPIDJSON_ERROR_STRING("Unknown error."); ++ } ++} ++ ++//! Maps error code of schema document compilation into error message. ++/*! ++ \ingroup RAPIDJSON_ERRORS ++ \param schemaErrorCode Error code obtained from compiling the schema document. ++ \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* GetSchemaError_En(SchemaErrorCode schemaErrorCode) { ++ switch (schemaErrorCode) { ++ case kSchemaErrorNone: return RAPIDJSON_ERROR_STRING("No error."); ++ ++ case kSchemaErrorStartUnknown: return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document."); ++ case kSchemaErrorRefPlainName: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer."); ++ case kSchemaErrorRefInvalid: return RAPIDJSON_ERROR_STRING("$ref must not be an empty string."); ++ case kSchemaErrorRefPointerInvalid: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'."); ++ case kSchemaErrorRefUnknown: return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document."); ++ case kSchemaErrorRefCyclical: return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical."); ++ case kSchemaErrorRefNoRemoteProvider: return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider."); ++ case kSchemaErrorRefNoRemoteSchema: return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema."); ++ case kSchemaErrorRegexInvalid: return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'."); ++ case kSchemaErrorSpecUnknown: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized."); ++ case kSchemaErrorSpecUnsupported: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported."); ++ case kSchemaErrorSpecIllegal: return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document."); ++ case kSchemaErrorReadOnlyAndWriteOnly: return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'."); ++ ++ default: return RAPIDJSON_ERROR_STRING("Unknown error."); ++ } ++ } ++ ++//! Maps error code of pointer parse into error message. ++/*! ++ \ingroup RAPIDJSON_ERRORS ++ \param pointerParseErrorCode Error code obtained from pointer parse. ++ \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* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) { ++ switch (pointerParseErrorCode) { ++ case kPointerParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); ++ ++ case kPointerParseErrorTokenMustBeginWithSolidus: return RAPIDJSON_ERROR_STRING("A token must begin with a '/'."); ++ case kPointerParseErrorInvalidEscape: return RAPIDJSON_ERROR_STRING("Invalid escape."); ++ case kPointerParseErrorInvalidPercentEncoding: return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment."); ++ case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment."); ++ ++ default: return RAPIDJSON_ERROR_STRING("Unknown error."); ++ } ++} ++ + RAPIDJSON_NAMESPACE_END + + #ifdef __clang__ +diff --git a/src/common/thirdparty/rapidjson/error/error.h b/src/common/thirdparty/rapidjson/error/error.h +index 95cb31a72..cae345db3 100644 +--- a/src/common/thirdparty/rapidjson/error/error.h ++++ b/src/common/thirdparty/rapidjson/error/error.h +@@ -1,15 +1,15 @@ + // 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. ++// ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 ++// 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_ +@@ -42,7 +42,7 @@ RAPIDJSON_DIAG_OFF(padded) + /////////////////////////////////////////////////////////////////////////////// + // RAPIDJSON_ERROR_STRING + +-//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. ++//! Macro for converting string literal 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 +@@ -104,6 +104,8 @@ enum ParseErrorCode { + \see GenericReader::Parse, GenericDocument::Parse + */ + struct ParseResult { ++ //!! Unspecified boolean type ++ typedef bool (ParseResult::*BooleanType)() const; + public: + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} +@@ -115,8 +117,8 @@ public: + //! 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(); } ++ //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). ++ operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + +@@ -124,6 +126,10 @@ public: + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + ++ bool operator!=(const ParseResult& that) const { return !(*this == that); } ++ bool operator!=(ParseErrorCode code) const { return !(*this == code); } ++ friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } ++ + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. +@@ -146,6 +152,130 @@ private: + */ + typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + ++/////////////////////////////////////////////////////////////////////////////// ++// ValidateErrorCode ++ ++//! Error codes when validating. ++/*! \ingroup RAPIDJSON_ERRORS ++ \see GenericSchemaValidator ++*/ ++enum ValidateErrorCode { ++ kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set. ++ kValidateErrorNone = 0, //!< No error. ++ ++ kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value. ++ kValidateErrorMaximum, //!< Number is greater than the 'maximum' value. ++ kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value. ++ kValidateErrorMinimum, //!< Number is less than the 'minimum' value. ++ kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value. ++ ++ kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value. ++ kValidateErrorMinLength, //!< String is longer than the 'maxLength' value. ++ kValidateErrorPattern, //!< String does not match the 'pattern' regular expression. ++ ++ kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value. ++ kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value. ++ kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true. ++ kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema. ++ ++ kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value. ++ kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value. ++ kValidateErrorRequired, //!< Object is missing one or more members required by the schema. ++ kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema. ++ kValidateErrorPatternProperties, //!< See other errors. ++ kValidateErrorDependencies, //!< Object has missing property or schema dependencies. ++ ++ kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values. ++ kValidateErrorType, //!< Property has a type that is not allowed by the schema. ++ ++ kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'. ++ kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'. ++ kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'. ++ kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'. ++ kValidateErrorNot, //!< Property matched the sub-schema specified by 'not'. ++ ++ kValidateErrorReadOnly, //!< Property is read-only but has been provided when validation is for writing ++ kValidateErrorWriteOnly //!< Property is write-only but has been provided when validation is for reading ++}; ++ ++//! Function pointer type of GetValidateError(). ++/*! \ingroup RAPIDJSON_ERRORS ++ ++ This is the prototype for \c GetValidateError_X(), where \c X is a locale. ++ User can dynamically change locale in runtime, e.g.: ++\code ++ GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever ++ const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode()); ++\endcode ++*/ ++typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode); ++ ++/////////////////////////////////////////////////////////////////////////////// ++// SchemaErrorCode ++ ++//! Error codes when validating. ++/*! \ingroup RAPIDJSON_ERRORS ++ \see GenericSchemaValidator ++*/ ++enum SchemaErrorCode { ++ kSchemaErrorNone = 0, //!< No error. ++ ++ kSchemaErrorStartUnknown, //!< Pointer to start of schema does not resolve to a location in the document ++ kSchemaErrorRefPlainName, //!< $ref fragment must be a JSON pointer ++ kSchemaErrorRefInvalid, //!< $ref must not be an empty string ++ kSchemaErrorRefPointerInvalid, //!< $ref fragment is not a valid JSON pointer at offset ++ kSchemaErrorRefUnknown, //!< $ref does not resolve to a location in the target document ++ kSchemaErrorRefCyclical, //!< $ref is cyclical ++ kSchemaErrorRefNoRemoteProvider, //!< $ref is remote but there is no remote provider ++ kSchemaErrorRefNoRemoteSchema, //!< $ref is remote but the remote provider did not return a schema ++ kSchemaErrorRegexInvalid, //!< Invalid regular expression in 'pattern' or 'patternProperties' ++ kSchemaErrorSpecUnknown, //!< JSON schema draft or OpenAPI version is not recognized ++ kSchemaErrorSpecUnsupported, //!< JSON schema draft or OpenAPI version is not supported ++ kSchemaErrorSpecIllegal, //!< Both JSON schema draft and OpenAPI version found in document ++ kSchemaErrorReadOnlyAndWriteOnly //!< Property must not be both 'readOnly' and 'writeOnly' ++}; ++ ++//! Function pointer type of GetSchemaError(). ++/*! \ingroup RAPIDJSON_ERRORS ++ ++ This is the prototype for \c GetSchemaError_X(), where \c X is a locale. ++ User can dynamically change locale in runtime, e.g.: ++\code ++ GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever ++ const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode()); ++\endcode ++*/ ++typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode); ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PointerParseErrorCode ++ ++//! Error code of JSON pointer 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 ++}; ++ ++//! Function pointer type of GetPointerParseError(). ++/*! \ingroup RAPIDJSON_ERRORS ++ ++ This is the prototype for \c GetPointerParseError_X(), where \c X is a locale. ++ User can dynamically change locale in runtime, e.g.: ++\code ++ GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever ++ const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode()); ++\endcode ++*/ ++typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode); ++ ++ + RAPIDJSON_NAMESPACE_END + + #ifdef __clang__ +diff --git a/src/common/thirdparty/rapidjson/filereadstream.h b/src/common/thirdparty/rapidjson/filereadstream.h +index b56ea13b3..f8bb43cb0 100644 +--- a/src/common/thirdparty/rapidjson/filereadstream.h ++++ b/src/common/thirdparty/rapidjson/filereadstream.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -59,7 +59,7 @@ public: + + // For encoding detection only. + const Ch* Peek4() const { +- return (current_ + 4 <= bufferLast_) ? current_ : 0; ++ return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + + private: +@@ -68,7 +68,7 @@ private: + ++current_; + else if (!eof_) { + count_ += readCount_; +- readCount_ = fread(buffer_, 1, bufferSize_, fp_); ++ readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + +diff --git a/src/common/thirdparty/rapidjson/filewritestream.h b/src/common/thirdparty/rapidjson/filewritestream.h +index 6378dd60e..5d89588c2 100644 +--- a/src/common/thirdparty/rapidjson/filewritestream.h ++++ b/src/common/thirdparty/rapidjson/filewritestream.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -25,7 +25,7 @@ RAPIDJSON_DIAG_OFF(unreachable-code) + + RAPIDJSON_NAMESPACE_BEGIN + +-//! Wrapper of C file stream for input using fread(). ++//! Wrapper of C file stream for output using fwrite(). + /*! + \note implements Stream concept + */ +@@ -62,7 +62,7 @@ public: + + void Flush() { + if (current_ != buffer_) { +- size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); ++ size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors +diff --git a/src/common/thirdparty/rapidjson/fwd.h b/src/common/thirdparty/rapidjson/fwd.h +index e8104e841..d62f77f0e 100644 +--- a/src/common/thirdparty/rapidjson/fwd.h ++++ b/src/common/thirdparty/rapidjson/fwd.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -102,7 +102,7 @@ class PrettyWriter; + // document.h + + template +-struct GenericMember; ++class GenericMember; + + template + class GenericMemberIterator; +diff --git a/src/common/thirdparty/rapidjson/internal/biginteger.h b/src/common/thirdparty/rapidjson/internal/biginteger.h +index 9d3e88c99..af4873803 100644 +--- a/src/common/thirdparty/rapidjson/internal/biginteger.h ++++ b/src/common/thirdparty/rapidjson/internal/biginteger.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -17,9 +17,13 @@ + + #include "../rapidjson.h" + +-#if defined(_MSC_VER) && defined(_M_AMD64) ++#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64) + #include // for _umul128 ++#if !defined(_ARM64EC_) + #pragma intrinsic(_umul128) ++#else ++#pragma comment(lib,"softintrin") ++#endif + #endif + + RAPIDJSON_NAMESPACE_BEGIN +@@ -37,7 +41,8 @@ public: + digits_[0] = u; + } + +- BigInteger(const char* decimals, size_t length) : count_(1) { ++ template ++ BigInteger(const Ch* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; +@@ -133,7 +138,7 @@ public: + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { +- std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); ++ std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); + count_ += offset; + } + else { +@@ -221,7 +226,8 @@ public: + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + + private: +- void AppendDecimal64(const char* begin, const char* end) { ++ template ++ void AppendDecimal64(const Ch* begin, const Ch* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; +@@ -236,11 +242,12 @@ private: + digits_[count_++] = digit; + } + +- static uint64_t ParseUint64(const char* begin, const char* end) { ++ template ++ static uint64_t ParseUint64(const Ch* begin, const Ch* end) { + uint64_t r = 0; +- for (const char* p = begin; p != end; ++p) { +- RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); +- r = r * 10u + static_cast(*p - '0'); ++ for (const Ch* p = begin; p != end; ++p) { ++ RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9')); ++ r = r * 10u + static_cast(*p - Ch('0')); + } + return r; + } +diff --git a/src/common/thirdparty/rapidjson/internal/clzll.h b/src/common/thirdparty/rapidjson/internal/clzll.h +new file mode 100644 +index 000000000..8fc5118aa +--- /dev/null ++++ b/src/common/thirdparty/rapidjson/internal/clzll.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. ++// ++// 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_CLZLL_H_ ++#define RAPIDJSON_CLZLL_H_ ++ ++#include "../rapidjson.h" ++ ++#if defined(_MSC_VER) && !defined(UNDER_CE) ++#include ++#if defined(_WIN64) ++#pragma intrinsic(_BitScanReverse64) ++#else ++#pragma intrinsic(_BitScanReverse) ++#endif ++#endif ++ ++RAPIDJSON_NAMESPACE_BEGIN ++namespace internal { ++ ++inline uint32_t clzll(uint64_t x) { ++ // Passing 0 to __builtin_clzll is UB in GCC and results in an ++ // infinite loop in the software implementation. ++ RAPIDJSON_ASSERT(x != 0); ++ ++#if defined(_MSC_VER) && !defined(UNDER_CE) ++ unsigned long r = 0; ++#if defined(_WIN64) ++ _BitScanReverse64(&r, x); ++#else ++ // Scan the high 32 bits. ++ if (_BitScanReverse(&r, static_cast(x >> 32))) ++ return 63 - (r + 32); ++ ++ // Scan the low 32 bits. ++ _BitScanReverse(&r, static_cast(x & 0xFFFFFFFF)); ++#endif // _WIN64 ++ ++ return 63 - r; ++#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) ++ // __builtin_clzll wrapper ++ return static_cast(__builtin_clzll(x)); ++#else ++ // naive version ++ uint32_t r = 0; ++ while (!(x & (static_cast(1) << 63))) { ++ x <<= 1; ++ ++r; ++ } ++ ++ return r; ++#endif // _MSC_VER ++} ++ ++#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll ++ ++} // namespace internal ++RAPIDJSON_NAMESPACE_END ++ ++#endif // RAPIDJSON_CLZLL_H_ +diff --git a/src/common/thirdparty/rapidjson/internal/diyfp.h b/src/common/thirdparty/rapidjson/internal/diyfp.h +index c9fefdc61..f7d46539a 100644 +--- a/src/common/thirdparty/rapidjson/internal/diyfp.h ++++ b/src/common/thirdparty/rapidjson/internal/diyfp.h +@@ -1,15 +1,15 @@ + // 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. ++// ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 ++// 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: +@@ -20,11 +20,16 @@ + #define RAPIDJSON_DIYFP_H_ + + #include "../rapidjson.h" ++#include "clzll.h" ++#include + +-#if defined(_MSC_VER) && defined(_M_AMD64) ++#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) + #include +-#pragma intrinsic(_BitScanReverse64) ++#if !defined(_ARM64EC_) + #pragma intrinsic(_umul128) ++#else ++#pragma comment(lib,"softintrin") ++#endif + #endif + + RAPIDJSON_NAMESPACE_BEGIN +@@ -56,7 +61,7 @@ struct DiyFp { + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; +- } ++ } + else { + f = significand; + e = kDpMinExponent + 1; +@@ -99,21 +104,8 @@ struct DiyFp { + } + + 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); ++ int s = static_cast(clzll(f)); + return DiyFp(f << s, e - s); +-#else +- DiyFp res = *this; +- while (!(res.f & (static_cast(1) << 63))) { +- res.f <<= 1; +- res.e--; +- } +- return res; +-#endif + } + + DiyFp NormalizeBoundary() const { +@@ -141,7 +133,16 @@ struct DiyFp { + double d; + uint64_t u64; + }u; +- const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : ++ RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask); ++ if (e < kDpDenormalExponent) { ++ // Underflow. ++ return 0.0; ++ } ++ if (e >= kDpMaxExponent) { ++ // Overflow. ++ return std::numeric_limits::infinity(); ++ } ++ const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; +@@ -220,9 +221,10 @@ inline DiyFp GetCachedPowerByIndex(size_t index) { + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; ++ RAPIDJSON_ASSERT(index < 87); + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); + } +- ++ + inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; +@@ -238,10 +240,11 @@ inline DiyFp GetCachedPower(int e, int* K) { + } + + inline DiyFp GetCachedPower10(int exp, int *outExp) { +- unsigned index = (static_cast(exp) + 348u) / 8u; +- *outExp = -348 + static_cast(index) * 8; +- return GetCachedPowerByIndex(index); +- } ++ RAPIDJSON_ASSERT(exp >= -348); ++ unsigned index = static_cast(exp + 348) / 8u; ++ *outExp = -348 + static_cast(index) * 8; ++ return GetCachedPowerByIndex(index); ++} + + #ifdef __GNUC__ + RAPIDJSON_DIAG_POP +diff --git a/src/common/thirdparty/rapidjson/internal/dtoa.h b/src/common/thirdparty/rapidjson/internal/dtoa.h +index 8d6350e62..cd456721a 100644 +--- a/src/common/thirdparty/rapidjson/internal/dtoa.h ++++ b/src/common/thirdparty/rapidjson/internal/dtoa.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin + } + } + +-inline unsigned CountDecimalDigit32(uint32_t n) { ++inline int 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; +@@ -58,12 +58,16 @@ inline unsigned CountDecimalDigit32(uint32_t n) { + } + + 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 }; ++ static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL, ++ 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL, ++ 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, ++ 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, ++ 10000000000000000000ULL }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); +- unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] ++ int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { +@@ -86,7 +90,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; +- GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); ++ GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f); + return; + } + } +@@ -102,8 +106,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff + kappa--; + if (p2 < delta) { + *K += kappa; +- int index = -static_cast(kappa); +- GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast(kappa)] : 0)); ++ int index = -kappa; ++ GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0)); + return; + } + } +diff --git a/src/common/thirdparty/rapidjson/internal/ieee754.h b/src/common/thirdparty/rapidjson/internal/ieee754.h +index 82bb0b99e..68c9e9664 100644 +--- a/src/common/thirdparty/rapidjson/internal/ieee754.h ++++ b/src/common/thirdparty/rapidjson/internal/ieee754.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -48,13 +48,13 @@ public: + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + +- static unsigned EffectiveSignificandSize(int order) { ++ static int EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else +- return static_cast(order) + 1074; ++ return order + 1074; + } + + private: +diff --git a/src/common/thirdparty/rapidjson/internal/itoa.h b/src/common/thirdparty/rapidjson/internal/itoa.h +index 01a4e7e72..9fe8c932f 100644 +--- a/src/common/thirdparty/rapidjson/internal/itoa.h ++++ b/src/common/thirdparty/rapidjson/internal/itoa.h +@@ -1,15 +1,15 @@ + // 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. ++// ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 ++// 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_ +@@ -37,12 +37,14 @@ inline const char* GetDigitsLut() { + } + + inline char* u32toa(uint32_t value, char* buffer) { ++ RAPIDJSON_ASSERT(buffer != 0); ++ + 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) +@@ -55,13 +57,13 @@ inline char* u32toa(uint32_t value, char* buffer) { + // 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) +@@ -69,7 +71,7 @@ inline char* u32toa(uint32_t value, char* buffer) { + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; +- ++ + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; +@@ -77,10 +79,10 @@ inline char* u32toa(uint32_t value, char* buffer) { + } + 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]; +@@ -91,13 +93,13 @@ inline char* u32toa(uint32_t value, char* buffer) { + + 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]; +@@ -111,6 +113,7 @@ inline char* u32toa(uint32_t value, char* buffer) { + } + + inline char* i32toa(int32_t value, char* buffer) { ++ RAPIDJSON_ASSERT(buffer != 0); + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; +@@ -121,6 +124,7 @@ inline char* i32toa(int32_t value, char* buffer) { + } + + inline char* u64toa(uint64_t value, char* buffer) { ++ RAPIDJSON_ASSERT(buffer != 0); + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; +@@ -131,13 +135,13 @@ inline char* u64toa(uint64_t value, char* buffer) { + 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(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) +@@ -150,13 +154,13 @@ inline char* u64toa(uint64_t value, char* buffer) { + // 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) +@@ -164,7 +168,7 @@ inline char* u64toa(uint64_t value, char* buffer) { + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; +- ++ + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; +@@ -174,22 +178,22 @@ inline char* u64toa(uint64_t value, char* buffer) { + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(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; + +@@ -207,9 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) { + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; +- if (value >= kTen8) +- *buffer++ = cDigitsLut[d4 + 1]; +- ++ ++ *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; +@@ -222,7 +225,7 @@ inline char* u64toa(uint64_t value, char* buffer) { + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; +- ++ + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { +@@ -232,7 +235,7 @@ inline char* u64toa(uint64_t value, char* buffer) { + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); +- ++ + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; +@@ -245,28 +248,28 @@ inline char* u64toa(uint64_t value, char* buffer) { + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } +- ++ + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(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]; +@@ -284,11 +287,12 @@ inline char* u64toa(uint64_t value, char* buffer) { + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } +- ++ + return buffer; + } + + inline char* i64toa(int64_t value, char* buffer) { ++ RAPIDJSON_ASSERT(buffer != 0); + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; +diff --git a/src/common/thirdparty/rapidjson/internal/meta.h b/src/common/thirdparty/rapidjson/internal/meta.h +index 5a9aaa428..27092dc0d 100644 +--- a/src/common/thirdparty/rapidjson/internal/meta.h ++++ b/src/common/thirdparty/rapidjson/internal/meta.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -21,7 +21,8 @@ + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(effc++) + #endif +-#if defined(_MSC_VER) ++ ++#if defined(_MSC_VER) && !defined(__clang__) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(6334) + #endif +@@ -174,7 +175,11 @@ template struct RemoveSfinaeTag { typedef T Type; + RAPIDJSON_NAMESPACE_END + //@endcond + +-#if defined(__GNUC__) || defined(_MSC_VER) ++#if defined(_MSC_VER) && !defined(__clang__) ++RAPIDJSON_DIAG_POP ++#endif ++ ++#ifdef __GNUC__ + RAPIDJSON_DIAG_POP + #endif + +diff --git a/src/common/thirdparty/rapidjson/internal/pow10.h b/src/common/thirdparty/rapidjson/internal/pow10.h +index 02f475d70..eae1a43ed 100644 +--- a/src/common/thirdparty/rapidjson/internal/pow10.h ++++ b/src/common/thirdparty/rapidjson/internal/pow10.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +diff --git a/src/common/thirdparty/rapidjson/internal/regex.h b/src/common/thirdparty/rapidjson/internal/regex.h +index 422a5240b..6446c403a 100644 +--- a/src/common/thirdparty/rapidjson/internal/regex.h ++++ b/src/common/thirdparty/rapidjson/internal/regex.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -23,7 +23,9 @@ + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(padded) + RAPIDJSON_DIAG_OFF(switch-enum) +-RAPIDJSON_DIAG_OFF(implicit-fallthrough) ++#elif defined(_MSC_VER) ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated + #endif + + #ifdef __GNUC__ +@@ -31,11 +33,6 @@ 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 +@@ -43,12 +40,40 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated + RAPIDJSON_NAMESPACE_BEGIN + namespace internal { + ++/////////////////////////////////////////////////////////////////////////////// ++// DecodedStream ++ ++template ++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_; ++}; ++ + /////////////////////////////////////////////////////////////////////////////// + // GenericRegex + + static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 + static const SizeType kRegexInvalidRange = ~SizeType(0); + ++template ++class GenericRegexSearch; ++ + //! Regular expression engine with subset of ECMAscript grammar. + /*! + Supported regular expression syntax: +@@ -84,45 +109,29 @@ static const SizeType kRegexInvalidRange = ~SizeType(0); + template + class GenericRegex { + public: ++ typedef Encoding EncodingType; + typedef typename Encoding::Ch Ch; ++ template friend class GenericRegexSearch; + + 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_() ++ ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), ++ states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), ++ anchorBegin_(), anchorEnd_() + { + GenericStringStream ss(source); +- DecodedStream > ds(ss); ++ DecodedStream, Encoding> ds(ss); + Parse(ds); + } + +- ~GenericRegex() { +- Allocator::Free(stateSet_); ++ ~GenericRegex() ++ { ++ RAPIDJSON_DELETE(ownAllocator_); + } + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + +- template +- bool Match(InputStream& is) const { +- return SearchWithAnchoring(is, true, true); +- } +- +- bool Match(const Ch* s) const { +- GenericStringStream is(s); +- return Match(is); +- } +- +- template +- bool Search(InputStream& is) const { +- return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); +- } +- +- bool Search(const Ch* s) const { +- GenericStringStream is(s); +- return Search(is); +- } +- + private: + enum Operator { + kZeroOrOne, +@@ -157,28 +166,6 @@ private: + SizeType minIndex; + }; + +- template +- 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()[index]; +@@ -200,11 +187,10 @@ private: + } + + template +- void Parse(DecodedStream& ds) { +- Allocator allocator; +- Stack operandStack(&allocator, 256); // Frag +- Stack operatorStack(&allocator, 256); // Operator +- Stack atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) ++ void Parse(DecodedStream& ds) { ++ Stack operandStack(allocator_, 256); // Frag ++ Stack operatorStack(allocator_, 256); // Operator ++ Stack atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push() = 0; + +@@ -301,6 +287,7 @@ private: + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default ++ RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: // Pattern character + PushOperand(operandStack, codepoint); +@@ -327,14 +314,6 @@ private: + printf("\n"); + #endif + } +- +- // Preallocate buffer for SearchWithAnchoring() +- RAPIDJSON_ASSERT(stateSet_ == 0); +- if (stateCount_ > 0) { +- stateSet_ = static_cast(states_.GetAllocator().Malloc(GetStateSetSize())); +- state0_.template Reserve(stateCount_); +- state1_.template Reserve(stateCount_); +- } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { +@@ -413,8 +392,7 @@ private: + } + return false; + +- default: +- RAPIDJSON_ASSERT(op == kOneOrMore); ++ case kOneOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); +@@ -423,6 +401,10 @@ private: + return true; + } + return false; ++ ++ default: ++ // syntax error (e.g. unclosed kLeftParenthesis) ++ return false; + } + } + +@@ -483,7 +465,7 @@ private: + } + + template +- bool ParseUnsigned(DecodedStream& ds, unsigned* u) { ++ bool ParseUnsigned(DecodedStream& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; +@@ -497,7 +479,7 @@ private: + } + + template +- bool ParseRange(DecodedStream& ds, SizeType* range) { ++ bool ParseRange(DecodedStream& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; +@@ -535,6 +517,7 @@ private: + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default ++ RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: + switch (step) { +@@ -544,6 +527,7 @@ private: + break; + } + // fall through to step 0 for other characters ++ RAPIDJSON_DELIBERATE_FALLTHROUGH; + + case 0: + { +@@ -575,7 +559,7 @@ private: + } + + template +- bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { ++ bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': +@@ -603,34 +587,95 @@ private: + } + } + ++ Allocator* ownAllocator_; ++ Allocator* allocator_; ++ Stack states_; ++ Stack ranges_; ++ SizeType root_; ++ SizeType stateCount_; ++ SizeType rangeCount_; ++ ++ static const unsigned kInfinityQuantifier = ~0u; ++ ++ // For SearchWithAnchoring() ++ bool anchorBegin_; ++ bool anchorEnd_; ++}; ++ ++template ++class GenericRegexSearch { ++public: ++ typedef typename RegexType::EncodingType Encoding; ++ typedef typename Encoding::Ch Ch; ++ ++ GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : ++ regex_(regex), allocator_(allocator), ownAllocator_(0), ++ state0_(allocator, 0), state1_(allocator, 0), stateSet_() ++ { ++ RAPIDJSON_ASSERT(regex_.IsValid()); ++ if (!allocator_) ++ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ++ stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); ++ state0_.template Reserve(regex_.stateCount_); ++ state1_.template Reserve(regex_.stateCount_); ++ } ++ ++ ~GenericRegexSearch() { ++ Allocator::Free(stateSet_); ++ RAPIDJSON_DELETE(ownAllocator_); ++ } ++ + template +- bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { +- RAPIDJSON_ASSERT(IsValid()); +- DecodedStream ds(is); ++ bool Match(InputStream& is) { ++ return SearchWithAnchoring(is, true, true); ++ } ++ ++ bool Match(const Ch* s) { ++ GenericStringStream is(s); ++ return Match(is); ++ } ++ ++ template ++ bool Search(InputStream& is) { ++ return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); ++ } ++ ++ bool Search(const Ch* s) { ++ GenericStringStream is(s); ++ return Search(is); ++ } ++ ++private: ++ typedef typename RegexType::State State; ++ typedef typename RegexType::Range Range; ++ ++ template ++ bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { ++ DecodedStream ds(is); + + state0_.Clear(); + Stack *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + +- bool matched = AddState(*current, root_); ++ bool matched = AddState(*current, regex_.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(); s != current->template End(); ++s) { +- const State& sr = GetState(*s); ++ const State& sr = regex_.GetState(*s); + if (sr.codepoint == codepoint || +- sr.codepoint == kAnyCharacterClass || +- (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) ++ sr.codepoint == RegexType::kAnyCharacterClass || ++ (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) +- AddState(*next, root_); ++ AddState(*next, regex_.root_); + } + internal::Swap(current, next); + } +@@ -639,62 +684,55 @@ private: + } + + size_t GetStateSetSize() const { +- return (stateCount_ + 31) / 32 * 4; ++ return (regex_.stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state +- bool AddState(Stack& l, SizeType index) const { ++ bool AddState(Stack& l, SizeType index) { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + +- const State& s = GetState(index); ++ const State& s = regex_.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)); ++ else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) { ++ stateSet_[index >> 5] |= (1u << (index & 31)); + *l.template PushUnsafe() = 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; ++ bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { +- const Range& r = GetRange(rangeIndex); +- if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end) ++ const Range& r = regex_.GetRange(rangeIndex); ++ if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + +- Stack states_; +- Stack ranges_; +- SizeType root_; +- SizeType stateCount_; +- SizeType rangeCount_; +- +- static const unsigned kInfinityQuantifier = ~0u; +- +- // For SearchWithAnchoring() +- uint32_t* stateSet_; // allocated by states_.GetAllocator() +- mutable Stack state0_; +- mutable Stack state1_; +- bool anchorBegin_; +- bool anchorEnd_; ++ const RegexType& regex_; ++ Allocator* allocator_; ++ Allocator* ownAllocator_; ++ Stack state0_; ++ Stack state1_; ++ uint32_t* stateSet_; + }; + + typedef GenericRegex > Regex; ++typedef GenericRegexSearch RegexSearch; + + } // namespace internal + RAPIDJSON_NAMESPACE_END + +-#ifdef __clang__ ++#ifdef __GNUC__ + RAPIDJSON_DIAG_POP + #endif + +-#ifdef _MSC_VER ++#if defined(__clang__) || defined(_MSC_VER) + RAPIDJSON_DIAG_POP + #endif + +diff --git a/src/common/thirdparty/rapidjson/internal/stack.h b/src/common/thirdparty/rapidjson/internal/stack.h +index 022c9aab4..73abd706e 100644 +--- a/src/common/thirdparty/rapidjson/internal/stack.h ++++ b/src/common/thirdparty/rapidjson/internal/stack.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -17,6 +17,7 @@ + + #include "../allocators.h" + #include "swap.h" ++#include + + #if defined(__clang__) + RAPIDJSON_DIAG_PUSH +@@ -100,7 +101,7 @@ public: + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. +- Allocator::Free(stack_); ++ Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; +@@ -114,7 +115,7 @@ public: + template + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed +- if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) ++ if (RAPIDJSON_UNLIKELY(static_cast(sizeof(T) * count) > (stackEnd_ - stackTop_))) + Expand(count); + } + +@@ -126,7 +127,8 @@ public: + + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { +- RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); ++ RAPIDJSON_ASSERT(stackTop_); ++ RAPIDJSON_ASSERT(static_cast(sizeof(T) * count) <= (stackEnd_ - stackTop_)); + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; +@@ -183,7 +185,7 @@ private: + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) +- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ++ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); +diff --git a/src/common/thirdparty/rapidjson/internal/strfunc.h b/src/common/thirdparty/rapidjson/internal/strfunc.h +index de41d8f9c..b698a8f43 100644 +--- a/src/common/thirdparty/rapidjson/internal/strfunc.h ++++ b/src/common/thirdparty/rapidjson/internal/strfunc.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -16,6 +16,7 @@ + #define RAPIDJSON_INTERNAL_STRFUNC_H_ + + #include "../stream.h" ++#include + + RAPIDJSON_NAMESPACE_BEGIN + namespace internal { +@@ -34,6 +35,30 @@ inline SizeType StrLen(const Ch* s) { + return SizeType(p - s); + } + ++template <> ++inline SizeType StrLen(const char* s) { ++ return SizeType(std::strlen(s)); ++} ++ ++template <> ++inline SizeType StrLen(const wchar_t* s) { ++ return SizeType(std::wcslen(s)); ++} ++ ++//! Custom strcmpn() which works on different character types. ++/*! \tparam Ch Character type (e.g. char, wchar_t, short) ++ \param s1 Null-terminated input string. ++ \param s2 Null-terminated input string. ++ \return 0 if equal ++*/ ++template ++inline int StrCmp(const Ch* s1, const Ch* s2) { ++ RAPIDJSON_ASSERT(s1 != 0); ++ RAPIDJSON_ASSERT(s2 != 0); ++ while(*s1 && (*s1 == *s2)) { s1++; s2++; } ++ return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2); ++} ++ + //! Returns number of code points in a encoded string. + template + bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { +diff --git a/src/common/thirdparty/rapidjson/internal/strtod.h b/src/common/thirdparty/rapidjson/internal/strtod.h +index 289c413b0..55f0e380b 100644 +--- a/src/common/thirdparty/rapidjson/internal/strtod.h ++++ b/src/common/thirdparty/rapidjson/internal/strtod.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -19,6 +19,8 @@ + #include "biginteger.h" + #include "diyfp.h" + #include "pow10.h" ++#include ++#include + + RAPIDJSON_NAMESPACE_BEGIN + namespace internal { +@@ -126,46 +128,47 @@ inline bool StrtodFast(double d, int p, double* result) { + } + + // 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) { ++template ++inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) { + uint64_t significand = 0; +- size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 +- for (; i < length; i++) { ++ int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 ++ for (; i < dLen; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || +- (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) ++ (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5'))) + break; +- significand = significand * 10u + static_cast(decimals[i] - '0'); ++ significand = significand * 10u + static_cast(decimals[i] - Ch('0')); + } + +- if (i < length && decimals[i] >= '5') // Rounding ++ if (i < dLen && decimals[i] >= Ch('5')) // Rounding + significand++; + +- size_t remaining = length - i; +- const unsigned kUlpShift = 3; +- const unsigned kUlp = 1 << kUlpShift; ++ int remaining = dLen - i; ++ const int kUlpShift = 3; ++ const int 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(decimalPosition) - static_cast(i) + exp; ++ dExp += remaining; + + 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 ++ DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1 ++ DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2 ++ DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3 ++ DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4 ++ DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5 ++ DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6 ++ DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7 + }; +- int adjustment = dExp - actualExp - 1; +- RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); +- v = v * kPow10[adjustment]; +- if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit ++ int adjustment = dExp - actualExp; ++ RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8); ++ v = v * kPow10[adjustment - 1]; ++ if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + +@@ -177,17 +180,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit + v = v.Normalize(); + error <<= oldExp - v.e; + +- const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); +- unsigned precisionSize = 64 - effectiveSignificandSize; ++ const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); ++ int precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { +- unsigned scaleExp = (precisionSize + kUlpShift) - 63; ++ int scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; +- error = (error >> scaleExp) + 1 + static_cast(kUlp); ++ error = (error >> scaleExp) + 1 + kUlp; + precisionSize -= scaleExp; + } + +- DiyFp rounded(v.f >> precisionSize, v.e + static_cast(precisionSize)); ++ DiyFp rounded(v.f >> precisionSize, v.e + 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(error)) { +@@ -203,9 +206,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(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(decimalPosition) - static_cast(length) + exp; ++template ++inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) { ++ RAPIDJSON_ASSERT(dLen >= 0); ++ const BigInteger dInt(decimals, static_cast(dLen)); + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) +@@ -221,46 +225,66 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt + return a.NextPositiveDouble(); + } + +-inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { ++template ++inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + +- double result; ++ double result = 0.0; + if (StrtodFast(d, p, &result)) + return result; + ++ RAPIDJSON_ASSERT(length <= INT_MAX); ++ int dLen = static_cast(length); ++ ++ RAPIDJSON_ASSERT(length >= decimalPosition); ++ RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX); ++ int dExpAdjust = static_cast(length - decimalPosition); ++ ++ RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust); ++ int dExp = exp - dExpAdjust; ++ ++ // Make sure length+dExp does not overflow ++ RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen); ++ + // Trim leading zeros +- while (*decimals == '0' && length > 1) { +- length--; ++ while (dLen > 0 && *decimals == '0') { ++ dLen--; + decimals++; +- decimalPosition--; + } + + // Trim trailing zeros +- while (decimals[length - 1] == '0' && length > 1) { +- length--; +- decimalPosition--; +- exp++; ++ while (dLen > 0 && decimals[dLen - 1] == '0') { ++ dLen--; ++ dExp++; ++ } ++ ++ if (dLen == 0) { // Buffer only contains zeros. ++ return 0.0; + } + + // Trim right-most digits +- const int kMaxDecimalDigit = 780; +- if (static_cast(length) > kMaxDecimalDigit) { +- int delta = (static_cast(length) - kMaxDecimalDigit); +- exp += delta; +- decimalPosition -= static_cast(delta); +- length = kMaxDecimalDigit; ++ const int kMaxDecimalDigit = 767 + 1; ++ if (dLen > kMaxDecimalDigit) { ++ dExp += dLen - kMaxDecimalDigit; ++ dLen = kMaxDecimalDigit; + } + +- // If too small, underflow to zero +- if (int(length) + exp < -324) ++ // If too small, underflow to zero. ++ // Any x <= 10^-324 is interpreted as zero. ++ if (dLen + dExp <= -324) + return 0.0; + +- if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) ++ // If too large, overflow to infinity. ++ // Any x >= 10^309 is interpreted as +infinity. ++ if (dLen + dExp > 309) ++ return std::numeric_limits::infinity(); ++ ++ if (StrtodDiyFp(decimals, dLen, dExp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison +- return StrtodBigInteger(result, decimals, length, decimalPosition, exp); ++ return StrtodBigInteger(result, decimals, dLen, dExp); + } + + } // namespace internal +diff --git a/src/common/thirdparty/rapidjson/internal/swap.h b/src/common/thirdparty/rapidjson/internal/swap.h +index 666e49f97..2cf92f93a 100644 +--- a/src/common/thirdparty/rapidjson/internal/swap.h ++++ b/src/common/thirdparty/rapidjson/internal/swap.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +diff --git a/src/common/thirdparty/rapidjson/istreamwrapper.h b/src/common/thirdparty/rapidjson/istreamwrapper.h +index f5fe28977..01437ec01 100644 +--- a/src/common/thirdparty/rapidjson/istreamwrapper.h ++++ b/src/common/thirdparty/rapidjson/istreamwrapper.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -17,13 +17,12 @@ + + #include "stream.h" + #include ++#include + + #ifdef __clang__ + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(padded) +-#endif +- +-#ifdef _MSC_VER ++#elif defined(_MSC_VER) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized + #endif +@@ -50,57 +49,71 @@ template + 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(c) : '\0'; ++ //! Constructor. ++ /*! ++ \param stream stream opened for read. ++ */ ++ BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { ++ Read(); + } + +- Ch Take() { +- typename StreamType::int_type c = stream_.get(); +- if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { +- count_++; +- return static_cast(c); +- } +- else +- return '\0'; ++ //! Constructor. ++ /*! ++ \param stream stream opened for read. ++ \param buffer user-supplied buffer. ++ \param bufferSize size of buffer in bytes. Must >=4 bytes. ++ */ ++ BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { ++ RAPIDJSON_ASSERT(bufferSize >= 4); ++ Read(); + } + +- // tellg() may return -1 when failed. So we count by ourself. +- size_t Tell() const { return count_; } ++ Ch Peek() const { return *current_; } ++ Ch Take() { Ch c = *current_; Read(); return c; } ++ size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + +- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } ++ // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } +- void Flush() { 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 { +- 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(c); +- } +- for (--i; i >= 0; --i) +- stream_.putback(peekBuffer_[i]); +- return !hasError ? peekBuffer_ : 0; ++ return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + + private: ++ BasicIStreamWrapper(); + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + +- StreamType& stream_; +- size_t count_; //!< Number of characters read. Note: +- mutable Ch peekBuffer_[4]; ++ void Read() { ++ if (current_ < bufferLast_) ++ ++current_; ++ else if (!eof_) { ++ count_ += readCount_; ++ readCount_ = bufferSize_; ++ bufferLast_ = buffer_ + readCount_ - 1; ++ current_ = buffer_; ++ ++ if (!stream_.read(buffer_, static_cast(bufferSize_))) { ++ readCount_ = static_cast(stream_.gcount()); ++ *(bufferLast_ = buffer_ + readCount_) = '\0'; ++ eof_ = true; ++ } ++ } ++ } ++ ++ StreamType &stream_; ++ Ch peekBuffer_[4], *buffer_; ++ size_t bufferSize_; ++ Ch *bufferLast_; ++ Ch *current_; ++ size_t readCount_; ++ size_t count_; //!< Number of characters read ++ bool eof_; + }; + + typedef BasicIStreamWrapper IStreamWrapper; +diff --git a/src/common/thirdparty/rapidjson/memorybuffer.h b/src/common/thirdparty/rapidjson/memorybuffer.h +index 39bee1dec..ffbc41ed1 100644 +--- a/src/common/thirdparty/rapidjson/memorybuffer.h ++++ b/src/common/thirdparty/rapidjson/memorybuffer.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +diff --git a/src/common/thirdparty/rapidjson/memorystream.h b/src/common/thirdparty/rapidjson/memorystream.h +index 1d71d8a4f..77af6c999 100644 +--- a/src/common/thirdparty/rapidjson/memorystream.h ++++ b/src/common/thirdparty/rapidjson/memorystream.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +diff --git a/src/common/thirdparty/rapidjson/ostreamwrapper.h b/src/common/thirdparty/rapidjson/ostreamwrapper.h +index 6f4667c08..11ed4d33f 100644 +--- a/src/common/thirdparty/rapidjson/ostreamwrapper.h ++++ b/src/common/thirdparty/rapidjson/ostreamwrapper.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +diff --git a/src/common/thirdparty/rapidjson/pointer.h b/src/common/thirdparty/rapidjson/pointer.h +index 0206ac1c8..05b1704dd 100644 +--- a/src/common/thirdparty/rapidjson/pointer.h ++++ b/src/common/thirdparty/rapidjson/pointer.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -16,14 +16,14 @@ + #define RAPIDJSON_POINTER_H_ + + #include "document.h" ++#include "uri.h" + #include "internal/itoa.h" ++#include "error/error.h" // PointerParseErrorCode + + #ifdef __clang__ + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(switch-enum) +-#endif +- +-#ifdef _MSC_VER ++#elif defined(_MSC_VER) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated + #endif +@@ -32,19 +32,6 @@ 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 + +@@ -70,10 +57,10 @@ enum PointerParseErrorCode { + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. +- ++ + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > + \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. + */ +@@ -82,8 +69,10 @@ class GenericPointer { + public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value ++ typedef GenericUri UriType; + +- //! A token is the basic units of internal representation. ++ ++ //! 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. +@@ -165,7 +154,12 @@ public: + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Copy constructor. +- GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { ++ GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { ++ *this = rhs; ++ } ++ ++ //! Copy constructor. ++ GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + +@@ -197,6 +191,36 @@ public: + return *this; + } + ++ //! Swap the content of this pointer with an other. ++ /*! ++ \param other The pointer to swap with. ++ \note Constant complexity. ++ */ ++ GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT { ++ internal::Swap(allocator_, other.allocator_); ++ internal::Swap(ownAllocator_, other.ownAllocator_); ++ internal::Swap(nameBuffer_, other.nameBuffer_); ++ internal::Swap(tokens_, other.tokens_); ++ internal::Swap(tokenCount_, other.tokenCount_); ++ internal::Swap(parseErrorOffset_, other.parseErrorOffset_); ++ internal::Swap(parseErrorCode_, other.parseErrorCode_); ++ 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.pointer, b.pointer); ++ // ... ++ } ++ \endcode ++ \see Swap() ++ */ ++ friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } ++ + //@} + + //!@name Append token +@@ -240,7 +264,7 @@ public: + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { +- return Append(name, StrLen(name), allocator); ++ return Append(name, internal::StrLen(name), allocator); + } + + #if RAPIDJSON_HAS_STDSTRING +@@ -274,7 +298,7 @@ public: + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) +- name[i] = buffer[i]; ++ name[i] = static_cast(buffer[i]); + Token token = { name, length, index }; + return Append(token, allocator); + } +@@ -353,6 +377,33 @@ public: + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + ++ //! Less than operator. ++ /*! ++ \note Invalid pointers are always greater than valid ones. ++ */ ++ bool operator<(const GenericPointer& rhs) const { ++ if (!IsValid()) ++ return false; ++ if (!rhs.IsValid()) ++ return true; ++ ++ if (tokenCount_ != rhs.tokenCount_) ++ return tokenCount_ < rhs.tokenCount_; ++ ++ for (size_t i = 0; i < tokenCount_; i++) { ++ if (tokens_[i].index != rhs.tokens_[i].index) ++ return tokens_[i].index < rhs.tokens_[i].index; ++ ++ if (tokens_[i].length != rhs.tokens_[i].length) ++ return tokens_[i].length < rhs.tokens_[i].length; ++ ++ if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length)) ++ return cmp < 0; ++ } ++ ++ return false; ++ } ++ + //@} + + //!@name Stringify +@@ -428,10 +479,11 @@ public: + v = &((*v)[t->index]); + } + else { +- typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); ++ typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(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 ++ m = v->MemberEnd(); ++ v = &(--m)->value; // Assumes AddMember() appends at the end + exist = false; + } + else +@@ -459,6 +511,70 @@ public: + + //@} + ++ //!@name Compute URI ++ //@{ ++ ++ //! Compute the in-scope URI for a subtree. ++ // For use with JSON pointers into JSON schema documents. ++ /*! ++ \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. ++ \param rootUri Root URI ++ \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. ++ \param allocator Allocator for Uris ++ \return Uri if it can be resolved. Otherwise null. ++ ++ \note ++ There are only 3 situations when a URI 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. ++ */ ++ UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { ++ static const Ch kIdString[] = { 'i', 'd', '\0' }; ++ static const ValueType kIdValue(kIdString, 2); ++ UriType base = UriType(rootUri, allocator); ++ RAPIDJSON_ASSERT(IsValid()); ++ ValueType* v = &root; ++ for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { ++ switch (v->GetType()) { ++ case kObjectType: ++ { ++ // See if we have an id, and if so resolve with the current base ++ typename ValueType::MemberIterator m = v->FindMember(kIdValue); ++ if (m != v->MemberEnd() && (m->value).IsString()) { ++ UriType here = UriType(m->value, allocator).Resolve(base, allocator); ++ base = here; ++ } ++ m = v->FindMember(GenericValue(GenericStringRef(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(t - tokens_); ++ return UriType(allocator); ++ } ++ return base; ++ } ++ ++ UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { ++ return GetUri(const_cast(root), rootUri, unresolvedTokenIndex, allocator); ++ } ++ ++ + //!@name Query value + //@{ + +@@ -483,7 +599,7 @@ public: + switch (v->GetType()) { + case kObjectType: + { +- typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); ++ typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; +@@ -532,14 +648,14 @@ public: + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; +- Value& v = Create(root, allocator, &alreadyExist); ++ ValueType& 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); ++ ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +@@ -547,7 +663,7 @@ public: + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; +- Value& v = Create(root, allocator, &alreadyExist); ++ ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + #endif +@@ -573,7 +689,7 @@ public: + ValueType& GetWithDefault(GenericDocument& 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 +@@ -719,7 +835,7 @@ public: + switch (v->GetType()) { + case kObjectType: + { +- typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); ++ typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + return false; + v = &m->value; +@@ -758,7 +874,7 @@ private: + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. +- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ++ 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) +@@ -806,7 +922,7 @@ private: + + // Create own allocator if user did not supply. + if (!allocator_) +- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ++ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Count number of '/' as tokenCount + tokenCount_ = 0; +@@ -867,7 +983,7 @@ private: + } + + i++; +- ++ + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { +@@ -1029,8 +1145,8 @@ private: + unsigned char u = static_cast(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]); ++ os_.Put(static_cast(hexDigits[u >> 4])); ++ os_.Put(static_cast(hexDigits[u & 15])); + } + private: + OutputStream& os_; +@@ -1347,11 +1463,7 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + + RAPIDJSON_NAMESPACE_END + +-#ifdef __clang__ +-RAPIDJSON_DIAG_POP +-#endif +- +-#ifdef _MSC_VER ++#if defined(__clang__) || defined(_MSC_VER) + RAPIDJSON_DIAG_POP + #endif + +diff --git a/src/common/thirdparty/rapidjson/prettywriter.h b/src/common/thirdparty/rapidjson/prettywriter.h +index c6f0216e9..fe45df1d1 100644 +--- a/src/common/thirdparty/rapidjson/prettywriter.h ++++ b/src/common/thirdparty/rapidjson/prettywriter.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -22,6 +22,11 @@ RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(effc++) + #endif + ++#if defined(__clang__) ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(c++98-compat) ++#endif ++ + RAPIDJSON_NAMESPACE_BEGIN + + //! Combination of PrettyWriter format flags. +@@ -34,7 +39,7 @@ enum PrettyFormatOptions { + + //! Writer with indentation and spacing. + /*! +- \tparam OutputStream Type of ouptut os. ++ \tparam OutputStream Type of output os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +@@ -42,7 +47,7 @@ enum PrettyFormatOptions { + template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> + class PrettyWriter : public Writer { + public: +- typedef Writer Base; ++ typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor +@@ -55,7 +60,12 @@ public: + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : +- Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} ++ Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} ++ ++#if RAPIDJSON_HAS_CXX11_RVALUE_REFS ++ PrettyWriter(PrettyWriter&& rhs) : ++ Base(std::forward(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} ++#endif + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). +@@ -82,26 +92,26 @@ public: + */ + //@{ + +- 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 Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } ++ bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } ++ bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } ++ bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); } ++ bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); } ++ bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } ++ bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kNumberType); +- return Base::WriteString(str, length); ++ return Base::EndValue(Base::WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kStringType); +- return Base::WriteString(str, length); ++ return Base::EndValue(Base::WriteString(str, length)); + } + + #if RAPIDJSON_HAS_STDSTRING +@@ -126,19 +136,21 @@ public: + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; +- RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); +- RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); ++ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object ++ RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); // currently inside an Array, not Object ++ RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value ++ + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } +- bool ret = Base::WriteEndObject(); ++ bool ret = Base::EndValue(Base::WriteEndObject()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text +- Base::os_->Flush(); ++ Base::Flush(); + return true; + } + +@@ -158,11 +170,11 @@ public: + Base::os_->Put('\n'); + WriteIndent(); + } +- bool ret = Base::WriteEndArray(); ++ bool ret = Base::EndValue(Base::WriteEndArray()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text +- Base::os_->Flush(); ++ Base::Flush(); + return true; + } + +@@ -189,7 +201,7 @@ public: + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + PrettyPrefix(type); +- return Base::WriteRawValue(json, length); ++ return Base::EndValue(Base::WriteRawValue(json, length)); + } + + protected: +@@ -239,7 +251,7 @@ protected: + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; +- PutN(*Base::os_, static_cast(indentChar_), count); ++ PutN(*Base::os_, static_cast(indentChar_), count); + } + + Ch indentChar_; +@@ -254,6 +266,10 @@ private: + + RAPIDJSON_NAMESPACE_END + ++#if defined(__clang__) ++RAPIDJSON_DIAG_POP ++#endif ++ + #ifdef __GNUC__ + RAPIDJSON_DIAG_POP + #endif +diff --git a/src/common/thirdparty/rapidjson/rapidjson.h b/src/common/thirdparty/rapidjson/rapidjson.h +index d5b7630b5..5ea694795 100644 +--- a/src/common/thirdparty/rapidjson/rapidjson.h ++++ b/src/common/thirdparty/rapidjson/rapidjson.h +@@ -1,15 +1,15 @@ + // 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. ++// ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 ++// 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_ +@@ -17,7 +17,7 @@ + + /*!\file rapidjson.h + \brief common definitions and configuration +- ++ + \see RAPIDJSON_CONFIG + */ + +@@ -26,7 +26,7 @@ + + 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 ++ features can be configured in terms of overridden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. +@@ -49,6 +49,11 @@ + // token stringification + #define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) + #define RAPIDJSON_DO_STRINGIFY(x) #x ++ ++// token concatenation ++#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 + //!@endcond + + /*! \def RAPIDJSON_MAJOR_VERSION +@@ -119,6 +124,19 @@ + #define RAPIDJSON_NAMESPACE_END } + #endif + ++/////////////////////////////////////////////////////////////////////////////// ++// __cplusplus macro ++ ++//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN ++ ++#if defined(_MSC_VER) ++#define RAPIDJSON_CPLUSPLUS _MSVC_LANG ++#else ++#define RAPIDJSON_CPLUSPLUS __cplusplus ++#endif ++ ++//!@endcond ++ + /////////////////////////////////////////////////////////////////////////////// + // RAPIDJSON_HAS_STDSTRING + +@@ -144,6 +162,24 @@ + #include + #endif // RAPIDJSON_HAS_STDSTRING + ++/////////////////////////////////////////////////////////////////////////////// ++// RAPIDJSON_USE_MEMBERSMAP ++ ++/*! \def RAPIDJSON_USE_MEMBERSMAP ++ \ingroup RAPIDJSON_CONFIG ++ \brief Enable RapidJSON support for object members handling in a \c std::multimap ++ ++ By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object ++ members are stored in a \c std::multimap for faster lookup and deletion times, a ++ trade off with a slightly slower insertion time and a small object allocat(or)ed ++ memory overhead. ++ ++ \hideinitializer ++*/ ++#ifndef RAPIDJSON_USE_MEMBERSMAP ++#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default ++#endif ++ + /////////////////////////////////////////////////////////////////////////////// + // RAPIDJSON_NO_INT64DEFINE + +@@ -159,7 +195,7 @@ + */ + #ifndef RAPIDJSON_NO_INT64DEFINE + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +-#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 ++#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 + #include "msinttypes/stdint.h" + #include "msinttypes/inttypes.h" + #else +@@ -214,7 +250,7 @@ + # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN + # else +-# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. ++# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. + # endif // __BYTE_ORDER__ + // Detect with GLIBC's endian.h + # elif defined(__GLIBC__) +@@ -224,7 +260,7 @@ + # elif (__BYTE_ORDER == __BIG_ENDIAN) + # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN + # else +-# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. ++# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. + # endif // __GLIBC__ + // Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro + # elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +@@ -236,14 +272,12 @@ + # 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(_MSC_VER) && defined(_M_ARM64) ++# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) + # 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. ++# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. + # endif + #endif // RAPIDJSON_ENDIAN + +@@ -266,16 +300,11 @@ + /*! \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. ++ Some machines require strict data alignment. The default is 8 bytes. + User can customize by defining the RAPIDJSON_ALIGN function macro. + */ + #ifndef RAPIDJSON_ALIGN +-#if RAPIDJSON_64BIT == 1 +-#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) +-#else +-#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) +-#endif ++#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) + #endif + + /////////////////////////////////////////////////////////////////////////////// +@@ -322,17 +351,17 @@ + #endif + + /////////////////////////////////////////////////////////////////////////////// +-// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD ++// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD + + /*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG +- \brief Enable SSE2/SSE4.2 optimization. ++ \brief Enable SSE2/SSE4.2/Neon optimization. + + RapidJSON supports optimized implementations for some parsing operations +- based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible +- processors. ++ based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel ++ or ARM compatible processors. + +- To enable these optimizations, two different symbols can be defined; ++ To enable these optimizations, three different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 +@@ -341,13 +370,17 @@ + #define RAPIDJSON_SSE42 + \endcode + +- \c RAPIDJSON_SSE42 takes precedence, if both are defined. ++ // Enable ARM Neon optimization. ++ #define RAPIDJSON_NEON ++ \endcode ++ ++ \c RAPIDJSON_SSE42 takes precedence over SSE2, 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) ++ || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) + #define RAPIDJSON_SIMD + #endif + +@@ -407,7 +440,15 @@ RAPIDJSON_NAMESPACE_END + /////////////////////////////////////////////////////////////////////////////// + // RAPIDJSON_STATIC_ASSERT + +-// Adopt from boost ++// Prefer C++11 static_assert, if available ++#ifndef RAPIDJSON_STATIC_ASSERT ++#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) ++#define RAPIDJSON_STATIC_ASSERT(x) \ ++ static_assert(x, RAPIDJSON_STRINGIFY(x)) ++#endif // C++11 ++#endif // RAPIDJSON_STATIC_ASSERT ++ ++// Adopt C++03 implementation from boost + #ifndef RAPIDJSON_STATIC_ASSERT + #ifndef __clang__ + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +@@ -415,14 +456,10 @@ RAPIDJSON_NAMESPACE_END + RAPIDJSON_NAMESPACE_BEGIN + template struct STATIC_ASSERTION_FAILURE; + template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +-template struct StaticAssertTest {}; ++template 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__) ++#if defined(__GNUC__) || defined(__clang__) + #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) + #else + #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +@@ -440,7 +477,7 @@ RAPIDJSON_NAMESPACE_END + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +-#endif ++#endif // RAPIDJSON_STATIC_ASSERT + + /////////////////////////////////////////////////////////////////////////////// + // RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY +@@ -476,7 +513,7 @@ RAPIDJSON_NAMESPACE_END + + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +-#define RAPIDJSON_MULTILINEMACRO_BEGIN do { ++#define RAPIDJSON_MULTILINEMACRO_BEGIN do { + #define RAPIDJSON_MULTILINEMACRO_END \ + } while((void)0, 0) + +@@ -484,6 +521,12 @@ RAPIDJSON_NAMESPACE_END + #define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + ++#if defined(__has_builtin) ++#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x) ++#else ++#define RAPIDJSON_HAS_BUILTIN(x) 0 ++#endif ++ + /////////////////////////////////////////////////////////////////////////////// + // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +@@ -529,16 +572,23 @@ RAPIDJSON_NAMESPACE_END + /////////////////////////////////////////////////////////////////////////////// + // C++11 features + ++#ifndef RAPIDJSON_HAS_CXX11 ++#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L) ++#endif ++ + #ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +-#if defined(__clang__) ++#if RAPIDJSON_HAS_CXX11 ++#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 ++#elif defined(__clang__) + #if __has_feature(cxx_rvalue_references) && \ +- (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) ++ (defined(_MSC_VER) || 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) ++ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ ++ (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + + #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 + #else +@@ -546,46 +596,120 @@ RAPIDJSON_NAMESPACE_END + #endif + #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + ++#if RAPIDJSON_HAS_CXX11_RVALUE_REFS ++#include // std::move ++#endif ++ + #ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +-#if defined(__clang__) ++#if RAPIDJSON_HAS_CXX11 ++#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 ++#elif 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 ++#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ ++ (defined(_MSC_VER) && _MSC_VER >= 1900) || \ ++ (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + #define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 + #else + #define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 + #endif + #endif ++#ifndef RAPIDJSON_NOEXCEPT + #if RAPIDJSON_HAS_CXX11_NOEXCEPT + #define RAPIDJSON_NOEXCEPT noexcept + #else +-#define RAPIDJSON_NOEXCEPT /* noexcept */ ++#define RAPIDJSON_NOEXCEPT throw() + #endif // RAPIDJSON_HAS_CXX11_NOEXCEPT ++#endif + + // no automatic detection, yet + #ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS ++#if (defined(_MSC_VER) && _MSC_VER >= 1700) ++#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1 ++#else + #define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 + #endif ++#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) ++#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ ++ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ ++ (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 + #else + #define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 + #endif + #endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + ++/////////////////////////////////////////////////////////////////////////////// ++// C++17 features ++ ++#ifndef RAPIDJSON_HAS_CXX17 ++#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L) ++#endif ++ ++#if RAPIDJSON_HAS_CXX17 ++# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] ++#elif defined(__has_cpp_attribute) ++# if __has_cpp_attribute(clang::fallthrough) ++# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]] ++# elif __has_cpp_attribute(fallthrough) ++# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough)) ++# else ++# define RAPIDJSON_DELIBERATE_FALLTHROUGH ++# endif ++#else ++# define RAPIDJSON_DELIBERATE_FALLTHROUGH ++#endif ++ + //!@endcond + ++//! Assertion (in non-throwing contexts). ++ /*! \ingroup RAPIDJSON_CONFIG ++ Some functions provide a \c noexcept guarantee, if the compiler supports it. ++ In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to ++ throw an exception. This macro adds a separate customization point for ++ such cases. ++ ++ Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is ++ supported, and to \ref RAPIDJSON_ASSERT otherwise. ++ */ ++ ++/////////////////////////////////////////////////////////////////////////////// ++// RAPIDJSON_NOEXCEPT_ASSERT ++ ++#ifndef RAPIDJSON_NOEXCEPT_ASSERT ++#ifdef RAPIDJSON_ASSERT_THROWS ++#include ++#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) ++#else ++#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) ++#endif // RAPIDJSON_ASSERT_THROWS ++#endif // RAPIDJSON_NOEXCEPT_ASSERT ++ ++/////////////////////////////////////////////////////////////////////////////// ++// malloc/realloc/free ++ ++#ifndef RAPIDJSON_MALLOC ++///! customization point for global \c malloc ++#define RAPIDJSON_MALLOC(size) std::malloc(size) ++#endif ++#ifndef RAPIDJSON_REALLOC ++///! customization point for global \c realloc ++#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size) ++#endif ++#ifndef RAPIDJSON_FREE ++///! customization point for global \c free ++#define RAPIDJSON_FREE(ptr) std::free(ptr) ++#endif ++ + /////////////////////////////////////////////////////////////////////////////// + // new/delete + + #ifndef RAPIDJSON_NEW + ///! customization point for global \c new +-#define RAPIDJSON_NEW(x) new x ++#define RAPIDJSON_NEW(TypeName) new TypeName + #endif + #ifndef RAPIDJSON_DELETE + ///! customization point for global \c delete +@@ -607,7 +731,7 @@ enum Type { + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object +- kArrayType = 4, //!< array ++ kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number + }; +diff --git a/src/common/thirdparty/rapidjson/reader.h b/src/common/thirdparty/rapidjson/reader.h +index 19f8849b1..55546601e 100644 +--- a/src/common/thirdparty/rapidjson/reader.h ++++ b/src/common/thirdparty/rapidjson/reader.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -20,6 +20,7 @@ + #include "allocators.h" + #include "stream.h" + #include "encodedstream.h" ++#include "internal/clzll.h" + #include "internal/meta.h" + #include "internal/stack.h" + #include "internal/strtod.h" +@@ -33,12 +34,8 @@ + #include + #elif defined(RAPIDJSON_SSE2) + #include +-#endif +- +-#ifdef _MSC_VER +-RAPIDJSON_DIAG_PUSH +-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +-RAPIDJSON_DIAG_OFF(4702) // unreachable code ++#elif defined(RAPIDJSON_NEON) ++#include + #endif + + #ifdef __clang__ +@@ -46,6 +43,10 @@ RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(old-style-cast) + RAPIDJSON_DIAG_OFF(padded) + RAPIDJSON_DIAG_OFF(switch-enum) ++#elif defined(_MSC_VER) ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant ++RAPIDJSON_DIAG_OFF(4702) // unreachable code + #endif + + #ifdef __GNUC__ +@@ -153,6 +154,7 @@ enum ParseFlag { + 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. ++ kParseEscapedApostropheFlag = 512, //!< Allow escaped apostrophe in strings. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS + }; + +@@ -299,16 +301,9 @@ inline const char *SkipWhitespace_SIMD(const char* p) { + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(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 +- } ++ const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); ++ if (r != 16) // some of characters is non-whitespace ++ return p + r; + } + } + +@@ -325,16 +320,9 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(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 +- } ++ const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); ++ if (r != 16) // some of characters is non-whitespace ++ return p + r; + } + + return SkipWhitespace(p, end); +@@ -425,7 +413,92 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + return SkipWhitespace(p, end); + } + +-#endif // RAPIDJSON_SSE2 ++#elif defined(RAPIDJSON_NEON) ++ ++//! Skip whitespace with ARM Neon 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((reinterpret_cast(p) + 15) & static_cast(~15)); ++ while (p != nextAligned) ++ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') ++ ++p; ++ else ++ return p; ++ ++ const uint8x16_t w0 = vmovq_n_u8(' '); ++ const uint8x16_t w1 = vmovq_n_u8('\n'); ++ const uint8x16_t w2 = vmovq_n_u8('\r'); ++ const uint8x16_t w3 = vmovq_n_u8('\t'); ++ ++ for (;; p += 16) { ++ const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); ++ uint8x16_t x = vceqq_u8(s, w0); ++ x = vorrq_u8(x, vceqq_u8(s, w1)); ++ x = vorrq_u8(x, vceqq_u8(s, w2)); ++ x = vorrq_u8(x, vceqq_u8(s, w3)); ++ ++ x = vmvnq_u8(x); // Negate ++ x = vrev64q_u8(x); // Rev in 64 ++ uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract ++ uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract ++ ++ if (low == 0) { ++ if (high != 0) { ++ uint32_t lz = internal::clzll(high); ++ return p + 8 + (lz >> 3); ++ } ++ } else { ++ uint32_t lz = internal::clzll(low); ++ return p + (lz >> 3); ++ } ++ } ++} ++ ++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; ++ ++ const uint8x16_t w0 = vmovq_n_u8(' '); ++ const uint8x16_t w1 = vmovq_n_u8('\n'); ++ const uint8x16_t w2 = vmovq_n_u8('\r'); ++ const uint8x16_t w3 = vmovq_n_u8('\t'); ++ ++ for (; p <= end - 16; p += 16) { ++ const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); ++ uint8x16_t x = vceqq_u8(s, w0); ++ x = vorrq_u8(x, vceqq_u8(s, w1)); ++ x = vorrq_u8(x, vceqq_u8(s, w2)); ++ x = vorrq_u8(x, vceqq_u8(s, w3)); ++ ++ x = vmvnq_u8(x); // Negate ++ x = vrev64q_u8(x); // Rev in 64 ++ uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract ++ uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract ++ ++ if (low == 0) { ++ if (high != 0) { ++ uint32_t lz = internal::clzll(high); ++ return p + 8 + (lz >> 3); ++ } ++ } else { ++ uint32_t lz = internal::clzll(low); ++ return p + (lz >> 3); ++ } ++ } ++ ++ return SkipWhitespace(p, end); ++} ++ ++#endif // RAPIDJSON_NEON + + #ifdef RAPIDJSON_SIMD + //! Template function specialization for InsituStringStream +@@ -471,7 +544,8 @@ public: + /*! \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_() {} ++ GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : ++ stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. +@@ -527,7 +601,84 @@ public: + return Parse(is, handler); + } + +- //! Whether a parse error has occured in the last parsing. ++ //! Initialize JSON text token-by-token parsing ++ /*! ++ */ ++ void IterativeParseInit() { ++ parseResult_.Clear(); ++ state_ = IterativeParsingStartState; ++ } ++ ++ //! Parse one token from JSON text ++ /*! \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 ++ bool IterativeParseNext(InputStream& is, Handler& handler) { ++ while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { ++ SkipWhitespaceAndComments(is); ++ ++ Token t = Tokenize(is.Peek()); ++ IterativeParsingState n = Predict(state_, t); ++ IterativeParsingState d = Transit(state_, t, n, is, handler); ++ ++ // If we've finished or hit an error... ++ if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) { ++ // Report errors. ++ if (d == IterativeParsingErrorState) { ++ HandleError(state_, is); ++ return false; ++ } ++ ++ // Transition to the finish state. ++ RAPIDJSON_ASSERT(d == IterativeParsingFinishState); ++ state_ = d; ++ ++ // If StopWhenDone is not set... ++ if (!(parseFlags & kParseStopWhenDoneFlag)) { ++ // ... and extra non-whitespace data is found... ++ SkipWhitespaceAndComments(is); ++ if (is.Peek() != '\0') { ++ // ... this is considered an error. ++ HandleError(state_, is); ++ return false; ++ } ++ } ++ ++ // Success! We are done! ++ return true; ++ } ++ ++ // Transition to the new state. ++ state_ = d; ++ ++ // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now. ++ if (!IsIterativeParsingDelimiterState(n)) ++ return true; ++ } ++ ++ // We reached the end of file. ++ stack_.Clear(); ++ ++ if (state_ != IterativeParsingFinishState) { ++ HandleError(state_, is); ++ return false; ++ } ++ ++ return true; ++ } ++ ++ //! Check if token-by-token parsing JSON text is complete ++ /*! \return Whether the JSON has been fully decoded. ++ */ ++ RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const { ++ return IsIterativeParsingCompleteState(state_); ++ } ++ ++ //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. +@@ -575,7 +726,7 @@ private: + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) +- while (is.Peek() != '\0' && is.Take() != '\n'); ++ while (is.Peek() != '\0' && is.Take() != '\n') {} + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + +@@ -750,7 +901,7 @@ private: + return false; + } + +- // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). ++ // Helper function to parse four hexadecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; +@@ -841,7 +992,7 @@ private: + //!@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, '/', + 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, +@@ -857,26 +1008,38 @@ private: + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape +- size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset ++ size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); + } ++ else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe ++ is.Take(); ++ os.Put('\''); ++ } + 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)) ++ if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) { ++ // high surrogate, check if followed by valid low surrogate ++ if (RAPIDJSON_LIKELY(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; ++ } ++ // single low surrogate ++ else ++ { + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); +- codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; ++ } + } + TEncoding::Encode(os, codepoint); + } +@@ -892,7 +1055,7 @@ private: + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else +- RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell()); ++ RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + else { + size_t offset = is.Tell(); +@@ -927,7 +1090,7 @@ private: + // 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 }; ++ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); +@@ -936,7 +1099,7 @@ private: + const __m128i s = _mm_load_si128(reinterpret_cast(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 t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped +@@ -948,11 +1111,13 @@ private: + #else + length = static_cast(__builtin_ffs(r) - 1); + #endif +- char* q = reinterpret_cast(os.Push(length)); +- for (size_t i = 0; i < length; i++) +- q[i] = p[i]; ++ if (length != 0) { ++ char* q = reinterpret_cast(os.Push(length)); ++ for (size_t i = 0; i < length; i++) ++ q[i] = p[i]; + +- p += length; ++ p += length; ++ } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); +@@ -988,7 +1153,7 @@ private: + // 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 }; ++ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); +@@ -997,7 +1162,7 @@ private: + const __m128i s = _mm_load_si128(reinterpret_cast(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 t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped +@@ -1036,7 +1201,7 @@ private: + // 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 }; ++ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); +@@ -1045,7 +1210,7 @@ private: + const __m128i s = _mm_load_si128(reinterpret_cast(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 t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped +@@ -1064,27 +1229,199 @@ private: + + is.src_ = is.dst_ = p; + } +-#endif ++#elif defined(RAPIDJSON_NEON) ++ // StringStream -> StackStream ++ static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& 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((reinterpret_cast(p) + 15) & static_cast(~15)); ++ while (p != nextAligned) ++ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { ++ is.src_ = p; ++ return; ++ } ++ else ++ os.Put(*p++); + +- template ++ // The rest of string using SIMD ++ const uint8x16_t s0 = vmovq_n_u8('"'); ++ const uint8x16_t s1 = vmovq_n_u8('\\'); ++ const uint8x16_t s2 = vmovq_n_u8('\b'); ++ const uint8x16_t s3 = vmovq_n_u8(32); ++ ++ for (;; p += 16) { ++ const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); ++ uint8x16_t x = vceqq_u8(s, s0); ++ x = vorrq_u8(x, vceqq_u8(s, s1)); ++ x = vorrq_u8(x, vceqq_u8(s, s2)); ++ x = vorrq_u8(x, vcltq_u8(s, s3)); ++ ++ x = vrev64q_u8(x); // Rev in 64 ++ uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract ++ uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract ++ ++ SizeType length = 0; ++ bool escaped = false; ++ if (low == 0) { ++ if (high != 0) { ++ uint32_t lz = internal::clzll(high); ++ length = 8 + (lz >> 3); ++ escaped = true; ++ } ++ } else { ++ uint32_t lz = internal::clzll(low); ++ length = lz >> 3; ++ escaped = true; ++ } ++ if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped ++ if (length != 0) { ++ char* q = reinterpret_cast(os.Push(length)); ++ for (size_t i = 0; i < length; i++) ++ q[i] = p[i]; ++ ++ p += length; ++ } ++ break; ++ } ++ vst1q_u8(reinterpret_cast(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((reinterpret_cast(p) + 15) & static_cast(~15)); ++ while (p != nextAligned) ++ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { ++ is.src_ = p; ++ is.dst_ = q; ++ return; ++ } ++ else ++ *q++ = *p++; ++ ++ // The rest of string using SIMD ++ const uint8x16_t s0 = vmovq_n_u8('"'); ++ const uint8x16_t s1 = vmovq_n_u8('\\'); ++ const uint8x16_t s2 = vmovq_n_u8('\b'); ++ const uint8x16_t s3 = vmovq_n_u8(32); ++ ++ for (;; p += 16, q += 16) { ++ const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); ++ uint8x16_t x = vceqq_u8(s, s0); ++ x = vorrq_u8(x, vceqq_u8(s, s1)); ++ x = vorrq_u8(x, vceqq_u8(s, s2)); ++ x = vorrq_u8(x, vcltq_u8(s, s3)); ++ ++ x = vrev64q_u8(x); // Rev in 64 ++ uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract ++ uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract ++ ++ SizeType length = 0; ++ bool escaped = false; ++ if (low == 0) { ++ if (high != 0) { ++ uint32_t lz = internal::clzll(high); ++ length = 8 + (lz >> 3); ++ escaped = true; ++ } ++ } else { ++ uint32_t lz = internal::clzll(low); ++ length = lz >> 3; ++ escaped = true; ++ } ++ if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped ++ for (const char* pend = p + length; p != pend; ) { ++ *q++ = *p++; ++ } ++ break; ++ } ++ vst1q_u8(reinterpret_cast(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((reinterpret_cast(p) + 15) & static_cast(~15)); ++ for (; p != nextAligned; p++) ++ if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { ++ is.src_ = is.dst_ = p; ++ return; ++ } ++ ++ // The rest of string using SIMD ++ const uint8x16_t s0 = vmovq_n_u8('"'); ++ const uint8x16_t s1 = vmovq_n_u8('\\'); ++ const uint8x16_t s2 = vmovq_n_u8('\b'); ++ const uint8x16_t s3 = vmovq_n_u8(32); ++ ++ for (;; p += 16) { ++ const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); ++ uint8x16_t x = vceqq_u8(s, s0); ++ x = vorrq_u8(x, vceqq_u8(s, s1)); ++ x = vorrq_u8(x, vceqq_u8(s, s2)); ++ x = vorrq_u8(x, vcltq_u8(s, s3)); ++ ++ x = vrev64q_u8(x); // Rev in 64 ++ uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract ++ uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract ++ ++ if (low == 0) { ++ if (high != 0) { ++ uint32_t lz = internal::clzll(high); ++ p += 8 + (lz >> 3); ++ break; ++ } ++ } else { ++ uint32_t lz = internal::clzll(low); ++ p += lz >> 3; ++ break; ++ } ++ } ++ ++ is.src_ = is.dst_ = p; ++ } ++#endif // RAPIDJSON_NEON ++ ++ template + class NumberStream; + +- template +- class NumberStream { ++ template ++ class NumberStream { + 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) {} ++ RAPIDJSON_FORCEINLINE void Push(char) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } +- const char* Pop() { return 0; } ++ const StackCharacter* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); +@@ -1092,47 +1429,47 @@ private: + InputStream& is; + }; + +- template +- class NumberStream : public NumberStream { +- typedef NumberStream Base; ++ template ++ class NumberStream : public NumberStream { ++ typedef NumberStream Base; + public: +- NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} +- ~NumberStream() {} ++ NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { +- stackStream.Put(static_cast(Base::is.Peek())); ++ stackStream.Put(static_cast(Base::is.Peek())); + return Base::is.Take(); + } + +- RAPIDJSON_FORCEINLINE void Push(char c) { ++ RAPIDJSON_FORCEINLINE void Push(StackCharacter c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + +- const char* Pop() { ++ const StackCharacter* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: +- StackStream stackStream; ++ StackStream stackStream; + }; + +- template +- class NumberStream : public NumberStream { +- typedef NumberStream Base; ++ template ++ class NumberStream : public NumberStream { ++ typedef NumberStream Base; + public: +- NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} +- ~NumberStream() {} ++ NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { ++ typedef typename internal::SelectIf, typename TargetEncoding::Ch, char>::Type NumberCharacter; ++ + internal::StreamLocalCopy copy(is); +- NumberStream::quiet_NaN(); ++ if (Consume(s, 'N')) { ++ if (Consume(s, 'a') && Consume(s, 'N')) { ++ d = std::numeric_limits::quiet_NaN(); ++ useNanOrInf = true; ++ } + } +- else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) { +- d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::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 if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { ++ if (Consume(s, 'n') && Consume(s, 'f')) { ++ d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); ++ useNanOrInf = true; ++ ++ 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 ++ ++ if (RAPIDJSON_UNLIKELY(!useNanOrInf)) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); ++ } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); +@@ -1231,8 +1577,6 @@ private: + // 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'); + } + } +@@ -1302,9 +1646,18 @@ private: + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast(s.Take() - '0'); + if (expMinus) { ++ // (exp + expFrac) must not underflow int => we're detecting when -exp gets ++ // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into ++ // underflow territory): ++ // ++ // -(exp * 10 + 9) + expFrac >= INT_MIN ++ // <=> exp <= (expFrac - INT_MIN - 9) / 10 ++ RAPIDJSON_ASSERT(expFrac <= 0); ++ int maxExp = (expFrac + 2147483639) / 10; ++ + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); +- if (exp >= 214748364) { // Issue #313: prevent overflow exponent ++ if (RAPIDJSON_UNLIKELY(exp > maxExp)) { + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } +@@ -1341,10 +1694,10 @@ private: + } + else { + SizeType numCharsToCopy = static_cast(s.Length()); +- StringStream srcStream(s.Pop()); ++ GenericStringStream > srcStream(s.Pop()); + StackStream dstStream(stack_); + while (numCharsToCopy--) { +- Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); ++ Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); +@@ -1354,7 +1707,7 @@ private: + } + else { + size_t length = s.Length(); +- const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. ++ const NumberCharacter* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; +@@ -1363,6 +1716,13 @@ private: + else + d = internal::StrtodNormalPrecision(d, p); + ++ // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal ++ if (d > (std::numeric_limits::max)()) { ++ // Overflow ++ // TODO: internal::StrtodX should report overflow (or underflow) ++ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); ++ } ++ + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { +@@ -1408,29 +1768,31 @@ private: + + // States + enum IterativeParsingState { +- IterativeParsingStartState = 0, +- IterativeParsingFinishState, +- IterativeParsingErrorState, ++ IterativeParsingFinishState = 0, // sink states at top ++ IterativeParsingErrorState, // sink states at top ++ IterativeParsingStartState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, +- IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, +- IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, +- IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, + + // Single value state +- IterativeParsingValueState +- }; ++ IterativeParsingValueState, ++ ++ // Delimiter states (at bottom) ++ IterativeParsingElementDelimiterState, ++ IterativeParsingMemberDelimiterState, ++ IterativeParsingKeyValueDelimiterState, + +- enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 }; ++ cIterativeParsingStateCount ++ }; + + // Tokens + enum Token { +@@ -1452,7 +1814,7 @@ private: + kTokenCount + }; + +- RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { ++ RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const { + + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + #define N NumberToken +@@ -1479,9 +1841,21 @@ private: + return NumberToken; + } + +- RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { ++ RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { ++ // 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 ++ }, + // Start + { + IterativeParsingArrayInitialState, // Left bracket +@@ -1496,18 +1870,6 @@ private: + 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 +@@ -1536,20 +1898,6 @@ private: + 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 +@@ -1564,20 +1912,6 @@ private: + 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, +@@ -1612,6 +1946,18 @@ private: + IterativeParsingErrorState, // Null + IterativeParsingErrorState // 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 ++ }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) +@@ -1626,18 +1972,34 @@ private: + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, +- // ArrayFinish(sink state) ++ // MemberDelimiter + { +- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, +- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, +- IterativeParsingErrorState ++ 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 + }, +- // Single Value (sink state) ++ // KeyValueDelimiter + { +- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, +- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, +- IterativeParsingErrorState +- } ++ 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 ++ }, + }; // End of G + + return static_cast(G[state][token]); +@@ -1818,6 +2180,14 @@ private: + } + } + ++ RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const { ++ return s >= IterativeParsingElementDelimiterState; ++ } ++ ++ RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const { ++ return s <= IterativeParsingErrorState; ++ } ++ + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); +@@ -1856,6 +2226,7 @@ private: + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; ++ IterativeParsingState state_; + }; // class GenericReader + + //! Reader with UTF8 encoding and default allocator. +@@ -1863,7 +2234,7 @@ typedef GenericReader, UTF8<> > Reader; + + RAPIDJSON_NAMESPACE_END + +-#ifdef __clang__ ++#if defined(__clang__) || defined(_MSC_VER) + RAPIDJSON_DIAG_POP + #endif + +@@ -1872,8 +2243,4 @@ RAPIDJSON_DIAG_POP + RAPIDJSON_DIAG_POP + #endif + +-#ifdef _MSC_VER +-RAPIDJSON_DIAG_POP +-#endif +- + #endif // RAPIDJSON_READER_H_ +diff --git a/src/common/thirdparty/rapidjson/schema.h b/src/common/thirdparty/rapidjson/schema.h +index 8497d3031..439133fa6 100644 +--- a/src/common/thirdparty/rapidjson/schema.h ++++ b/src/common/thirdparty/rapidjson/schema.h +@@ -1,5 +1,5 @@ + // 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 +@@ -7,9 +7,9 @@ + // + // 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 ++// 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_ +@@ -17,6 +17,9 @@ + + #include "document.h" + #include "pointer.h" ++#include "stringbuffer.h" ++#include "error/en.h" ++#include "uri.h" + #include // abs, floor + + #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +@@ -25,7 +28,7 @@ + #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)) ++#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 +@@ -47,10 +50,6 @@ + #define RAPIDJSON_SCHEMA_VERBOSE 0 + #endif + +-#if RAPIDJSON_SCHEMA_VERBOSE +-#include "stringbuffer.h" +-#endif +- + RAPIDJSON_DIAG_PUSH + + #if defined(__GNUC__) +@@ -62,9 +61,7 @@ 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 ++#elif defined(_MSC_VER) + RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated + #endif + +@@ -77,50 +74,163 @@ RAPIDJSON_NAMESPACE_BEGIN + + namespace internal { + +-inline void PrintInvalidKeyword(const char* keyword) { +- printf("Fail keyword: %s\n", keyword); ++inline void PrintInvalidKeywordData(const char* keyword) { ++ printf(" Fail keyword: '%s'\n", keyword); ++} ++ ++inline void PrintInvalidKeywordData(const wchar_t* keyword) { ++ wprintf(L" Fail keyword: '%ls'\n", keyword); ++} ++ ++inline void PrintInvalidDocumentData(const char* document) { ++ printf(" Fail document: '%s'\n", document); ++} ++ ++inline void PrintInvalidDocumentData(const wchar_t* document) { ++ wprintf(L" Fail document: '%ls'\n", document); ++} ++ ++inline void PrintValidatorPointersData(const char* s, const char* d, unsigned depth) { ++ printf(" Sch: %*s'%s'\n Doc: %*s'%s'\n", depth * 4, " ", s, depth * 4, " ", d); ++} ++ ++inline void PrintValidatorPointersData(const wchar_t* s, const wchar_t* d, unsigned depth) { ++ wprintf(L" Sch: %*ls'%ls'\n Doc: %*ls'%ls'\n", depth * 4, L" ", s, depth * 4, L" ", d); ++} ++ ++inline void PrintSchemaIdsData(const char* base, const char* local, const char* resolved) { ++ printf(" Resolving id: Base: '%s', Local: '%s', Resolved: '%s'\n", base, local, resolved); ++} ++ ++inline void PrintSchemaIdsData(const wchar_t* base, const wchar_t* local, const wchar_t* resolved) { ++ wprintf(L" Resolving id: Base: '%ls', Local: '%ls', Resolved: '%ls'\n", base, local, resolved); ++} ++ ++inline void PrintMethodData(const char* method) { ++ printf("%s\n", method); ++} ++ ++inline void PrintMethodData(const char* method, bool b) { ++ printf("%s, Data: '%s'\n", method, b ? "true" : "false"); ++} ++ ++inline void PrintMethodData(const char* method, int64_t i) { ++ printf("%s, Data: '%" PRId64 "'\n", method, i); + } + +-inline void PrintInvalidKeyword(const wchar_t* keyword) { +- wprintf(L"Fail keyword: %ls\n", keyword); ++inline void PrintMethodData(const char* method, uint64_t u) { ++ printf("%s, Data: '%" PRIu64 "'\n", method, u); + } + +-inline void PrintInvalidDocument(const char* document) { +- printf("Fail document: %s\n\n", document); ++inline void PrintMethodData(const char* method, double d) { ++ printf("%s, Data: '%lf'\n", method, d); + } + +-inline void PrintInvalidDocument(const wchar_t* document) { +- wprintf(L"Fail document: %ls\n\n", document); ++inline void PrintMethodData(const char* method, const char* s) { ++ printf("%s, Data: '%s'\n", method, s); + } + +-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 PrintMethodData(const char* method, const wchar_t* s) { ++ wprintf(L"%hs, Data: '%ls'\n", method, s); + } + +-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); ++inline void PrintMethodData(const char* method, const char* s1, const char* s2) { ++ printf("%s, Data: '%s', '%s'\n", method, s1, s2); ++} ++ ++inline void PrintMethodData(const char* method, const wchar_t* s1, const wchar_t* s2) { ++ wprintf(L"%hs, Data: '%ls', '%ls'\n", method, s1, s2); + } + + } // namespace internal + + #endif // RAPIDJSON_SCHEMA_VERBOSE + +-/////////////////////////////////////////////////////////////////////////////// +-// RAPIDJSON_INVALID_KEYWORD_RETURN +- ++#ifndef RAPIDJSON_SCHEMA_PRINT + #if RAPIDJSON_SCHEMA_VERBOSE +-#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) ++#define RAPIDJSON_SCHEMA_PRINT(name, ...) internal::Print##name##Data(__VA_ARGS__) + #else +-#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) ++#define RAPIDJSON_SCHEMA_PRINT(name, ...) ++#endif + #endif + +-#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\ ++/////////////////////////////////////////////////////////////////////////////// ++// RAPIDJSON_INVALID_KEYWORD_RETURN ++ ++#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ + RAPIDJSON_MULTILINEMACRO_BEGIN\ +- context.invalidKeyword = keyword.GetString();\ +- RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\ ++ context.invalidCode = code;\ ++ context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ ++ RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, context.invalidKeyword);\ + return false;\ + RAPIDJSON_MULTILINEMACRO_END + ++/////////////////////////////////////////////////////////////////////////////// ++// ValidateFlag ++ ++/*! \def RAPIDJSON_VALIDATE_DEFAULT_FLAGS ++ \ingroup RAPIDJSON_CONFIG ++ \brief User-defined kValidateDefaultFlags definition. ++ ++ User can define this as any \c ValidateFlag combinations. ++*/ ++#ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS ++#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags ++#endif ++ ++//! Combination of validate flags ++/*! \see ++ */ ++enum ValidateFlag { ++ kValidateNoFlags = 0, //!< No flags are set. ++ kValidateContinueOnErrorFlag = 1, //!< Don't stop after first validation error. ++ kValidateReadFlag = 2, //!< Validation is for a read semantic. ++ kValidateWriteFlag = 4, //!< Validation is for a write semantic. ++ kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS ++}; ++ ++/////////////////////////////////////////////////////////////////////////////// ++// Specification ++enum SchemaDraft { ++ kDraftUnknown = -1, ++ kDraftNone = 0, ++ kDraft03 = 3, ++ kDraftMin = 4, //!< Current minimum supported draft ++ kDraft04 = 4, ++ kDraft05 = 5, ++ kDraftMax = 5, //!< Current maximum supported draft ++ kDraft06 = 6, ++ kDraft07 = 7, ++ kDraft2019_09 = 8, ++ kDraft2020_12 = 9 ++}; ++ ++enum OpenApiVersion { ++ kVersionUnknown = -1, ++ kVersionNone = 0, ++ kVersionMin = 2, //!< Current minimum supported version ++ kVersion20 = 2, ++ kVersion30 = 3, ++ kVersionMax = 3, //!< Current maximum supported version ++ kVersion31 = 4, ++}; ++ ++struct Specification { ++ Specification(SchemaDraft d) : draft(d), oapi(kVersionNone) {} ++ Specification(OpenApiVersion o) : oapi(o) { ++ if (oapi == kVersion20) draft = kDraft04; ++ else if (oapi == kVersion30) draft = kDraft05; ++ else if (oapi == kVersion31) draft = kDraft2020_12; ++ else draft = kDraft04; ++ } ++ ~Specification() {} ++ bool IsSupported() const { ++ return ((draft >= kDraftMin && draft <= kDraftMax) && ((oapi == kVersionNone) || (oapi >= kVersionMin && oapi <= kVersionMax))); ++ } ++ SchemaDraft draft; ++ OpenApiVersion oapi; ++}; ++ + /////////////////////////////////////////////////////////////////////////////// + // Forward declarations + +@@ -139,6 +249,8 @@ class ISchemaValidator { + public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; ++ virtual void SetValidateFlags(unsigned flags) = 0; ++ virtual unsigned GetValidateFlags() const = 0; + }; + + /////////////////////////////////////////////////////////////////////////////// +@@ -148,7 +260,7 @@ template + class ISchemaStateFactory { + public: + virtual ~ISchemaStateFactory() {} +- virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0; ++ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; +@@ -157,6 +269,65 @@ public: + virtual void FreeState(void* p) = 0; + }; + ++/////////////////////////////////////////////////////////////////////////////// ++// IValidationErrorHandler ++ ++template ++class IValidationErrorHandler { ++public: ++ typedef typename SchemaType::Ch Ch; ++ typedef typename SchemaType::SValue SValue; ++ ++ virtual ~IValidationErrorHandler() {} ++ ++ virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0; ++ virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0; ++ virtual void NotMultipleOf(double actual, const SValue& expected) = 0; ++ virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0; ++ virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0; ++ virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0; ++ virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0; ++ virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0; ++ virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0; ++ ++ virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0; ++ virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0; ++ virtual void DoesNotMatch(const Ch* str, SizeType length) = 0; ++ ++ virtual void DisallowedItem(SizeType index) = 0; ++ virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0; ++ virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0; ++ virtual void DuplicateItems(SizeType index1, SizeType index2) = 0; ++ ++ virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0; ++ virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0; ++ virtual void StartMissingProperties() = 0; ++ virtual void AddMissingProperty(const SValue& name) = 0; ++ virtual bool EndMissingProperties() = 0; ++ virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0; ++ virtual void DisallowedProperty(const Ch* name, SizeType length) = 0; ++ ++ virtual void StartDependencyErrors() = 0; ++ virtual void StartMissingDependentProperties() = 0; ++ virtual void AddMissingDependentProperty(const SValue& targetName) = 0; ++ virtual void EndMissingDependentProperties(const SValue& sourceName) = 0; ++ virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0; ++ virtual bool EndDependencyErrors() = 0; ++ ++ virtual void DisallowedValue(const ValidateErrorCode code) = 0; ++ virtual void StartDisallowedType() = 0; ++ virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0; ++ virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0; ++ virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0; ++ virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0; ++ virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0; ++ virtual void MultipleOneOf(SizeType index1, SizeType index2) = 0; ++ virtual void Disallowed() = 0; ++ virtual void DisallowedWhenWriting() = 0; ++ virtual void DisallowedWhenReading() = 0; ++}; ++ ++ + /////////////////////////////////////////////////////////////////////////////// + // Hasher + +@@ -174,10 +345,10 @@ public: + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } +- bool Double(double d) { +- Number n; ++ bool Double(double d) { ++ Number n; + if (d < 0) n.u.i = static_cast(d); +- else n.u.u = static_cast(d); ++ else n.u.u = static_cast(d); + n.d = d; + return WriteNumber(n); + } +@@ -261,6 +432,7 @@ template + struct SchemaValidationContext { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; ++ typedef IValidationErrorHandler ErrorHandlerType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + +@@ -270,11 +442,14 @@ struct SchemaValidationContext { + kPatternValidatorWithAdditionalProperty + }; + +- SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) : ++ SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s, unsigned fl = 0) : + factory(f), ++ error_handler(eh), + schema(s), ++ flags(fl), + valueSchema(), + invalidKeyword(), ++ invalidCode(), + hasher(), + arrayElementHashCodes(), + validators(), +@@ -295,13 +470,19 @@ struct SchemaValidationContext { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { +- for (SizeType i = 0; i < validatorCount; i++) +- factory.DestroySchemaValidator(validators[i]); ++ for (SizeType i = 0; i < validatorCount; i++) { ++ if (validators[i]) { ++ factory.DestroySchemaValidator(validators[i]); ++ } ++ } + factory.FreeState(validators); + } + if (patternPropertiesValidators) { +- for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) +- factory.DestroySchemaValidator(patternPropertiesValidators[i]); ++ for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) { ++ if (patternPropertiesValidators[i]) { ++ factory.DestroySchemaValidator(patternPropertiesValidators[i]); ++ } ++ } + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) +@@ -311,9 +492,12 @@ struct SchemaValidationContext { + } + + SchemaValidatorFactoryType& factory; ++ ErrorHandlerType& error_handler; + const SchemaType* schema; ++ unsigned flags; + const SchemaType* valueSchema; + const Ch* invalidKeyword; ++ ValidateErrorCode invalidCode; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; +@@ -345,15 +529,23 @@ public: + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; ++ typedef IValidationErrorHandler ErrorHandler; ++ typedef GenericUri UriType; + friend class GenericSchemaDocument; + +- Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : ++ Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator, const UriType& id = UriType()) : + allocator_(allocator), ++ uri_(schemaDocument->GetURI(), *allocator), ++ id_(id, allocator), ++ spec_(schemaDocument->GetSpecification()), ++ pointer_(p, allocator), ++ typeless_(schemaDocument->GetTypeless()), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), ++ notValidatorIndex_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), +@@ -377,15 +569,44 @@ public: + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), +- exclusiveMaximum_(false) ++ exclusiveMaximum_(false), ++ defaultValueLength_(0), ++ readOnly_(false), ++ writeOnly_(false), ++ nullable_(false) + { +- typedef typename SchemaDocumentType::ValueType ValueType; ++ GenericStringBuffer sb; ++ p.StringifyUriFragment(sb); ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Schema", sb.GetString(), id.GetString()); ++ + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + ++ // PR #1393 ++ // Early add this Schema and its $ref(s) in schemaDocument's map to avoid infinite ++ // recursion (with recursive schemas), since schemaDocument->getSchema() is always ++ // checked before creating a new one. Don't cache typeless_, though. ++ if (this != typeless_) { ++ typedef typename SchemaDocumentType::SchemaEntry SchemaEntry; ++ SchemaEntry *entry = schemaDocument->schemaMap_.template Push(); ++ new (entry) SchemaEntry(pointer_, this, true, allocator_); ++ schemaDocument->AddSchemaRefs(this); ++ } ++ + if (!value.IsObject()) + return; + ++ // If we have an id property, resolve it with the in-scope id ++ // Not supported for open api 2.0 or 3.0 ++ if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) ++ if (const ValueType* v = GetMember(value, GetIdString())) { ++ if (v->IsString()) { ++ UriType local(*v, allocator); ++ id_ = local.Resolve(id_, allocator); ++ RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), v->GetString(), id_.GetString()); ++ } ++ } ++ + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) +@@ -395,29 +616,33 @@ public: + AddType(*itr); + } + +- if (const ValueType* v = GetMember(value, GetEnumString())) ++ if (const ValueType* v = GetMember(value, GetEnumString())) { + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { +- typedef Hasher > EnumHasherType; +- char buffer[256 + 24]; +- MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); ++ typedef Hasher > EnumHasherType; ++ char buffer[256u + 24]; ++ MemoryPoolAllocator hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } ++ } + +- if (schemaDocument) { ++ if (schemaDocument) + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); ++ ++ // AnyOf, OneOf, Not not supported for open api 2.0 ++ if (schemaDocument && spec_.oapi != kVersion20) { + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); +- } + +- if (const ValueType* v = GetMember(value, GetNotString())) { +- schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); +- notValidatorIndex_ = validatorCount_; +- validatorCount_++; ++ if (const ValueType* v = GetMember(value, GetNotString())) { ++ schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_); ++ notValidatorIndex_ = validatorCount_; ++ validatorCount_++; ++ } + } + + // Object +@@ -432,12 +657,14 @@ public: + 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); + ++ // Dependencies not supported for open api 2.0 and 3.0 ++ if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); +@@ -453,7 +680,7 @@ public: + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; +- properties_[i].schema = GetTypeless(); ++ properties_[i].schema = typeless_; + } + } + } +@@ -463,10 +690,12 @@ public: + 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); ++ schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_); + } + } + ++ // PatternProperties not supported for open api 2.0 and 3.0 ++ if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); +@@ -474,8 +703,9 @@ public: + + 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); ++ PointerType r = q.Append(itr->name, allocator_); ++ patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name, schemaDocument, r); ++ schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, r, itr->value, document, id_); + patternPropertyCount_++; + } + } +@@ -490,6 +720,8 @@ public: + } + } + ++ // Dependencies not supported for open api 2.0 and 3.0 ++ if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; +@@ -507,7 +739,7 @@ public: + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; +- schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); ++ schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } +@@ -519,7 +751,7 @@ public: + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) +- schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); ++ schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); +@@ -529,23 +761,25 @@ public: + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation +- schemaDocument->CreateSchema(&itemsList_, q, *v, document); ++ schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast(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); ++ schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + ++ // AdditionalItems not supported for openapi 2.0 and 3.0 ++ if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + 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); ++ schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); +@@ -555,7 +789,7 @@ public: + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) +- pattern_ = CreatePattern(*v); ++ pattern_ = CreatePattern(*v, schemaDocument, p.Append(GetPatternString(), allocator_)); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) +@@ -572,12 +806,33 @@ public: + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); ++ ++ // Default ++ if (const ValueType* v = GetMember(value, GetDefaultValueString())) ++ if (v->IsString()) ++ defaultValueLength_ = v->GetStringLength(); ++ ++ // ReadOnly - open api only (until draft 7 supported) ++ // WriteOnly - open api 3 only (until draft 7 supported) ++ // Both can't be true ++ if (spec_.oapi != kVersionNone) ++ AssignIfExist(readOnly_, value, GetReadOnlyString()); ++ if (spec_.oapi >= kVersion30) ++ AssignIfExist(writeOnly_, value, GetWriteOnlyString()); ++ if (readOnly_ && writeOnly_) ++ schemaDocument->SchemaError(kSchemaErrorReadOnlyAndWriteOnly, p); ++ ++ // Nullable - open api 3 only ++ // If true add 'null' as allowable type ++ if (spec_.oapi >= kVersion30) { ++ AssignIfExist(nullable_, value, GetNullableString()); ++ if (nullable_) ++ AddType(GetNullString()); ++ } + } + + ~Schema() { +- if (allocator_) { +- allocator_->Free(enum_); +- } ++ AllocatorType::Free(enum_); + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); +@@ -592,12 +847,29 @@ public: + #if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); +- allocator_->Free(pattern_); ++ AllocatorType::Free(pattern_); + } + #endif + } + ++ const SValue& GetURI() const { ++ return uri_; ++ } ++ ++ const UriType& GetId() const { ++ return id_; ++ } ++ ++ const Specification& GetSpecification() const { ++ return spec_; ++ } ++ ++ const PointerType& GetPointer() const { ++ return pointer_; ++ } ++ + bool BeginValue(Context& context) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::BeginValue"); + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; +@@ -610,12 +882,18 @@ public: + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) +- context.valueSchema = GetTypeless(); +- else +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); ++ context.valueSchema = typeless_; ++ else { ++ context.error_handler.DisallowedItem(context.arrayElementIndex); ++ // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error ++ context.valueSchema = typeless_; ++ // Must bump arrayElementIndex for when kValidateContinueOnErrorFlag is set ++ context.arrayElementIndex++; ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalItems); ++ } + } + else +- context.valueSchema = GetTypeless(); ++ context.valueSchema = typeless_; + + context.arrayElementIndex++; + } +@@ -623,6 +901,8 @@ public: + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndValue"); ++ // Only check pattern properties if we have validators + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; +@@ -637,133 +917,178 @@ public: + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { +- if (!patternValid) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); ++ if (!patternValid) { ++ context.error_handler.PropertyViolations(context.patternPropertiesValidators, count); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); ++ } + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { +- if (!patternValid || !otherValid) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); ++ if (!patternValid || !otherValid) { ++ context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); ++ } ++ } ++ else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty) ++ context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } +- else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + +- if (enum_) { ++ // For enums only check if we have a hasher ++ if (enum_ && context.hasher) { + 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()); ++ context.error_handler.DisallowedValue(kValidateErrorEnum); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorEnum); + 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; ++ // Only check allOf etc if we have validators ++ if (context.validatorCount > 0) { ++ if (allOf_.schemas) ++ for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) ++ if (!context.validators[i]->IsValid()) { ++ context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf); ++ } ++ ++ if (anyOf_.schemas) { ++ for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) ++ if (context.validators[i]->IsValid()) ++ goto foundAny; ++ context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf); ++ foundAny:; ++ } ++ ++ if (oneOf_.schemas) { ++ bool oneValid = false; ++ SizeType firstMatch = 0; ++ for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) ++ if (context.validators[i]->IsValid()) { ++ if (oneValid) { ++ context.error_handler.MultipleOneOf(firstMatch, i - oneOf_.begin); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); ++ } else { ++ oneValid = true; ++ firstMatch = i - oneOf_.begin; ++ } ++ } ++ if (!oneValid) { ++ context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf); + } +- if (!oneValid) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); +- } ++ } + +- if (not_ && context.validators[notValidatorIndex_]->IsValid()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString()); ++ if (not_ && context.validators[notValidatorIndex_]->IsValid()) { ++ context.error_handler.Disallowed(); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot); ++ } ++ } + + return true; + } + +- bool Null(Context& context) const { +- if (!(type_ & (1 << kNullSchemaType))) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); ++ bool Null(Context& context) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Null"); ++ if (!(type_ & (1 << kNullSchemaType))) { ++ DisallowedType(context, GetNullString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + return CreateParallelValidator(context); + } +- +- bool Bool(Context& context, bool) const { +- if (!(type_ & (1 << kBooleanSchemaType))) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); ++ ++ bool Bool(Context& context, bool b) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Bool", b); ++ if (!CheckBool(context, b)) ++ return false; + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int", (int64_t)i); + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint", (uint64_t)u); + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int64", i); + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint64", u); + 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()); ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Double", d); ++ if (!(type_ & (1 << kNumberSchemaType))) { ++ DisallowedType(context, GetNumberString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + + 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()); ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::String", str); ++ if (!(type_ & (1 << kStringSchemaType))) { ++ DisallowedType(context, GetStringString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint(str, length, &count)) { +- if (count < minLength_) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString()); +- if (count > maxLength_) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString()); ++ if (count < minLength_) { ++ context.error_handler.TooShort(str, length, minLength_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinLength); ++ } ++ if (count > maxLength_) { ++ context.error_handler.TooLong(str, length, maxLength_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxLength); ++ } + } + } + +- if (pattern_ && !IsPatternMatch(pattern_, str, length)) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString()); ++ if (pattern_ && !IsPatternMatch(pattern_, str, length)) { ++ context.error_handler.DoesNotMatch(str, length); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPattern); ++ } + + return CreateParallelValidator(context); + } + +- bool StartObject(Context& context) const { +- if (!(type_ & (1 << kObjectSchemaType))) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); ++ bool StartObject(Context& context) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartObject"); ++ if (!(type_ & (1 << kObjectSchemaType))) { ++ DisallowedType(context, GetObjectString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); +@@ -779,20 +1104,24 @@ public: + + return CreateParallelValidator(context); + } +- ++ + bool Key(Context& context, const Ch* str, SizeType len, bool) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Key", str); ++ + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) +- if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) ++ if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; ++ context.valueSchema = typeless_; ++ } + } + +- SizeType index; ++ SizeType index = 0; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; +- context.valueSchema = GetTypeless(); ++ context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else +@@ -805,9 +1134,9 @@ public: + } + + if (additionalPropertiesSchema_) { +- if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { ++ if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; +- context.valueSchema = GetTypeless(); ++ context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else +@@ -815,73 +1144,144 @@ public: + return true; + } + else if (additionalProperties_) { +- context.valueSchema = GetTypeless(); ++ context.valueSchema = typeless_; + return true; + } + +- if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString()); ++ if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties ++ // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error ++ context.valueSchema = typeless_; ++ context.error_handler.DisallowedProperty(str, len); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalProperties); ++ } + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { +- if (hasRequired_) ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndObject"); ++ if (hasRequired_) { ++ context.error_handler.StartMissingProperties(); + for (SizeType index = 0; index < propertyCount_; index++) +- if (properties_[index].required) +- if (!context.propertyExist[index]) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); ++ if (properties_[index].required && !context.propertyExist[index]) ++ if (properties_[index].schema->defaultValueLength_ == 0 ) ++ context.error_handler.AddMissingProperty(properties_[index].name); ++ if (context.error_handler.EndMissingProperties()) ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired); ++ } + +- if (memberCount < minProperties_) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString()); ++ if (memberCount < minProperties_) { ++ context.error_handler.TooFewProperties(memberCount, minProperties_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinProperties); ++ } + +- if (memberCount > maxProperties_) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString()); ++ if (memberCount > maxProperties_) { ++ context.error_handler.TooManyProperties(memberCount, maxProperties_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxProperties); ++ } + + if (hasDependencies_) { +- for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) ++ context.error_handler.StartDependencyErrors(); ++ for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) { ++ const Property& source = properties_[sourceIndex]; + if (context.propertyExist[sourceIndex]) { +- if (properties_[sourceIndex].dependencies) { ++ if (source.dependencies) { ++ context.error_handler.StartMissingDependentProperties(); + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) +- if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex]) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); ++ if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex]) ++ context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name); ++ context.error_handler.EndMissingDependentProperties(source.name); ++ } ++ else if (source.dependenciesSchema) { ++ ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex]; ++ if (!dependenciesValidator->IsValid()) ++ context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator); + } +- else if (properties_[sourceIndex].dependenciesSchema) +- if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } ++ } ++ if (context.error_handler.EndDependencyErrors()) ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies); + } + + return true; + } + +- bool StartArray(Context& context) const { +- if (!(type_ & (1 << kArraySchemaType))) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); +- ++ bool StartArray(Context& context) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartArray"); + context.arrayElementIndex = 0; +- context.inArray = true; ++ context.inArray = true; // Ensure we note that we are in an array ++ ++ if (!(type_ & (1 << kArraySchemaType))) { ++ DisallowedType(context, GetArrayString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + + return CreateParallelValidator(context); + } + +- bool EndArray(Context& context, SizeType elementCount) const { ++ bool EndArray(Context& context, SizeType elementCount) const { ++ RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndArray"); + context.inArray = false; +- +- if (elementCount < minItems_) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString()); +- +- if (elementCount > maxItems_) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString()); ++ ++ if (elementCount < minItems_) { ++ context.error_handler.TooFewItems(elementCount, minItems_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinItems); ++ } ++ ++ if (elementCount > maxItems_) { ++ context.error_handler.TooManyItems(elementCount, maxItems_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxItems); ++ } + + return true; + } + ++ static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) { ++ switch (validateErrorCode) { ++ case kValidateErrorMultipleOf: return GetMultipleOfString(); ++ case kValidateErrorMaximum: return GetMaximumString(); ++ case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same ++ case kValidateErrorMinimum: return GetMinimumString(); ++ case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same ++ ++ case kValidateErrorMaxLength: return GetMaxLengthString(); ++ case kValidateErrorMinLength: return GetMinLengthString(); ++ case kValidateErrorPattern: return GetPatternString(); ++ ++ case kValidateErrorMaxItems: return GetMaxItemsString(); ++ case kValidateErrorMinItems: return GetMinItemsString(); ++ case kValidateErrorUniqueItems: return GetUniqueItemsString(); ++ case kValidateErrorAdditionalItems: return GetAdditionalItemsString(); ++ ++ case kValidateErrorMaxProperties: return GetMaxPropertiesString(); ++ case kValidateErrorMinProperties: return GetMinPropertiesString(); ++ case kValidateErrorRequired: return GetRequiredString(); ++ case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString(); ++ case kValidateErrorPatternProperties: return GetPatternPropertiesString(); ++ case kValidateErrorDependencies: return GetDependenciesString(); ++ ++ case kValidateErrorEnum: return GetEnumString(); ++ case kValidateErrorType: return GetTypeString(); ++ ++ case kValidateErrorOneOf: return GetOneOfString(); ++ case kValidateErrorOneOfMatch: return GetOneOfString(); // Same ++ case kValidateErrorAllOf: return GetAllOfString(); ++ case kValidateErrorAnyOf: return GetAnyOfString(); ++ case kValidateErrorNot: return GetNotString(); ++ ++ case kValidateErrorReadOnly: return GetReadOnlyString(); ++ case kValidateErrorWriteOnly: return GetWriteOnlyString(); ++ ++ default: return GetNullString(); ++ } ++ } ++ ++ + // 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);\ ++ static const ValueType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1));\ + return v;\ + } + +@@ -918,6 +1318,15 @@ public: + 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') ++ RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't') ++ RAPIDJSON_STRING_(Schema, '$', 's', 'c', 'h', 'e', 'm', 'a') ++ RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f') ++ RAPIDJSON_STRING_(Id, 'i', 'd') ++ RAPIDJSON_STRING_(Swagger, 's', 'w', 'a', 'g', 'g', 'e', 'r') ++ RAPIDJSON_STRING_(OpenApi, 'o', 'p', 'e', 'n', 'a', 'p', 'i') ++ RAPIDJSON_STRING_(ReadOnly, 'r', 'e', 'a', 'd', 'O', 'n', 'l', 'y') ++ RAPIDJSON_STRING_(WriteOnly, 'w', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') ++ RAPIDJSON_STRING_(Nullable, 'n', 'u', 'l', 'l', 'a', 'b', 'l', 'e') + + #undef RAPIDJSON_STRING_ + +@@ -934,7 +1343,7 @@ private: + }; + + #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +- typedef internal::GenericRegex RegexType; ++ typedef internal::GenericRegex RegexType; + #elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex RegexType; + #else +@@ -949,11 +1358,6 @@ private: + SizeType count; + }; + +- static const SchemaType* GetTypeless() { +- static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); +- return &typeless; +- } +- + template + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) +@@ -988,7 +1392,7 @@ private: + out.schemas = static_cast(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); ++ schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_); + out.begin = validatorCount_; + validatorCount_ += out.count; + } +@@ -997,10 +1401,11 @@ private: + + #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template +- RegexType* CreatePattern(const ValueType& value) { ++ RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { + if (value.IsString()) { +- RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString()); ++ RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_); + if (!r->IsValid()) { ++ sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); + r->~RegexType(); + AllocatorType::Free(r); + r = 0; +@@ -1011,17 +1416,22 @@ private: + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { +- return pattern->Search(str); ++ GenericRegexSearch rs(*pattern); ++ return rs.Search(str); + } + #elif RAPIDJSON_SCHEMA_USE_STDREGEX + template +- RegexType* CreatePattern(const ValueType& value) { +- if (value.IsString()) ++ RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { ++ if (value.IsString()) { ++ RegexType *r = static_cast(allocator_->Malloc(sizeof(RegexType))); + try { +- return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); ++ return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } +- catch (const std::regex_error&) { ++ catch (const std::regex_error& e) { ++ sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); ++ AllocatorType::Free(r); + } ++ } + return 0; + } + +@@ -1031,7 +1441,9 @@ private: + } + #else + template +- RegexType* CreatePattern(const ValueType&) { return 0; } ++ RegexType* CreatePattern(const ValueType&) { ++ return 0; ++ } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } + #endif // RAPIDJSON_SCHEMA_USE_STDREGEX +@@ -1046,6 +1458,9 @@ private: + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + ++ // Creates parallel validators for allOf, anyOf, oneOf, not and schema dependencies, if required. ++ // Also creates a hasher for enums and array uniqueness, if required. ++ // Also a useful place to add type-independent error checks. + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); +@@ -1053,33 +1468,45 @@ private: + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); ++ std::memset(context.validators, 0, sizeof(ISchemaValidator*) * validatorCount_); + context.validatorCount = validatorCount_; + ++ // Always return after first failure for these sub-validators + if (allOf_.schemas) +- CreateSchemaValidators(context, allOf_); ++ CreateSchemaValidators(context, allOf_, false); + + if (anyOf_.schemas) +- CreateSchemaValidators(context, anyOf_); +- ++ CreateSchemaValidators(context, anyOf_, false); ++ + if (oneOf_.schemas) +- CreateSchemaValidators(context, oneOf_); +- ++ CreateSchemaValidators(context, oneOf_, false); ++ + if (not_) +- context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); +- ++ context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false); ++ + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) +- context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema); ++ context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema, false); + } + } + ++ // Add any other type-independent checks here ++ if (readOnly_ && (context.flags & kValidateWriteFlag)) { ++ context.error_handler.DisallowedWhenWriting(); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorReadOnly); ++ } ++ if (writeOnly_ && (context.flags & kValidateReadFlag)) { ++ context.error_handler.DisallowedWhenReading(); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorWriteOnly); ++ } ++ + return true; + } + +- void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const { ++ void CreateSchemaValidators(Context& context, const SchemaArray& schemas, const bool inheritContinueOnErrors) const { + for (SizeType i = 0; i < schemas.count; i++) +- context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); ++ context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors); + } + + // O(n) +@@ -1087,7 +1514,7 @@ private: + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) +- if (properties_[index].name.GetStringLength() == len && ++ if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; +@@ -1096,17 +1523,30 @@ private: + return false; + } + ++ bool CheckBool(Context& context, bool) const { ++ if (!(type_ & (1 << kBooleanSchemaType))) { ++ DisallowedType(context, GetBooleanString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } ++ return true; ++ } ++ + bool CheckInt(Context& context, int64_t i) const { +- if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); ++ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { ++ DisallowedType(context, GetIntegerString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { +- if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); ++ if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) { ++ context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); ++ } + } + else if (minimum_.IsUint64()) { +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64() ++ context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; +@@ -1114,19 +1554,23 @@ private: + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { +- if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); ++ if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) { ++ context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); ++ } + } +- else if (maximum_.IsUint64()) +- /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64() ++ else if (maximum_.IsUint64()) { } ++ /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { +- if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); ++ if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) { ++ context.error_handler.NotMultipleOf(i, multipleOf_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); ++ } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; +@@ -1136,13 +1580,17 @@ private: + } + + bool CheckUint(Context& context, uint64_t i) const { +- if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); ++ if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { ++ DisallowedType(context, GetIntegerString()); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); ++ } + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { +- if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); ++ if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) { ++ context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); ++ } + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() +@@ -1152,19 +1600,25 @@ private: + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { +- if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); ++ if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) { ++ context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); ++ } ++ } ++ else if (maximum_.IsInt64()) { ++ context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); // i >= 0 > maximum_ + } +- else if (maximum_.IsInt64()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_ + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { +- if (i % multipleOf_.GetUint64() != 0) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); ++ if (i % multipleOf_.GetUint64() != 0) { ++ context.error_handler.NotMultipleOf(i, multipleOf_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); ++ } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; +@@ -1174,14 +1628,18 @@ private: + } + + bool CheckDoubleMinimum(Context& context, double d) const { +- if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); ++ if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) { ++ context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); ++ } + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { +- if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) +- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); ++ if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) { ++ context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); ++ } + return true; + } + +@@ -1189,11 +1647,29 @@ private: + 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()); ++ if (r > 0.0) { ++ context.error_handler.NotMultipleOf(d, multipleOf_); ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); ++ } + return true; + } + ++ void DisallowedType(Context& context, const ValueType& actualType) const { ++ ErrorHandler& eh = context.error_handler; ++ eh.StartDisallowedType(); ++ ++ if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString()); ++ if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString()); ++ if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString()); ++ if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString()); ++ if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString()); ++ ++ if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString()); ++ else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString()); ++ ++ eh.EndDisallowedType(actualType); ++ } ++ + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } +@@ -1207,7 +1683,7 @@ private: + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} +- ~PatternProperty() { ++ ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); +@@ -1218,6 +1694,11 @@ private: + }; + + AllocatorType* allocator_; ++ SValue uri_; ++ UriType id_; ++ Specification spec_; ++ PointerType pointer_; ++ const SchemaType* typeless_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; +@@ -1258,6 +1739,12 @@ private: + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; ++ ++ SizeType defaultValueLength_; ++ ++ bool readOnly_; ++ bool writeOnly_; ++ bool nullable_; + }; + + template +@@ -1267,7 +1754,7 @@ struct TokenHelper { + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) +- *documentStack.template Push() = buffer[i]; ++ *documentStack.template Push() = static_cast(buffer[i]); + } + }; + +@@ -1299,9 +1786,18 @@ template + class IGenericRemoteSchemaDocumentProvider { + public: + typedef typename SchemaDocumentType::Ch Ch; ++ typedef typename SchemaDocumentType::ValueType ValueType; ++ typedef typename SchemaDocumentType::AllocatorType AllocatorType; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; ++ virtual const SchemaDocumentType* GetRemoteDocument(const GenericUri uri, Specification& spec) { ++ // Default implementation just calls through for compatibility ++ // Following line suppresses unused parameter warning ++ (void)spec; ++ // printf("GetRemoteDocument: %d %d\n", spec.draft, spec.oapi); ++ return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength()); ++ } + }; + + /////////////////////////////////////////////////////////////////////////////// +@@ -1326,6 +1822,9 @@ public: + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; ++ typedef GenericValue GValue; ++ typedef GenericUri UriType; ++ typedef GenericStringRef StringRefType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; +@@ -1335,37 +1834,57 @@ public: + Compile a JSON document into schema document. + + \param document A JSON document as source. ++ \param uri The base URI of this schema document for purposes of violation reporting. ++ \param uriLength Length of \c name, in code points. + \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. ++ \param pointer An optional JSON pointer to the start of the schema document ++ \param spec Optional schema draft or OpenAPI version. Used if no specification in document. Defaults to draft-04. + */ +- explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : ++ explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, ++ IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0, ++ const PointerType& pointer = PointerType(), // PR #1393 ++ const Specification& spec = Specification(kDraft04)) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), ++ typeless_(), + schemaMap_(allocator, kInitialSchemaMapSize), +- schemaRef_(allocator, kInitialSchemaRefSize) ++ schemaRef_(allocator, kInitialSchemaRefSize), ++ spec_(spec), ++ error_(kObjectType), ++ currentError_() + { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::GenericSchemaDocument"); + if (!allocator_) +- ownAllocator_ = allocator_ = RAPIDJSON_NEW(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); ++ Ch noUri[1] = {0}; ++ uri_.SetString(uri ? uri : noUri, uriLength, *allocator_); ++ docId_ = UriType(uri_, allocator_); + +- // Resolve $ref +- while (!schemaRef_.Empty()) { +- SchemaRefEntry* refEntry = schemaRef_.template Pop(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(refEntry->source, const_cast(s), false, allocator_); +- } +- } +- refEntry->~SchemaRefEntry(); ++ typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); ++ new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_); ++ ++ // Establish the schema draft or open api version. ++ // We only ever look for '$schema' or 'swagger' or 'openapi' at the root of the document. ++ SetSchemaSpecification(document); ++ ++ // Generate root schema, it will call CreateSchema() to create sub-schemas, ++ // And call HandleRefSchema() if there are $ref. ++ // PR #1393 use input pointer if supplied ++ root_ = typeless_; ++ if (pointer.GetTokenCount() == 0) { ++ CreateSchemaRecursive(&root_, pointer, document, document, docId_); ++ } ++ else if (const ValueType* v = pointer.Get(document)) { ++ CreateSchema(&root_, pointer, *v, document, docId_); ++ } ++ else { ++ GenericStringBuffer sb; ++ pointer.StringifyUriFragment(sb); ++ SchemaErrorValue(kSchemaErrorStartUnknown, PointerType(), sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch))); + } + + RAPIDJSON_ASSERT(root_ != 0); +@@ -1380,12 +1899,19 @@ public: + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), ++ typeless_(rhs.typeless_), + schemaMap_(std::move(rhs.schemaMap_)), +- schemaRef_(std::move(rhs.schemaRef_)) ++ schemaRef_(std::move(rhs.schemaRef_)), ++ uri_(std::move(rhs.uri_)), ++ docId_(std::move(rhs.docId_)), ++ spec_(rhs.spec_), ++ error_(std::move(rhs.error_)), ++ currentError_(std::move(rhs.currentError_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; ++ rhs.typeless_ = 0; + } + #endif + +@@ -1394,24 +1920,92 @@ public: + while (!schemaMap_.Empty()) + schemaMap_.template Pop(1)->~SchemaEntry(); + ++ if (typeless_) { ++ typeless_->~SchemaType(); ++ Allocator::Free(typeless_); ++ } ++ ++ // these may contain some allocator data so clear before deleting ownAllocator_ ++ uri_.SetNull(); ++ error_.SetNull(); ++ currentError_.SetNull(); ++ + RAPIDJSON_DELETE(ownAllocator_); + } + ++ const GValue& GetURI() const { return uri_; } ++ ++ const Specification& GetSpecification() const { return spec_; } ++ bool IsSupportedSpecification() const { return spec_.IsSupported(); } ++ ++ //! Static method to get the specification of any schema document ++ // Returns kDraftNone if document is silent ++ static const Specification GetSpecification(const ValueType& document) { ++ SchemaDraft draft = GetSchemaDraft(document); ++ if (draft != kDraftNone) ++ return Specification(draft); ++ else { ++ OpenApiVersion oapi = GetOpenApiVersion(document); ++ if (oapi != kVersionNone) ++ return Specification(oapi); ++ } ++ return Specification(kDraftNone); ++ } ++ + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + +-private: ++ //! Gets the error object. ++ GValue& GetError() { return error_; } ++ const GValue& GetError() const { return error_; } ++ ++ static const StringRefType& GetSchemaErrorKeyword(SchemaErrorCode schemaErrorCode) { ++ switch (schemaErrorCode) { ++ case kSchemaErrorStartUnknown: return GetStartUnknownString(); ++ case kSchemaErrorRefPlainName: return GetRefPlainNameString(); ++ case kSchemaErrorRefInvalid: return GetRefInvalidString(); ++ case kSchemaErrorRefPointerInvalid: return GetRefPointerInvalidString(); ++ case kSchemaErrorRefUnknown: return GetRefUnknownString(); ++ case kSchemaErrorRefCyclical: return GetRefCyclicalString(); ++ case kSchemaErrorRefNoRemoteProvider: return GetRefNoRemoteProviderString(); ++ case kSchemaErrorRefNoRemoteSchema: return GetRefNoRemoteSchemaString(); ++ case kSchemaErrorRegexInvalid: return GetRegexInvalidString(); ++ case kSchemaErrorSpecUnknown: return GetSpecUnknownString(); ++ case kSchemaErrorSpecUnsupported: return GetSpecUnsupportedString(); ++ case kSchemaErrorSpecIllegal: return GetSpecIllegalString(); ++ case kSchemaErrorReadOnlyAndWriteOnly: return GetReadOnlyAndWriteOnlyString(); ++ default: return GetNullString(); ++ } ++ } ++ ++ //! Default error method ++ void SchemaError(const SchemaErrorCode code, const PointerType& location) { ++ currentError_ = GValue(kObjectType); ++ AddCurrentError(code, location); ++ } ++ ++ //! Method for error with single string value insert ++ void SchemaErrorValue(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length) { ++ currentError_ = GValue(kObjectType); ++ currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); ++ AddCurrentError(code, location); ++ } ++ ++ //! Method for error with invalid pointer ++ void SchemaErrorPointer(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length, const PointerType& pointer) { ++ currentError_ = GValue(kObjectType); ++ currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); ++ currentError_.AddMember(GetOffsetString(), static_cast(pointer.GetParseErrorOffset() / sizeof(Ch)), *allocator_); ++ AddCurrentError(code, location); ++ } ++ ++ 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; +- }; ++ typedef const PointerType* SchemaRefPtr; // PR #1393 + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} +@@ -1426,78 +2020,361 @@ private: + bool owned; + }; + +- void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { +- if (schema) +- *schema = SchemaType::GetTypeless(); ++ void AddErrorInstanceLocation(GValue& result, const PointerType& location) { ++ GenericStringBuffer sb; ++ location.StringifyUriFragment(sb); ++ GValue instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), *allocator_); ++ result.AddMember(GetInstanceRefString(), instanceRef, *allocator_); ++ } ++ ++ void AddError(GValue& keyword, GValue& error) { ++ typename GValue::MemberIterator member = error_.FindMember(keyword); ++ if (member == error_.MemberEnd()) ++ error_.AddMember(keyword, error, *allocator_); ++ else { ++ if (member->value.IsObject()) { ++ GValue errors(kArrayType); ++ errors.PushBack(member->value, *allocator_); ++ member->value = errors; ++ } ++ member->value.PushBack(error, *allocator_); ++ } ++ } ++ ++ void AddCurrentError(const SchemaErrorCode code, const PointerType& location) { ++ RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, GetSchemaErrorKeyword(code)); ++ currentError_.AddMember(GetErrorCodeString(), code, *allocator_); ++ AddErrorInstanceLocation(currentError_, location); ++ AddError(GValue(GetSchemaErrorKeyword(code)).Move(), currentError_); ++ } ++ ++#define RAPIDJSON_STRING_(name, ...) \ ++ static const StringRefType& Get##name##String() {\ ++ static const Ch s[] = { __VA_ARGS__, '\0' };\ ++ static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ ++ return v;\ ++ } ++ ++ RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') ++ RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') ++ RAPIDJSON_STRING_(Value, 'v', 'a', 'l', 'u', 'e') ++ RAPIDJSON_STRING_(Offset, 'o', 'f', 'f', 's', 'e', 't') ++ ++ RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') ++ RAPIDJSON_STRING_(SpecUnknown, 'S', 'p', 'e', 'c', 'U', 'n', 'k', 'n', 'o', 'w', 'n') ++ RAPIDJSON_STRING_(SpecUnsupported, 'S', 'p', 'e', 'c', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd') ++ RAPIDJSON_STRING_(SpecIllegal, 'S', 'p', 'e', 'c', 'I', 'l', 'l', 'e', 'g', 'a', 'l') ++ RAPIDJSON_STRING_(StartUnknown, 'S', 't', 'a', 'r', 't', 'U', 'n', 'k', 'n', 'o', 'w', 'n') ++ RAPIDJSON_STRING_(RefPlainName, 'R', 'e', 'f', 'P', 'l', 'a', 'i', 'n', 'N', 'a', 'm', 'e') ++ RAPIDJSON_STRING_(RefInvalid, 'R', 'e', 'f', 'I', 'n', 'v', 'a', 'l', 'i', 'd') ++ RAPIDJSON_STRING_(RefPointerInvalid, 'R', 'e', 'f', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'I', 'n', 'v', 'a', 'l', 'i', 'd') ++ RAPIDJSON_STRING_(RefUnknown, 'R', 'e', 'f', 'U', 'n', 'k', 'n', 'o', 'w', 'n') ++ RAPIDJSON_STRING_(RefCyclical, 'R', 'e', 'f', 'C', 'y', 'c', 'l', 'i', 'c', 'a', 'l') ++ RAPIDJSON_STRING_(RefNoRemoteProvider, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r') ++ RAPIDJSON_STRING_(RefNoRemoteSchema, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'S', 'c', 'h', 'e', 'm', 'a') ++ RAPIDJSON_STRING_(ReadOnlyAndWriteOnly, 'R', 'e', 'a', 'd', 'O', 'n', 'l', 'y', 'A', 'n', 'd', 'W', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') ++ RAPIDJSON_STRING_(RegexInvalid, 'R', 'e', 'g', 'e', 'x', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + ++#undef RAPIDJSON_STRING_ ++ ++ // Static method to get schema draft of any schema document ++ static SchemaDraft GetSchemaDraft(const ValueType& document) { ++ static const Ch kDraft03String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '3', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; ++ static const Ch kDraft04String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '4', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; ++ static const Ch kDraft05String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '5', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; ++ static const Ch kDraft06String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '6', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; ++ static const Ch kDraft07String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '7', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; ++ static const Ch kDraft2019_09String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '1', '9', '-', '0', '9', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; ++ static const Ch kDraft2020_12String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '2', '0', '-', '1', '2', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; ++ ++ if (!document.IsObject()) { ++ return kDraftNone; ++ } ++ ++ // Get the schema draft from the $schema keyword at the supplied location ++ typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSchemaString()); ++ if (itr != document.MemberEnd()) { ++ if (!itr->value.IsString()) return kDraftUnknown; ++ const UriType draftUri(itr->value); ++ // Check base uri for match ++ if (draftUri.Match(UriType(kDraft04String), false)) return kDraft04; ++ if (draftUri.Match(UriType(kDraft05String), false)) return kDraft05; ++ if (draftUri.Match(UriType(kDraft06String), false)) return kDraft06; ++ if (draftUri.Match(UriType(kDraft07String), false)) return kDraft07; ++ if (draftUri.Match(UriType(kDraft03String), false)) return kDraft03; ++ if (draftUri.Match(UriType(kDraft2019_09String), false)) return kDraft2019_09; ++ if (draftUri.Match(UriType(kDraft2020_12String), false)) return kDraft2020_12; ++ return kDraftUnknown; ++ } ++ // $schema not found ++ return kDraftNone; ++ } ++ ++ ++ // Get open api version of any schema document ++ static OpenApiVersion GetOpenApiVersion(const ValueType& document) { ++ static const Ch kVersion20String[] = { '2', '.', '0', '\0' }; ++ static const Ch kVersion30String[] = { '3', '.', '0', '.', '\0' }; // ignore patch level ++ static const Ch kVersion31String[] = { '3', '.', '1', '.', '\0' }; // ignore patch level ++ static SizeType len = internal::StrLen(kVersion30String); ++ ++ if (!document.IsObject()) { ++ return kVersionNone; ++ } ++ ++ // Get the open api version from the swagger / openapi keyword at the supplied location ++ typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSwaggerString()); ++ if (itr == document.MemberEnd()) itr = document.FindMember(SchemaType::GetOpenApiString()); ++ if (itr != document.MemberEnd()) { ++ if (!itr->value.IsString()) return kVersionUnknown; ++ const ValueType kVersion20Value(kVersion20String); ++ if (kVersion20Value == itr->value) return kVersion20; // must match 2.0 exactly ++ const ValueType kVersion30Value(kVersion30String); ++ if (itr->value.GetStringLength() > len && kVersion30Value == ValueType(itr->value.GetString(), len)) return kVersion30; // must match 3.0.x ++ const ValueType kVersion31Value(kVersion31String); ++ if (itr->value.GetStringLength() > len && kVersion31Value == ValueType(itr->value.GetString(), len)) return kVersion31; // must match 3.1.x ++ return kVersionUnknown; ++ } ++ // swagger or openapi not found ++ return kVersionNone; ++ } ++ ++ // Get the draft of the schema or the open api version (which implies the draft). ++ // Report an error if schema draft or open api version not supported or not recognized, or both in document, and carry on. ++ void SetSchemaSpecification(const ValueType& document) { ++ // Look for '$schema', 'swagger' or 'openapi' keyword at document root ++ SchemaDraft docDraft = GetSchemaDraft(document); ++ OpenApiVersion docOapi = GetOpenApiVersion(document); ++ // Error if both in document ++ if (docDraft != kDraftNone && docOapi != kVersionNone) ++ SchemaError(kSchemaErrorSpecIllegal, PointerType()); ++ // Use document draft or open api version if present or use spec from constructor ++ if (docDraft != kDraftNone) ++ spec_ = Specification(docDraft); ++ else if (docOapi != kVersionNone) ++ spec_ = Specification(docOapi); ++ // Error if draft or version unknown ++ if (spec_.draft == kDraftUnknown || spec_.oapi == kVersionUnknown) ++ SchemaError(kSchemaErrorSpecUnknown, PointerType()); ++ else if (!spec_.IsSupported()) ++ SchemaError(kSchemaErrorSpecUnsupported, PointerType()); ++ } ++ ++ // Changed by PR #1393 ++ void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { + if (v.GetType() == kObjectType) { +- const SchemaType* s = GetSchema(pointer); +- if (!s) +- CreateSchema(schema, pointer, v, document); ++ UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) +- CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); ++ CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) +- CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); ++ CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id); + } + +- void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { ++ // Changed by PR #1393 ++ const UriType& CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { + RAPIDJSON_ASSERT(pointer.IsValid()); ++ GenericStringBuffer sb; ++ pointer.StringifyUriFragment(sb); ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::CreateSchema", sb.GetString(), id.GetString()); + 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(pointer, s, true, allocator_); ++ if (const SchemaType* sc = GetSchema(pointer)) { ++ if (schema) ++ *schema = sc; ++ AddSchemaRefs(const_cast(sc)); ++ } ++ else if (!HandleRefSchema(pointer, schema, v, document, id)) { ++ // The new schema constructor adds itself and its $ref(s) to schemaMap_ ++ SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_, id); + if (schema) + *schema = s; ++ return s->GetId(); + } + } ++ else { ++ if (schema) ++ *schema = typeless_; ++ AddSchemaRefs(typeless_); ++ } ++ return id; + } + +- 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); ++ // Changed by PR #1393 ++ // TODO should this return a UriType& ? ++ bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document, const UriType& id) { ++ typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString()); + if (itr == v.MemberEnd()) + return false; + ++ GenericStringBuffer sb; ++ source.StringifyUriFragment(sb); ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::HandleRefSchema", sb.GetString(), id.GetString()); ++ // Resolve the source pointer to the $ref'ed schema (finally) ++ new (schemaRef_.template Push()) SchemaRefPtr(&source); ++ + 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)) { +- PointerType pointer(&s[i], len - i, allocator_); +- if (pointer.IsValid()) { +- if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { +- if (schema) +- *schema = sc; ++ if (len == 0) ++ SchemaError(kSchemaErrorRefInvalid, source); ++ else { ++ // First resolve $ref against the in-scope id ++ UriType scopeId = UriType(id, allocator_); ++ UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_); ++ RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), itr->value.GetString(), ref.GetString()); ++ // See if the resolved $ref minus the fragment matches a resolved id in this document ++ // Search from the root. Returns the subschema in the document and its absolute JSON pointer. ++ PointerType basePointer = PointerType(); ++ const ValueType *base = FindId(document, ref, basePointer, docId_, false); ++ if (!base) { ++ // Remote reference - call the remote document provider ++ if (!remoteProvider_) ++ SchemaError(kSchemaErrorRefNoRemoteProvider, source); ++ else { ++ if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref, spec_)) { ++ const Ch* s = ref.GetFragString(); ++ len = ref.GetFragStringLength(); ++ if (len <= 1 || s[1] == '/') { ++ // JSON pointer fragment, absolute in the remote schema ++ const PointerType pointer(s, len, allocator_); ++ if (!pointer.IsValid()) ++ SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, pointer); ++ else { ++ // Get the subschema ++ if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) { ++ if (schema) ++ *schema = sc; ++ AddSchemaRefs(const_cast(sc)); ++ return true; ++ } else ++ SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); ++ } ++ } else ++ // Plain name fragment, not allowed in remote schema ++ SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); ++ } else ++ SchemaErrorValue(kSchemaErrorRefNoRemoteSchema, source, ref.GetString(), ref.GetStringLength()); ++ } ++ } ++ else { // Local reference ++ const Ch* s = ref.GetFragString(); ++ len = ref.GetFragStringLength(); ++ if (len <= 1 || s[1] == '/') { ++ // JSON pointer fragment, relative to the resolved URI ++ const PointerType relPointer(s, len, allocator_); ++ if (!relPointer.IsValid()) ++ SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, relPointer); ++ else { ++ // Get the subschema ++ if (const ValueType *pv = relPointer.Get(*base)) { ++ // Now get the absolute JSON pointer by adding relative to base ++ PointerType pointer(basePointer, allocator_); ++ for (SizeType i = 0; i < relPointer.GetTokenCount(); i++) ++ pointer = pointer.Append(relPointer.GetTokens()[i], allocator_); ++ if (IsCyclicRef(pointer)) ++ SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); ++ else { ++ // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there ++ // TODO: cache pointer <-> id mapping ++ size_t unresolvedTokenIndex; ++ scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); ++ CreateSchema(schema, pointer, *pv, document, scopeId); + return true; + } +- } ++ } else ++ SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } ++ } else { ++ // Plain name fragment, relative to the resolved URI ++ // Not supported in open api 2.0 and 3.0 ++ PointerType pointer(allocator_); ++ if (spec_.oapi == kVersion20 || spec_.oapi == kVersion30) ++ SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); ++ // See if the fragment matches an id in this document. ++ // Search from the base we just established. Returns the subschema in the document and its absolute JSON pointer. ++ else if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) { ++ if (IsCyclicRef(pointer)) ++ SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); ++ else { ++ // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there ++ // TODO: cache pointer <-> id mapping ++ size_t unresolvedTokenIndex; ++ scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); ++ CreateSchema(schema, pointer, *pv, document, scopeId); ++ return true; ++ } ++ } else ++ SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } +- 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(source, pointer, schema, allocator_); +- return true; +- } ++ // Invalid/Unknown $ref ++ if (schema) ++ *schema = typeless_; ++ AddSchemaRefs(typeless_); ++ return true; ++ } ++ ++ //! Find the first subschema with a resolved 'id' that matches the specified URI. ++ // If full specified use all URI else ignore fragment. ++ // If found, return a pointer to the subschema and its JSON pointer. ++ // TODO cache pointer <-> id mapping ++ ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const { ++ SizeType i = 0; ++ ValueType* resval = 0; ++ UriType tempuri = UriType(finduri, allocator_); ++ UriType localuri = UriType(baseuri, allocator_); ++ if (doc.GetType() == kObjectType) { ++ // Establish the base URI of this object ++ typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString()); ++ if (m != doc.MemberEnd() && m->value.GetType() == kStringType) { ++ localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_); ++ } ++ // See if it matches ++ if (localuri.Match(finduri, full)) { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::FindId (match)", full ? localuri.GetString() : localuri.GetBaseString()); ++ resval = const_cast(&doc); ++ resptr = here; ++ return resval; ++ } ++ // No match, continue looking ++ for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) { ++ if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) { ++ resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_)); ++ } ++ if (resval) break; ++ } ++ } else if (doc.GetType() == kArrayType) { ++ // Continue looking ++ for (typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) { ++ if (v->GetType() == kObjectType || v->GetType() == kArrayType) { ++ resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_)); + } ++ if (resval) break; ++ i++; + } + } ++ return resval; ++ } ++ ++ // Added by PR #1393 ++ void AddSchemaRefs(SchemaType* schema) { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::AddSchemaRefs"); ++ while (!schemaRef_.Empty()) { ++ SchemaRefPtr *ref = schemaRef_.template Pop(1); ++ SchemaEntry *entry = schemaMap_.template Push(); ++ new (entry) SchemaEntry(**ref, schema, false, allocator_); ++ } ++ } ++ ++ // Added by PR #1393 ++ bool IsCyclicRef(const PointerType& pointer) const { ++ for (const SchemaRefPtr* ref = schemaRef_.template Bottom(); ref != schemaRef_.template End(); ++ref) ++ if (pointer == **ref) ++ return true; + return false; + } + +@@ -1515,6 +2392,8 @@ private: + return PointerType(); + } + ++ const SchemaType* GetTypeless() const { return typeless_; } ++ + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + +@@ -1522,8 +2401,14 @@ private: + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. ++ SchemaType* typeless_; + internal::Stack schemaMap_; // Stores created Pointer -> Schemas +- internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref ++ internal::Stack schemaRef_; // Stores Pointer(s) from $ref(s) until resolved ++ GValue uri_; // Schema document URI ++ UriType docId_; ++ Specification spec_; ++ GValue error_; ++ GValue currentError_; + }; + + //! GenericSchemaDocument using Value type. +@@ -1552,13 +2437,16 @@ template < + typename StateAllocator = CrtAllocator> + class GenericSchemaValidator : + public internal::ISchemaStateFactory, +- public internal::ISchemaValidator +-{ ++ public internal::ISchemaValidator, ++ public internal::IValidationErrorHandler { + public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; ++ typedef typename SchemaType::SValue SValue; + typedef typename EncodingType::Ch Ch; ++ typedef GenericStringRef StringRefType; ++ typedef GenericValue ValueType; + + //! Constructor without output handler. + /*! +@@ -1575,16 +2463,19 @@ public: + : + 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 ++ outputHandler_(0), ++ error_(kObjectType), ++ currentError_(), ++ missingDependents_(), ++ valid_(true), ++ flags_(kValidateDefaultFlags), ++ depth_(0) + { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator"); + } + + //! Constructor with output handler. +@@ -1603,16 +2494,19 @@ public: + : + 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 ++ outputHandler_(&outputHandler), ++ error_(kObjectType), ++ currentError_(), ++ missingDependents_(), ++ valid_(true), ++ flags_(kValidateDefaultFlags), ++ depth_(0) + { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (output handler)"); + } + + //! Destructor. +@@ -1626,44 +2520,291 @@ public: + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); ++ ResetError(); ++ } ++ ++ //! Reset the error state. ++ void ResetError() { ++ error_.SetObject(); ++ currentError_.SetNull(); ++ missingDependents_.SetNull(); + valid_ = true; + } + +- //! Checks whether the current state is valid. +- // Implementation of ISchemaValidator +- virtual bool IsValid() const { return valid_; } ++ //! Implementation of ISchemaValidator ++ void SetValidateFlags(unsigned flags) { ++ flags_ = flags; ++ } ++ virtual unsigned GetValidateFlags() const { ++ return flags_; ++ } ++ ++ virtual bool IsValid() const { ++ if (!valid_) return false; ++ if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false; ++ return true; ++ } ++ //! End of Implementation of ISchemaValidator ++ ++ //! Gets the error object. ++ ValueType& GetError() { return error_; } ++ const ValueType& GetError() const { return error_; } + + //! Gets the JSON pointer pointed to the invalid schema. ++ // If reporting all errors, the stack will be empty. + PointerType GetInvalidSchemaPointer() const { +- return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); ++ return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer(); + } + + //! Gets the keyword of invalid schema. ++ // If reporting all errors, the stack will be empty, so return "errors". + const Ch* GetInvalidSchemaKeyword() const { +- return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword; ++ if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword; ++ if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString(); ++ return 0; ++ } ++ ++ //! Gets the error code of invalid schema. ++ // If reporting all errors, the stack will be empty, so return kValidateErrors. ++ ValidateErrorCode GetInvalidSchemaCode() const { ++ if (!schemaStack_.Empty()) return CurrentContext().invalidCode; ++ if (GetContinueOnErrors() && !error_.ObjectEmpty()) return kValidateErrors; ++ return kValidateErrorNone; + } + + //! Gets the JSON pointer pointed to the invalid value. ++ // If reporting all errors, the stack will be empty. + PointerType GetInvalidDocumentPointer() const { +- return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); ++ if (documentStack_.Empty()) { ++ return PointerType(); ++ } ++ else { ++ return PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); ++ } + } + +-#if RAPIDJSON_SCHEMA_VERBOSE +-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ +-RAPIDJSON_MULTILINEMACRO_BEGIN\ +- *documentStack_.template Push() = '\0';\ +- documentStack_.template Pop(1);\ +- internal::PrintInvalidDocument(documentStack_.template Bottom());\ +-RAPIDJSON_MULTILINEMACRO_END +-#else +-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() +-#endif ++ void NotMultipleOf(int64_t actual, const SValue& expected) { ++ AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); ++ } ++ void NotMultipleOf(uint64_t actual, const SValue& expected) { ++ AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); ++ } ++ void NotMultipleOf(double actual, const SValue& expected) { ++ AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); ++ } ++ void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) { ++ AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, ++ exclusive ? &SchemaType::GetExclusiveMaximumString : 0); ++ } ++ void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) { ++ AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, ++ exclusive ? &SchemaType::GetExclusiveMaximumString : 0); ++ } ++ void AboveMaximum(double actual, const SValue& expected, bool exclusive) { ++ AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, ++ exclusive ? &SchemaType::GetExclusiveMaximumString : 0); ++ } ++ void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) { ++ AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, ++ exclusive ? &SchemaType::GetExclusiveMinimumString : 0); ++ } ++ void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) { ++ AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, ++ exclusive ? &SchemaType::GetExclusiveMinimumString : 0); ++ } ++ void BelowMinimum(double actual, const SValue& expected, bool exclusive) { ++ AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, ++ exclusive ? &SchemaType::GetExclusiveMinimumString : 0); ++ } ++ ++ void TooLong(const Ch* str, SizeType length, SizeType expected) { ++ AddNumberError(kValidateErrorMaxLength, ++ ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); ++ } ++ void TooShort(const Ch* str, SizeType length, SizeType expected) { ++ AddNumberError(kValidateErrorMinLength, ++ ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); ++ } ++ void DoesNotMatch(const Ch* str, SizeType length) { ++ currentError_.SetObject(); ++ currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator()); ++ AddCurrentError(kValidateErrorPattern); ++ } ++ ++ void DisallowedItem(SizeType index) { ++ currentError_.SetObject(); ++ currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator()); ++ AddCurrentError(kValidateErrorAdditionalItems, true); ++ } ++ void TooFewItems(SizeType actualCount, SizeType expectedCount) { ++ AddNumberError(kValidateErrorMinItems, ++ ValueType(actualCount).Move(), SValue(expectedCount).Move()); ++ } ++ void TooManyItems(SizeType actualCount, SizeType expectedCount) { ++ AddNumberError(kValidateErrorMaxItems, ++ ValueType(actualCount).Move(), SValue(expectedCount).Move()); ++ } ++ void DuplicateItems(SizeType index1, SizeType index2) { ++ ValueType duplicates(kArrayType); ++ duplicates.PushBack(index1, GetStateAllocator()); ++ duplicates.PushBack(index2, GetStateAllocator()); ++ currentError_.SetObject(); ++ currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator()); ++ AddCurrentError(kValidateErrorUniqueItems, true); ++ } ++ ++ void TooManyProperties(SizeType actualCount, SizeType expectedCount) { ++ AddNumberError(kValidateErrorMaxProperties, ++ ValueType(actualCount).Move(), SValue(expectedCount).Move()); ++ } ++ void TooFewProperties(SizeType actualCount, SizeType expectedCount) { ++ AddNumberError(kValidateErrorMinProperties, ++ ValueType(actualCount).Move(), SValue(expectedCount).Move()); ++ } ++ void StartMissingProperties() { ++ currentError_.SetArray(); ++ } ++ void AddMissingProperty(const SValue& name) { ++ currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator()); ++ } ++ bool EndMissingProperties() { ++ if (currentError_.Empty()) ++ return false; ++ ValueType error(kObjectType); ++ error.AddMember(GetMissingString(), currentError_, GetStateAllocator()); ++ currentError_ = error; ++ AddCurrentError(kValidateErrorRequired); ++ return true; ++ } ++ void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) { ++ for (SizeType i = 0; i < count; ++i) ++ MergeError(static_cast(subvalidators[i])->GetError()); ++ } ++ void DisallowedProperty(const Ch* name, SizeType length) { ++ currentError_.SetObject(); ++ currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator()); ++ AddCurrentError(kValidateErrorAdditionalProperties, true); ++ } ++ ++ void StartDependencyErrors() { ++ currentError_.SetObject(); ++ } ++ void StartMissingDependentProperties() { ++ missingDependents_.SetArray(); ++ } ++ void AddMissingDependentProperty(const SValue& targetName) { ++ missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator()); ++ } ++ void EndMissingDependentProperties(const SValue& sourceName) { ++ if (!missingDependents_.Empty()) { ++ // Create equivalent 'required' error ++ ValueType error(kObjectType); ++ ValidateErrorCode code = kValidateErrorRequired; ++ error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator()); ++ AddErrorCode(error, code); ++ AddErrorInstanceLocation(error, false); ++ // When appending to a pointer ensure its allocator is used ++ PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator()); ++ AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator())); ++ ValueType wrapper(kObjectType); ++ wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator()); ++ currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator()); ++ } ++ } ++ void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) { ++ currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), ++ static_cast(subvalidator)->GetError(), GetStateAllocator()); ++ } ++ bool EndDependencyErrors() { ++ if (currentError_.ObjectEmpty()) ++ return false; ++ ValueType error(kObjectType); ++ error.AddMember(GetErrorsString(), currentError_, GetStateAllocator()); ++ currentError_ = error; ++ AddCurrentError(kValidateErrorDependencies); ++ return true; ++ } ++ ++ void DisallowedValue(const ValidateErrorCode code = kValidateErrorEnum) { ++ currentError_.SetObject(); ++ AddCurrentError(code); ++ } ++ void StartDisallowedType() { ++ currentError_.SetArray(); ++ } ++ void AddExpectedType(const typename SchemaType::ValueType& expectedType) { ++ currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator()); ++ } ++ void EndDisallowedType(const typename SchemaType::ValueType& actualType) { ++ ValueType error(kObjectType); ++ error.AddMember(GetExpectedString(), currentError_, GetStateAllocator()); ++ error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator()); ++ currentError_ = error; ++ AddCurrentError(kValidateErrorType); ++ } ++ void NotAllOf(ISchemaValidator** subvalidators, SizeType count) { ++ // Treat allOf like oneOf and anyOf to match https://rapidjson.org/md_doc_schema.html#allOf-anyOf-oneOf ++ AddErrorArray(kValidateErrorAllOf, subvalidators, count); ++ //for (SizeType i = 0; i < count; ++i) { ++ // MergeError(static_cast(subvalidators[i])->GetError()); ++ //} ++ } ++ void NoneOf(ISchemaValidator** subvalidators, SizeType count) { ++ AddErrorArray(kValidateErrorAnyOf, subvalidators, count); ++ } ++ void NotOneOf(ISchemaValidator** subvalidators, SizeType count) { ++ AddErrorArray(kValidateErrorOneOf, subvalidators, count); ++ } ++ void MultipleOneOf(SizeType index1, SizeType index2) { ++ ValueType matches(kArrayType); ++ matches.PushBack(index1, GetStateAllocator()); ++ matches.PushBack(index2, GetStateAllocator()); ++ currentError_.SetObject(); ++ currentError_.AddMember(GetMatchesString(), matches, GetStateAllocator()); ++ AddCurrentError(kValidateErrorOneOfMatch); ++ } ++ void Disallowed() { ++ currentError_.SetObject(); ++ AddCurrentError(kValidateErrorNot); ++ } ++ void DisallowedWhenWriting() { ++ currentError_.SetObject(); ++ AddCurrentError(kValidateErrorReadOnly); ++ } ++ void DisallowedWhenReading() { ++ currentError_.SetObject(); ++ AddCurrentError(kValidateErrorWriteOnly); ++ } ++ ++#define RAPIDJSON_STRING_(name, ...) \ ++ static const StringRefType& Get##name##String() {\ ++ static const Ch s[] = { __VA_ARGS__, '\0' };\ ++ static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ ++ return v;\ ++ } ++ ++ RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') ++ RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f') ++ RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd') ++ RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l') ++ RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd') ++ RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g') ++ RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's') ++ RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') ++ RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e') ++ RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's') ++ RAPIDJSON_STRING_(Matches, 'm', 'a', 't', 'c', 'h', 'e', 's') ++ ++#undef RAPIDJSON_STRING_ + + #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ +- if (!BeginValue() || !CurrentSchema().method arg1) {\ +- RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ +- return valid_ = false;\ ++ if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ ++ *documentStack_.template Push() = '\0';\ ++ documentStack_.template Pop(1);\ ++ RAPIDJSON_SCHEMA_PRINT(InvalidDocument, documentStack_.template Bottom());\ ++ valid_ = false;\ ++ return valid_;\ + } + + #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ +@@ -1679,14 +2820,15 @@ RAPIDJSON_MULTILINEMACRO_END + } + + #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ +- return valid_ = EndValue() && outputHandler_.method arg2 ++ valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\ ++ return valid_; + + #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 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)); } +@@ -1699,51 +2841,69 @@ RAPIDJSON_MULTILINEMACRO_END + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartObject"); + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); +- return valid_ = outputHandler_.StartObject(); ++ valid_ = !outputHandler_ || outputHandler_->StartObject(); ++ return valid_; + } + + bool Key(const Ch* str, SizeType len, bool copy) { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::Key", str); + if (!valid_) return false; + AppendToken(str, len); +- if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false; ++ if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) { ++ valid_ = false; ++ return valid_; ++ } + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); +- return valid_ = outputHandler_.Key(str, len, copy); ++ valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); ++ return valid_; + } + +- bool EndObject(SizeType memberCount) { ++ bool EndObject(SizeType memberCount) { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndObject"); + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); +- if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false; ++ if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) { ++ valid_ = false; ++ return valid_; ++ } + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartArray"); + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); +- return valid_ = outputHandler_.StartArray(); ++ valid_ = !outputHandler_ || outputHandler_->StartArray(); ++ return valid_; + } + + bool EndArray(SizeType elementCount) { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndArray"); + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); +- if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false; ++ if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) { ++ valid_ = false; ++ return valid_; ++ } + 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 +- virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) { +- return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, +-#if RAPIDJSON_SCHEMA_VERBOSE ++ virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) { ++ *documentStack_.template Push() = '\0'; ++ documentStack_.template Pop(1); ++ ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom(), documentStack_.GetSize(), + depth_ + 1, +-#endif + &GetStateAllocator()); ++ sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag); ++ return sv; + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { +@@ -1771,8 +2931,9 @@ RAPIDJSON_MULTILINEMACRO_END + } + + virtual void FreeState(void* p) { +- return StateAllocator::Free(p); ++ StateAllocator::Free(p); + } ++ // End of implementation of ISchemaStateFactory + + private: + typedef typename SchemaType::Context Context; +@@ -1782,57 +2943,67 @@ private: + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, +-#if RAPIDJSON_SCHEMA_VERBOSE ++ const char* basePath, size_t basePathSize, + 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 ++ outputHandler_(0), ++ error_(kObjectType), ++ currentError_(), ++ missingDependents_(), ++ valid_(true), ++ flags_(kValidateDefaultFlags), ++ depth_(depth) + { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (internal)", basePath && basePathSize ? basePath : ""); ++ if (basePath && basePathSize) ++ memcpy(documentStack_.template Push(basePathSize), basePath, basePathSize); + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) +- stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator()); ++ stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); + return *stateAllocator_; + } + ++ bool GetContinueOnErrors() const { ++ return flags_ & kValidateContinueOnErrorFlag; ++ } ++ + bool BeginValue() { ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::BeginValue"); + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + +- if (!CurrentSchema().BeginValue(CurrentContext())) ++ if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors()) + 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); ++ RAPIDJSON_ASSERT(CurrentContext().valueSchema); ++ PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); ++ std::memset(va, 0, sizeof(ISchemaValidator*) * count); + for (SizeType i = 0; i < count; i++) +- va[validatorCount++] = CreateSchemaValidator(*sa[i]); ++ va[validatorCount++] = CreateSchemaValidator(*sa[i], true); // Inherit continueOnError + } + + CurrentContext().arrayUniqueness = valueUniqueness; +@@ -1841,31 +3012,37 @@ private: + } + + bool EndValue() { +- if (!CurrentSchema().EndValue(CurrentContext())) ++ RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndValue"); ++ if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + +-#if RAPIDJSON_SCHEMA_VERBOSE + GenericStringBuffer sb; +- schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); +- ++ schemaDocument_->GetPointer(&CurrentSchema()).StringifyUriFragment(sb); + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); +- internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); +-#endif +- +- uint64_t h = CurrentContext().arrayUniqueness ? static_cast(CurrentContext().hasher)->GetHashCode() : 0; ++ RAPIDJSON_SCHEMA_PRINT(ValidatorPointers, sb.GetString(), documentStack_.template Bottom(), depth_); ++ void* hasher = CurrentContext().hasher; ++ uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast(hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); +- if (context.valueUniqueness) { ++ // Only check uniqueness if there is a hasher ++ if (hasher && context.valueUniqueness) { + HashCodeArray* a = static_cast(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()); ++ if (itr->GetUint64() == h) { ++ DuplicateItems(static_cast(itr - a->Begin()), a->Size()); ++ // Cleanup before returning if continuing ++ if (GetContinueOnErrors()) { ++ a->PushBack(h, GetStateAllocator()); ++ while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/'); ++ } ++ RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems); ++ } + a->PushBack(h, GetStateAllocator()); + } + } +@@ -1894,7 +3071,7 @@ private: + } + } + +- RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, &schema); } ++ RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, *this, &schema, flags_); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop(1); +@@ -1905,28 +3082,98 @@ private: + c->~Context(); + } + ++ void AddErrorInstanceLocation(ValueType& result, bool parent) { ++ GenericStringBuffer sb; ++ PointerType instancePointer = GetInvalidDocumentPointer(); ++ ((parent && instancePointer.GetTokenCount() > 0) ++ ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1) ++ : instancePointer).StringifyUriFragment(sb); ++ ValueType instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), ++ GetStateAllocator()); ++ result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator()); ++ } ++ ++ void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) { ++ GenericStringBuffer sb; ++ SizeType len = CurrentSchema().GetURI().GetStringLength(); ++ if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch)); ++ if (schema.GetTokenCount()) schema.StringifyUriFragment(sb); ++ else GetInvalidSchemaPointer().StringifyUriFragment(sb); ++ ValueType schemaRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), ++ GetStateAllocator()); ++ result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator()); ++ } ++ ++ void AddErrorCode(ValueType& result, const ValidateErrorCode code) { ++ result.AddMember(GetErrorCodeString(), code, GetStateAllocator()); ++ } ++ ++ void AddError(ValueType& keyword, ValueType& error) { ++ typename ValueType::MemberIterator member = error_.FindMember(keyword); ++ if (member == error_.MemberEnd()) ++ error_.AddMember(keyword, error, GetStateAllocator()); ++ else { ++ if (member->value.IsObject()) { ++ ValueType errors(kArrayType); ++ errors.PushBack(member->value, GetStateAllocator()); ++ member->value = errors; ++ } ++ member->value.PushBack(error, GetStateAllocator()); ++ } ++ } ++ ++ void AddCurrentError(const ValidateErrorCode code, bool parent = false) { ++ AddErrorCode(currentError_, code); ++ AddErrorInstanceLocation(currentError_, parent); ++ AddErrorSchemaLocation(currentError_); ++ AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(), false).Move(), currentError_); ++ } ++ ++ void MergeError(ValueType& other) { ++ for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) { ++ AddError(it->name, it->value); ++ } ++ } ++ ++ void AddNumberError(const ValidateErrorCode code, ValueType& actual, const SValue& expected, ++ const typename SchemaType::ValueType& (*exclusive)() = 0) { ++ currentError_.SetObject(); ++ currentError_.AddMember(GetActualString(), actual, GetStateAllocator()); ++ currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator()); ++ if (exclusive) ++ currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator()); ++ AddCurrentError(code); ++ } ++ ++ void AddErrorArray(const ValidateErrorCode code, ++ ISchemaValidator** subvalidators, SizeType count) { ++ ValueType errors(kArrayType); ++ for (SizeType i = 0; i < count; ++i) ++ errors.PushBack(static_cast(subvalidators[i])->GetError(), GetStateAllocator()); ++ currentError_.SetObject(); ++ currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator()); ++ AddCurrentError(code); ++ } ++ + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top(); } + const Context& CurrentContext() const { return *schemaStack_.template Top(); } + +- 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 schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) ++ OutputHandler* outputHandler_; ++ ValueType error_; ++ ValueType currentError_; ++ ValueType missingDependents_; + bool valid_; +-#if RAPIDJSON_SCHEMA_VERBOSE ++ unsigned flags_; + unsigned depth_; +-#endif + }; + + typedef GenericSchemaValidator SchemaValidator; +@@ -1954,13 +3201,14 @@ class SchemaValidatingReader { + public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; ++ typedef GenericValue ValueType; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ +- SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {} ++ SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), invalidSchemaCode_(kValidateErrorNone), error_(kObjectType), isValid_(true) {} + + template + bool operator()(Handler& handler) { +@@ -1973,11 +3221,14 @@ public: + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); ++ error_.SetObject(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); ++ invalidSchemaCode_ = validator.GetInvalidSchemaCode(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); ++ error_.CopyFrom(validator.GetError(), allocator_); + } + + return parseResult_; +@@ -1988,6 +3239,8 @@ public: + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } ++ const ValueType& GetError() const { return error_; } ++ ValidateErrorCode GetInvalidSchemaCode() const { return invalidSchemaCode_; } + + private: + InputStream& is_; +@@ -1997,6 +3250,9 @@ private: + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; ++ ValidateErrorCode invalidSchemaCode_; ++ StackAllocator allocator_; ++ ValueType error_; + bool isValid_; + }; + +diff --git a/src/common/thirdparty/rapidjson/stream.h b/src/common/thirdparty/rapidjson/stream.h +index fef82c252..1fd70915c 100644 +--- a/src/common/thirdparty/rapidjson/stream.h ++++ b/src/common/thirdparty/rapidjson/stream.h +@@ -1,15 +1,15 @@ + // 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. ++// ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 ++// 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" +@@ -100,6 +100,50 @@ inline void PutN(Stream& stream, Ch c, size_t n) { + PutUnsafe(stream, c); + } + ++/////////////////////////////////////////////////////////////////////////////// ++// GenericStreamWrapper ++ ++//! A Stream Wrapper ++/*! \tThis string stream is a wrapper for any stream by just forwarding any ++ \treceived message to the origin stream. ++ \note implements Stream concept ++*/ ++ ++#if defined(_MSC_VER) && _MSC_VER <= 1800 ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(4702) // unreachable code ++RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated ++#endif ++ ++template > ++class GenericStreamWrapper { ++public: ++ typedef typename Encoding::Ch Ch; ++ GenericStreamWrapper(InputStream& is): is_(is) {} ++ ++ Ch Peek() const { return is_.Peek(); } ++ Ch Take() { return is_.Take(); } ++ size_t Tell() { return is_.Tell(); } ++ Ch* PutBegin() { return is_.PutBegin(); } ++ void Put(Ch ch) { is_.Put(ch); } ++ void Flush() { is_.Flush(); } ++ size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); } ++ ++ // wrapper for MemoryStream ++ const Ch* Peek4() const { return is_.Peek4(); } ++ ++ // wrapper for AutoUTFInputStream ++ UTFType GetType() const { return is_.GetType(); } ++ bool HasBOM() const { return is_.HasBOM(); } ++ ++protected: ++ InputStream& is_; ++}; ++ ++#if defined(_MSC_VER) && _MSC_VER <= 1800 ++RAPIDJSON_DIAG_POP ++#endif ++ + /////////////////////////////////////////////////////////////////////////////// + // StringStream + +diff --git a/src/common/thirdparty/rapidjson/stringbuffer.h b/src/common/thirdparty/rapidjson/stringbuffer.h +index 78f34d209..82ad3ca6b 100644 +--- a/src/common/thirdparty/rapidjson/stringbuffer.h ++++ b/src/common/thirdparty/rapidjson/stringbuffer.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -78,8 +78,12 @@ public: + return stack_.template Bottom(); + } + ++ //! Get the size of string in bytes in the string buffer. + size_t GetSize() const { return stack_.GetSize(); } + ++ //! Get the length of string in Ch in the string buffer. ++ size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } ++ + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +diff --git a/src/common/thirdparty/rapidjson/uri.h b/src/common/thirdparty/rapidjson/uri.h +new file mode 100644 +index 000000000..f93e508a4 +--- /dev/null ++++ b/src/common/thirdparty/rapidjson/uri.h +@@ -0,0 +1,481 @@ ++// Tencent is pleased to support the open source community by making RapidJSON available. ++// ++// (C) Copyright IBM Corporation 2021 ++// ++// 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_URI_H_ ++#define RAPIDJSON_URI_H_ ++ ++#include "internal/strfunc.h" ++ ++#if defined(__clang__) ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(c++98-compat) ++#elif defined(_MSC_VER) ++RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated ++#endif ++ ++RAPIDJSON_NAMESPACE_BEGIN ++ ++/////////////////////////////////////////////////////////////////////////////// ++// GenericUri ++ ++template ++class GenericUri { ++public: ++ typedef typename ValueType::Ch Ch; ++#if RAPIDJSON_HAS_STDSTRING ++ typedef std::basic_string String; ++#endif ++ ++ //! Constructors ++ GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { ++ } ++ ++ GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { ++ Parse(uri, len); ++ } ++ ++ GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { ++ Parse(uri, internal::StrLen(uri)); ++ } ++ ++ // Use with specializations of GenericValue ++ template GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { ++ const Ch* u = uri.template Get(); // TypeHelper from document.h ++ Parse(u, internal::StrLen(u)); ++ } ++ ++#if RAPIDJSON_HAS_STDSTRING ++ GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { ++ Parse(uri.c_str(), internal::StrLen(uri.c_str())); ++ } ++#endif ++ ++ //! Copy constructor ++ GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() { ++ *this = rhs; ++ } ++ ++ //! Copy constructor ++ GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { ++ *this = rhs; ++ } ++ ++ //! Destructor. ++ ~GenericUri() { ++ Free(); ++ RAPIDJSON_DELETE(ownAllocator_); ++ } ++ ++ //! Assignment operator ++ GenericUri& operator=(const GenericUri& rhs) { ++ if (this != &rhs) { ++ // Do not delete ownAllocator ++ Free(); ++ Allocate(rhs.GetStringLength()); ++ auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength()); ++ path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength()); ++ query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength()); ++ frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength()); ++ base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength()); ++ uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength()); ++ CopyPart(uri_, rhs.uri_, rhs.GetStringLength()); ++ } ++ return *this; ++ } ++ ++ //! Getters ++ // Use with specializations of GenericValue ++ template void Get(T& uri, Allocator& allocator) { ++ uri.template Set(this->GetString(), allocator); // TypeHelper from document.h ++ } ++ ++ const Ch* GetString() const { return uri_; } ++ SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen(uri_); } ++ const Ch* GetBaseString() const { return base_; } ++ SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen(base_); } ++ const Ch* GetSchemeString() const { return scheme_; } ++ SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen(scheme_); } ++ const Ch* GetAuthString() const { return auth_; } ++ SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen(auth_); } ++ const Ch* GetPathString() const { return path_; } ++ SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen(path_); } ++ const Ch* GetQueryString() const { return query_; } ++ SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen(query_); } ++ const Ch* GetFragString() const { return frag_; } ++ SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen(frag_); } ++ ++#if RAPIDJSON_HAS_STDSTRING ++ static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); } ++ static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); } ++ static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); } ++ static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); } ++ static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); } ++ static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); } ++ static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); } ++#endif ++ ++ //! Equality operators ++ bool operator==(const GenericUri& rhs) const { ++ return Match(rhs, true); ++ } ++ ++ bool operator!=(const GenericUri& rhs) const { ++ return !Match(rhs, true); ++ } ++ ++ bool Match(const GenericUri& uri, bool full = true) const { ++ Ch* s1; ++ Ch* s2; ++ if (full) { ++ s1 = uri_; ++ s2 = uri.uri_; ++ } else { ++ s1 = base_; ++ s2 = uri.base_; ++ } ++ if (s1 == s2) return true; ++ if (s1 == 0 || s2 == 0) return false; ++ return internal::StrCmp(s1, s2) == 0; ++ } ++ ++ //! Resolve this URI against another (base) URI in accordance with URI resolution rules. ++ // See https://tools.ietf.org/html/rfc3986 ++ // Use for resolving an id or $ref with an in-scope id. ++ // Returns a new GenericUri for the resolved URI. ++ GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) { ++ GenericUri resuri; ++ resuri.allocator_ = allocator; ++ // Ensure enough space for combining paths ++ resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash ++ ++ if (!(GetSchemeStringLength() == 0)) { ++ // Use all of this URI ++ resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength()); ++ resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); ++ resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); ++ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); ++ resuri.RemoveDotSegments(); ++ } else { ++ // Use the base scheme ++ resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength()); ++ if (!(GetAuthStringLength() == 0)) { ++ // Use this auth, path, query ++ resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); ++ resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); ++ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); ++ resuri.RemoveDotSegments(); ++ } else { ++ // Use the base auth ++ resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength()); ++ if (GetPathStringLength() == 0) { ++ // Use the base path ++ resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength()); ++ if (GetQueryStringLength() == 0) { ++ // Use the base query ++ resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength()); ++ } else { ++ // Use this query ++ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); ++ } ++ } else { ++ if (path_[0] == '/') { ++ // Absolute path - use all of this path ++ resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); ++ resuri.RemoveDotSegments(); ++ } else { ++ // Relative path - append this path to base path after base path's last slash ++ size_t pos = 0; ++ if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) { ++ resuri.path_[pos] = '/'; ++ pos++; ++ } ++ size_t lastslashpos = baseuri.GetPathStringLength(); ++ while (lastslashpos > 0) { ++ if (baseuri.path_[lastslashpos - 1] == '/') break; ++ lastslashpos--; ++ } ++ std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch)); ++ pos += lastslashpos; ++ resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength()); ++ resuri.RemoveDotSegments(); ++ } ++ // Use this query ++ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); ++ } ++ } ++ } ++ // Always use this frag ++ resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength()); ++ ++ // Re-constitute base_ and uri_ ++ resuri.SetBase(); ++ resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1; ++ resuri.SetUri(); ++ return resuri; ++ } ++ ++ //! Get the allocator of this GenericUri. ++ Allocator& GetAllocator() { return *allocator_; } ++ ++private: ++ // Allocate memory for a URI ++ // Returns total amount allocated ++ std::size_t Allocate(std::size_t len) { ++ // Create own allocator if user did not supply. ++ if (!allocator_) ++ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ++ ++ // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated. ++ // Order: scheme, auth, path, query, frag, base, uri ++ // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. ++ size_t total = (3 * len + 7) * sizeof(Ch); ++ scheme_ = static_cast(allocator_->Malloc(total)); ++ *scheme_ = '\0'; ++ auth_ = scheme_; ++ auth_++; ++ *auth_ = '\0'; ++ path_ = auth_; ++ path_++; ++ *path_ = '\0'; ++ query_ = path_; ++ query_++; ++ *query_ = '\0'; ++ frag_ = query_; ++ frag_++; ++ *frag_ = '\0'; ++ base_ = frag_; ++ base_++; ++ *base_ = '\0'; ++ uri_ = base_; ++ uri_++; ++ *uri_ = '\0'; ++ return total; ++ } ++ ++ // Free memory for a URI ++ void Free() { ++ if (scheme_) { ++ Allocator::Free(scheme_); ++ scheme_ = 0; ++ } ++ } ++ ++ // Parse a URI into constituent scheme, authority, path, query, & fragment parts ++ // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per ++ // https://tools.ietf.org/html/rfc3986 ++ void Parse(const Ch* uri, std::size_t len) { ++ std::size_t start = 0, pos1 = 0, pos2 = 0; ++ Allocate(len); ++ ++ // Look for scheme ([^:/?#]+):)? ++ if (start < len) { ++ while (pos1 < len) { ++ if (uri[pos1] == ':') break; ++ pos1++; ++ } ++ if (pos1 != len) { ++ while (pos2 < len) { ++ if (uri[pos2] == '/') break; ++ if (uri[pos2] == '?') break; ++ if (uri[pos2] == '#') break; ++ pos2++; ++ } ++ if (pos1 < pos2) { ++ pos1++; ++ std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch)); ++ scheme_[pos1] = '\0'; ++ start = pos1; ++ } ++ } ++ } ++ // Look for auth (//([^/?#]*))? ++ // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. ++ auth_ = scheme_ + GetSchemeStringLength(); ++ auth_++; ++ *auth_ = '\0'; ++ if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') { ++ pos2 = start + 2; ++ while (pos2 < len) { ++ if (uri[pos2] == '/') break; ++ if (uri[pos2] == '?') break; ++ if (uri[pos2] == '#') break; ++ pos2++; ++ } ++ std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch)); ++ auth_[pos2 - start] = '\0'; ++ start = pos2; ++ } ++ // Look for path ([^?#]*) ++ // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. ++ path_ = auth_ + GetAuthStringLength(); ++ path_++; ++ *path_ = '\0'; ++ if (start < len) { ++ pos2 = start; ++ while (pos2 < len) { ++ if (uri[pos2] == '?') break; ++ if (uri[pos2] == '#') break; ++ pos2++; ++ } ++ if (start != pos2) { ++ std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch)); ++ path_[pos2 - start] = '\0'; ++ if (path_[0] == '/') ++ RemoveDotSegments(); // absolute path - normalize ++ start = pos2; ++ } ++ } ++ // Look for query (\?([^#]*))? ++ // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. ++ query_ = path_ + GetPathStringLength(); ++ query_++; ++ *query_ = '\0'; ++ if (start < len && uri[start] == '?') { ++ pos2 = start + 1; ++ while (pos2 < len) { ++ if (uri[pos2] == '#') break; ++ pos2++; ++ } ++ if (start != pos2) { ++ std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch)); ++ query_[pos2 - start] = '\0'; ++ start = pos2; ++ } ++ } ++ // Look for fragment (#(.*))? ++ // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. ++ frag_ = query_ + GetQueryStringLength(); ++ frag_++; ++ *frag_ = '\0'; ++ if (start < len && uri[start] == '#') { ++ std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch)); ++ frag_[len - start] = '\0'; ++ } ++ ++ // Re-constitute base_ and uri_ ++ base_ = frag_ + GetFragStringLength() + 1; ++ SetBase(); ++ uri_ = base_ + GetBaseStringLength() + 1; ++ SetUri(); ++ } ++ ++ // Reconstitute base ++ void SetBase() { ++ Ch* next = base_; ++ std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch)); ++ next+= GetSchemeStringLength(); ++ std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch)); ++ next+= GetAuthStringLength(); ++ std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch)); ++ next+= GetPathStringLength(); ++ std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch)); ++ next+= GetQueryStringLength(); ++ *next = '\0'; ++ } ++ ++ // Reconstitute uri ++ void SetUri() { ++ Ch* next = uri_; ++ std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch)); ++ next+= GetBaseStringLength(); ++ std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch)); ++ next+= GetFragStringLength(); ++ *next = '\0'; ++ } ++ ++ // Copy a part from one GenericUri to another ++ // Return the pointer to the next part to be copied to ++ Ch* CopyPart(Ch* to, Ch* from, std::size_t len) { ++ RAPIDJSON_ASSERT(to != 0); ++ RAPIDJSON_ASSERT(from != 0); ++ std::memcpy(to, from, len * sizeof(Ch)); ++ to[len] = '\0'; ++ Ch* next = to + len + 1; ++ return next; ++ } ++ ++ // Remove . and .. segments from the path_ member. ++ // https://tools.ietf.org/html/rfc3986 ++ // This is done in place as we are only removing segments. ++ void RemoveDotSegments() { ++ std::size_t pathlen = GetPathStringLength(); ++ std::size_t pathpos = 0; // Position in path_ ++ std::size_t newpos = 0; // Position in new path_ ++ ++ // Loop through each segment in original path_ ++ while (pathpos < pathlen) { ++ // Get next segment, bounded by '/' or end ++ size_t slashpos = 0; ++ while ((pathpos + slashpos) < pathlen) { ++ if (path_[pathpos + slashpos] == '/') break; ++ slashpos++; ++ } ++ // Check for .. and . segments ++ if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') { ++ // Backup a .. segment in the new path_ ++ // We expect to find a previously added slash at the end or nothing ++ RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/'); ++ size_t lastslashpos = newpos; ++ // Make sure we don't go beyond the start segment ++ if (lastslashpos > 1) { ++ // Find the next to last slash and back up to it ++ lastslashpos--; ++ while (lastslashpos > 0) { ++ if (path_[lastslashpos - 1] == '/') break; ++ lastslashpos--; ++ } ++ // Set the new path_ position ++ newpos = lastslashpos; ++ } ++ } else if (slashpos == 1 && path_[pathpos] == '.') { ++ // Discard . segment, leaves new path_ unchanged ++ } else { ++ // Move any other kind of segment to the new path_ ++ RAPIDJSON_ASSERT(newpos <= pathpos); ++ std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch)); ++ newpos += slashpos; ++ // Add slash if not at end ++ if ((pathpos + slashpos) < pathlen) { ++ path_[newpos] = '/'; ++ newpos++; ++ } ++ } ++ // Move to next segment ++ pathpos += slashpos + 1; ++ } ++ path_[newpos] = '\0'; ++ } ++ ++ Ch* uri_; // Everything ++ Ch* base_; // Everything except fragment ++ Ch* scheme_; // Includes the : ++ Ch* auth_; // Includes the // ++ Ch* path_; // Absolute if starts with / ++ Ch* query_; // Includes the ? ++ Ch* frag_; // Includes the # ++ ++ Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. ++ Allocator* ownAllocator_; //!< Allocator owned by this Uri. ++}; ++ ++//! GenericUri for Value (UTF-8, default allocator). ++typedef GenericUri Uri; ++ ++RAPIDJSON_NAMESPACE_END ++ ++#if defined(__clang__) ++RAPIDJSON_DIAG_POP ++#endif ++ ++#endif // RAPIDJSON_URI_H_ +diff --git a/src/common/thirdparty/rapidjson/writer.h b/src/common/thirdparty/rapidjson/writer.h +index 200abadae..50f6af989 100644 +--- a/src/common/thirdparty/rapidjson/writer.h ++++ b/src/common/thirdparty/rapidjson/writer.h +@@ -1,6 +1,6 @@ + // 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. ++// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + // + // 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 +@@ -16,6 +16,8 @@ + #define RAPIDJSON_WRITER_H_ + + #include "stream.h" ++#include "internal/clzll.h" ++#include "internal/meta.h" + #include "internal/stack.h" + #include "internal/strfunc.h" + #include "internal/dtoa.h" +@@ -31,17 +33,18 @@ + #include + #elif defined(RAPIDJSON_SSE2) + #include +-#endif +- +-#ifdef _MSC_VER +-RAPIDJSON_DIAG_PUSH +-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant ++#elif defined(RAPIDJSON_NEON) ++#include + #endif + + #ifdef __clang__ + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(padded) + RAPIDJSON_DIAG_OFF(unreachable-code) ++RAPIDJSON_DIAG_OFF(c++98-compat) ++#elif defined(_MSC_VER) ++RAPIDJSON_DIAG_PUSH ++RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant + #endif + + RAPIDJSON_NAMESPACE_BEGIN +@@ -103,6 +106,13 @@ public: + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + ++#if RAPIDJSON_HAS_CXX11_RVALUE_REFS ++ Writer(Writer&& rhs) : ++ os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { ++ rhs.os_ = 0; ++ } ++#endif ++ + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, +@@ -211,10 +221,18 @@ public: + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + ++#if RAPIDJSON_HAS_STDSTRING ++ bool Key(const std::basic_string& str) ++ { ++ return Key(str.data(), SizeType(str.size())); ++ } ++#endif ++ + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; +- RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); +- RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); ++ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object ++ RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); // currently inside an Array, not Object ++ RAPIDJSON_ASSERT(0 == level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + level_stack_.template Pop(1); + return EndValue(WriteEndObject()); + } +@@ -238,9 +256,9 @@ public: + //@{ + + //! 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)); } +- ++ bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } ++ bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } ++ + //@} + + //! Write a raw JSON value. +@@ -257,6 +275,16 @@ public: + return EndValue(WriteRawValue(json, length)); + } + ++ //! Flush the output stream. ++ /*! ++ Allows the user to flush the output stream immediately. ++ */ ++ void Flush() { ++ os_->Flush(); ++ } ++ ++ static const size_t kDefaultLevelDepth = 32; ++ + protected: + //! Information for each nested level + struct Level { +@@ -265,8 +293,6 @@ protected: + 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; +@@ -289,7 +315,7 @@ protected: + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) +- PutUnsafe(*os_, static_cast(*p)); ++ PutUnsafe(*os_, static_cast(*p)); + return true; + } + +@@ -298,7 +324,7 @@ protected: + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) +- PutUnsafe(*os_, static_cast(*p)); ++ PutUnsafe(*os_, static_cast(*p)); + return true; + } + +@@ -307,7 +333,7 @@ protected: + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) +- PutUnsafe(*os_, static_cast(*p)); ++ PutUnsafe(*os_, static_cast(*p)); + return true; + } + +@@ -316,7 +342,7 @@ protected: + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) +- PutUnsafe(*os_, static_cast(*p)); ++ PutUnsafe(*os_, static_cast(*p)); + return true; + } + +@@ -352,12 +378,12 @@ protected: + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) +- PutUnsafe(*os_, static_cast(*p)); ++ PutUnsafe(*os_, static_cast(*p)); + return ret; + } + + 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 typename OutputStream::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 +@@ -413,7 +439,7 @@ protected: + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); +- PutUnsafe(*os_, static_cast(escape[static_cast(c)])); ++ PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); +@@ -441,9 +467,13 @@ protected: + + 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]); ++ GenericStringStream is(json); ++ while (RAPIDJSON_LIKELY(is.Tell() < length)) { ++ RAPIDJSON_ASSERT(is.Peek() != '\0'); ++ if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? ++ Transcoder::Validate(is, *os_) : ++ Transcoder::TranscodeUnsafe(is, *os_)))) ++ return false; + } + return true; + } +@@ -471,7 +501,7 @@ protected: + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text +- os_->Flush(); ++ Flush(); + return ret; + } + +@@ -524,15 +554,8 @@ template<> + inline bool Writer::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)) +- { +- // At least ensure that the output does not get broken. +- PutReserve(*os_, 3); +- PutUnsafe(*os_, '0'); +- PutUnsafe(*os_, '.'); +- PutUnsafe(*os_, '0'); +- return false; +- } ++ if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) ++ return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); +@@ -582,7 +605,7 @@ inline bool Writer::ScanWriteUnescapedString(StringStream& is, siz + // 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 }; ++ static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); +@@ -591,7 +614,7 @@ inline bool Writer::ScanWriteUnescapedString(StringStream& is, siz + const __m128i s = _mm_load_si128(reinterpret_cast(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 t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped +@@ -616,15 +639,79 @@ inline bool Writer::ScanWriteUnescapedString(StringStream& is, siz + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } +-#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) ++#elif defined(RAPIDJSON_NEON) ++template<> ++inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { ++ if (length < 16) ++ return RAPIDJSON_LIKELY(is.Tell() < length); + +-RAPIDJSON_NAMESPACE_END ++ if (!RAPIDJSON_LIKELY(is.Tell() < length)) ++ return false; + +-#ifdef _MSC_VER +-RAPIDJSON_DIAG_POP +-#endif ++ const char* p = is.src_; ++ const char* end = is.head_ + length; ++ const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); ++ const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); ++ if (nextAligned > end) ++ return true; + +-#ifdef __clang__ ++ 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 ++ const uint8x16_t s0 = vmovq_n_u8('"'); ++ const uint8x16_t s1 = vmovq_n_u8('\\'); ++ const uint8x16_t s2 = vmovq_n_u8('\b'); ++ const uint8x16_t s3 = vmovq_n_u8(32); ++ ++ for (; p != endAligned; p += 16) { ++ const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); ++ uint8x16_t x = vceqq_u8(s, s0); ++ x = vorrq_u8(x, vceqq_u8(s, s1)); ++ x = vorrq_u8(x, vceqq_u8(s, s2)); ++ x = vorrq_u8(x, vcltq_u8(s, s3)); ++ ++ x = vrev64q_u8(x); // Rev in 64 ++ uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract ++ uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract ++ ++ SizeType len = 0; ++ bool escaped = false; ++ if (low == 0) { ++ if (high != 0) { ++ uint32_t lz = internal::clzll(high); ++ len = 8 + (lz >> 3); ++ escaped = true; ++ } ++ } else { ++ uint32_t lz = internal::clzll(low); ++ len = lz >> 3; ++ escaped = true; ++ } ++ if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped ++ char* q = reinterpret_cast(os_->PushUnsafe(len)); ++ for (size_t i = 0; i < len; i++) ++ q[i] = p[i]; ++ ++ p += len; ++ break; ++ } ++ vst1q_u8(reinterpret_cast(os_->PushUnsafe(16)), s); ++ } ++ ++ is.src_ = p; ++ return RAPIDJSON_LIKELY(is.Tell() < length); ++} ++#endif // RAPIDJSON_NEON ++ ++RAPIDJSON_NAMESPACE_END ++ ++#if defined(_MSC_VER) || defined(__clang__) + RAPIDJSON_DIAG_POP + #endif + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0045-made-D_WriteUserInfoStrings-memory-safe.patch b/games-fps/gzdoom/files/0045-made-D_WriteUserInfoStrings-memory-safe.patch new file mode 100644 index 0000000..cf7cb17 --- /dev/null +++ b/games-fps/gzdoom/files/0045-made-D_WriteUserInfoStrings-memory-safe.patch @@ -0,0 +1,200 @@ +From 3b52c955b18667bd6ea319f89e762c5331603bc9 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sun, 26 Mar 2023 09:27:26 +0200 +Subject: [PATCH 45/51] - made D_WriteUserInfoStrings memory safe. + +Its callers are anything but for now but this function was the main blocker for refactoring so it had to come first. +--- + src/d_net.cpp | 8 +++- + src/d_netinf.h | 2 +- + src/d_netinfo.cpp | 106 +++++++++++++++++++++++----------------------- + src/g_game.cpp | 10 +++-- + 4 files changed, 65 insertions(+), 61 deletions(-) + +diff --git a/src/d_net.cpp b/src/d_net.cpp +index e83b06939..80f43e1a2 100644 +--- a/src/d_net.cpp ++++ b/src/d_net.cpp +@@ -1505,7 +1505,9 @@ bool DoArbitrate (void *userdata) + netbuffer[1] = consoleplayer; + netbuffer[9] = data->gotsetup[0]; + stream = &netbuffer[10]; +- D_WriteUserInfoStrings (consoleplayer, &stream, true); ++ auto str = D_GetUserInfoStrings (consoleplayer, true); ++ memcpy(stream, str.GetChars(), str.Len() + 1); ++ stream += str.Len(); + SendSetup (data->playersdetected, data->gotsetup, int(stream - netbuffer)); + } + else +@@ -1520,7 +1522,9 @@ bool DoArbitrate (void *userdata) + { + netbuffer[1] = j; + stream = &netbuffer[9]; +- D_WriteUserInfoStrings (j, &stream, true); ++ auto str = D_GetUserInfoStrings(j, true); ++ memcpy(stream, str.GetChars(), str.Len() + 1); ++ stream += str.Len(); + HSendPacket (i, int(stream - netbuffer)); + } + } +diff --git a/src/d_netinf.h b/src/d_netinf.h +index 5e46b7b14..56f955e06 100644 +--- a/src/d_netinf.h ++++ b/src/d_netinf.h +@@ -58,7 +58,7 @@ bool D_SendServerInfoChange (FBaseCVar *cvar, UCVarValue value, ECVarType type); + bool D_SendServerFlagChange (FBaseCVar *cvar, int bitnum, bool set, bool silent); + void D_DoServerInfoChange (uint8_t **stream, bool singlebit); + +-void D_WriteUserInfoStrings (int player, uint8_t **stream, bool compact=false); ++FString D_GetUserInfoStrings(int pnum, bool compact = false); + void D_ReadUserInfoStrings (int player, uint8_t **stream, bool update); + + struct FPlayerColorSet; +diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp +index 6c31fbe73..bbcd42168 100644 +--- a/src/d_netinfo.cpp ++++ b/src/d_netinfo.cpp +@@ -727,67 +727,65 @@ static int namesortfunc(const void *a, const void *b) + return stricmp(name1->GetChars(), name2->GetChars()); + } + +-void D_WriteUserInfoStrings (int pnum, uint8_t **stream, bool compact) ++FString D_GetUserInfoStrings(int pnum, bool compact) + { +- if (pnum >= MAXPLAYERS) ++ FString result; ++ if (pnum >= 0 && pnum < MAXPLAYERS) + { +- WriteByte (0, stream); +- return; +- } +- +- userinfo_t *info = &players[pnum].userinfo; +- TArray::Pair *> userinfo_pairs(info->CountUsed()); +- TMap::Iterator it(*info); +- TMap::Pair *pair; +- UCVarValue cval; ++ userinfo_t* info = &players[pnum].userinfo; ++ TArray::Pair*> userinfo_pairs(info->CountUsed()); ++ TMap::Iterator it(*info); ++ TMap::Pair* pair; ++ UCVarValue cval; + +- // Create a simple array of all userinfo cvars +- while (it.NextPair(pair)) +- { +- userinfo_pairs.Push(pair); +- } +- // For compact mode, these need to be sorted. Verbose mode doesn't matter. +- if (compact) +- { +- qsort(&userinfo_pairs[0], userinfo_pairs.Size(), sizeof(pair), userinfosortfunc); +- // Compact mode is signified by starting the string with two backslash characters. +- // We output one now. The second will be output as part of the first value. +- *(*stream)++ = '\\'; +- } +- for (unsigned int i = 0; i < userinfo_pairs.Size(); ++i) +- { +- pair = userinfo_pairs[i]; +- +- if (!compact) +- { // In verbose mode, prepend the cvar's name +- *stream += sprintf(*((char **)stream), "\\%s", pair->Key.GetChars()); ++ // Create a simple array of all userinfo cvars ++ while (it.NextPair(pair)) ++ { ++ userinfo_pairs.Push(pair); ++ } ++ // For compact mode, these need to be sorted. Verbose mode doesn't matter. ++ if (compact) ++ { ++ qsort(&userinfo_pairs[0], userinfo_pairs.Size(), sizeof(pair), userinfosortfunc); ++ // Compact mode is signified by starting the string with two backslash characters. ++ // We output one now. The second will be output as part of the first value. ++ result += '\\'; + } +- // A few of these need special handling for compatibility reasons. +- switch (pair->Key.GetIndex()) ++ for (unsigned int i = 0; i < userinfo_pairs.Size(); ++i) + { +- case NAME_Gender: +- *stream += sprintf(*((char **)stream), "\\%s", +- *static_cast(pair->Value) == GENDER_FEMALE ? "female" : +- *static_cast(pair->Value) == GENDER_NEUTER ? "neutral" : +- *static_cast(pair->Value) == GENDER_OBJECT ? "other" : "male"); +- break; +- +- case NAME_PlayerClass: +- *stream += sprintf(*((char **)stream), "\\%s", info->GetPlayerClassNum() == -1 ? "Random" : +- D_EscapeUserInfo(info->GetPlayerClassType()->GetDisplayName().GetChars()).GetChars()); +- break; +- +- case NAME_Skin: +- *stream += sprintf(*((char **)stream), "\\%s", D_EscapeUserInfo(Skins[info->GetSkin()].Name).GetChars()); +- break; +- +- default: +- cval = pair->Value->GetGenericRep(CVAR_String); +- *stream += sprintf(*((char **)stream), "\\%s", cval.String); +- break; ++ pair = userinfo_pairs[i]; ++ ++ if (!compact) ++ { // In verbose mode, prepend the cvar's name ++ result.AppendFormat("\\%s", pair->Key.GetChars()); ++ } ++ // A few of these need special handling for compatibility reasons. ++ switch (pair->Key.GetIndex()) ++ { ++ case NAME_Gender: ++ result.AppendFormat("\\%s", ++ *static_cast(pair->Value) == GENDER_FEMALE ? "female" : ++ *static_cast(pair->Value) == GENDER_NEUTER ? "neutral" : ++ *static_cast(pair->Value) == GENDER_OBJECT ? "other" : "male"); ++ break; ++ ++ case NAME_PlayerClass: ++ result.AppendFormat("\\%s", info->GetPlayerClassNum() == -1 ? "Random" : ++ D_EscapeUserInfo(info->GetPlayerClassType()->GetDisplayName().GetChars()).GetChars()); ++ break; ++ ++ case NAME_Skin: ++ result.AppendFormat("\\%s", D_EscapeUserInfo(Skins[info->GetSkin()].Name).GetChars()); ++ break; ++ ++ default: ++ cval = pair->Value->GetGenericRep(CVAR_String); ++ result.AppendFormat("\\%s", cval.String); ++ break; ++ } + } + } +- *(*stream)++ = '\0'; ++ return result; + } + + void D_ReadUserInfoStrings (int pnum, uint8_t **stream, bool update) +diff --git a/src/g_game.cpp b/src/g_game.cpp +index c960bab26..7ac7fd98d 100644 +--- a/src/g_game.cpp ++++ b/src/g_game.cpp +@@ -2618,10 +2618,12 @@ void G_BeginRecording (const char *startmap) + { + if (playeringame[i]) + { +- StartChunk (UINF_ID, &demo_p); +- WriteByte ((uint8_t)i, &demo_p); +- D_WriteUserInfoStrings (i, &demo_p); +- FinishChunk (&demo_p); ++ StartChunk(UINF_ID, &demo_p); ++ WriteByte((uint8_t)i, &demo_p); ++ auto str = D_GetUserInfoStrings(i); ++ memcpy(demo_p, str.GetChars(), str.Len() + 1); ++ demo_p += str.Len(); ++ FinishChunk(&demo_p); + } + } + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0046-avoid-arithmetics-with-literal-null-pointers-in-Pars.patch b/games-fps/gzdoom/files/0046-avoid-arithmetics-with-literal-null-pointers-in-Pars.patch new file mode 100644 index 0000000..fa2712d --- /dev/null +++ b/games-fps/gzdoom/files/0046-avoid-arithmetics-with-literal-null-pointers-in-Pars.patch @@ -0,0 +1,68 @@ +From 43131effaa913a40fe10c15836e272c484b7c4f7 Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sun, 26 Mar 2023 09:49:40 +0200 +Subject: [PATCH 46/51] - avoid arithmetics with literal null pointers in + ParseCommandLine. + +Also avoid using longs. +--- + src/m_misc.cpp | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/m_misc.cpp b/src/m_misc.cpp +index 6e40991da..45af80cec 100644 +--- a/src/m_misc.cpp ++++ b/src/m_misc.cpp +@@ -74,7 +74,7 @@ CVAR(String, screenshot_type, "png", CVAR_ARCHIVE|CVAR_GLOBALCONFIG); + CVAR(String, screenshot_dir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG); + EXTERN_CVAR(Bool, longsavemessages); + +-static long ParseCommandLine (const char *args, int *argc, char **argv); ++static size_t ParseCommandLine (const char *args, int *argc, char **argv); + + + //--------------------------------------------------------------------------- +@@ -101,7 +101,7 @@ void M_FindResponseFile (void) + TArray file; + int argc = 0; + int size; +- long argsize = 0; ++ size_t argsize = 0; + int index; + + // Any more response files after the limit will be removed from the +@@ -179,17 +179,19 @@ void M_FindResponseFile (void) + // This is just like the version in c_dispatch.cpp, except it does not + // do cvar expansion. + +-static long ParseCommandLine (const char *args, int *argc, char **argv) ++static size_t ParseCommandLine (const char *args, int *argc, char **argv) + { + int count; ++ char* buffstart; + char *buffplace; + + count = 0; +- buffplace = NULL; ++ buffstart = NULL; + if (argv != NULL) + { +- buffplace = argv[0]; ++ buffstart = argv[0]; + } ++ buffplace = buffstart; + + for (;;) + { +@@ -257,7 +259,7 @@ static long ParseCommandLine (const char *args, int *argc, char **argv) + { + *argc = count; + } +- return (long)(buffplace - (char *)0); ++ return (buffplace - buffstart); + } + + +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0047-backported-RapidJSON-fix-from-Raze.patch b/games-fps/gzdoom/files/0047-backported-RapidJSON-fix-from-Raze.patch new file mode 100644 index 0000000..bf57edc --- /dev/null +++ b/games-fps/gzdoom/files/0047-backported-RapidJSON-fix-from-Raze.patch @@ -0,0 +1,69 @@ +From 08d36a6540644f636466d118f1fa92d23060e24a Mon Sep 17 00:00:00 2001 +From: Christoph Oelckers +Date: Sat, 1 Apr 2023 12:45:55 +0200 +Subject: [PATCH 47/51] - backported RapidJSON fix from Raze. + +--- + src/common/thirdparty/rapidjson/writer.h | 36 +++++++++++++++--------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +diff --git a/src/common/thirdparty/rapidjson/writer.h b/src/common/thirdparty/rapidjson/writer.h +index 50f6af989..bbc944979 100644 +--- a/src/common/thirdparty/rapidjson/writer.h ++++ b/src/common/thirdparty/rapidjson/writer.h +@@ -552,30 +552,38 @@ inline bool Writer::WriteUint64(uint64_t u) { + + template<> + inline bool Writer::WriteDouble(double d) { ++ bool ret = true; + 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_, '-'); ++ { ++ // if we abort here, the writer is left in a broken state, unable to recover, so better write a 0 in addition to returning an error. ++ ret = false; ++ d = 0; + } + 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; ++ { ++ 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(25 - (end - buffer))); +- return true; ++ return ret; + } + + #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0048-Fix-value-of-X-Y-when-Y-is-an-int-constant.patch b/games-fps/gzdoom/files/0048-Fix-value-of-X-Y-when-Y-is-an-int-constant.patch new file mode 100644 index 0000000..c5c0cd8 --- /dev/null +++ b/games-fps/gzdoom/files/0048-Fix-value-of-X-Y-when-Y-is-an-int-constant.patch @@ -0,0 +1,33 @@ +From 2990caaa937b96c70124258ed48353587dbcdd4f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Sat, 11 Feb 2023 12:51:25 -0300 +Subject: [PATCH 48/51] Fix value of `X = Y` when Y is an int constant + +--- + src/common/scripting/backend/codegen.cpp | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp +index 6cf593fa2..7be3c67c1 100644 +--- a/src/common/scripting/backend/codegen.cpp ++++ b/src/common/scripting/backend/codegen.cpp +@@ -2571,7 +2571,15 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) + } + + pointer.Free(build); +- return result; ++ ++ if(intconst) ++ { //fix int constant return for assignment ++ return Right->Emit(build); ++ } ++ else ++ { ++ return result; ++ } + } + + //========================================================================== +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0049-Fix-BUILD_SHARED_LIBS-build-option-on-Windows.patch b/games-fps/gzdoom/files/0049-Fix-BUILD_SHARED_LIBS-build-option-on-Windows.patch new file mode 100644 index 0000000..339a5a6 --- /dev/null +++ b/games-fps/gzdoom/files/0049-Fix-BUILD_SHARED_LIBS-build-option-on-Windows.patch @@ -0,0 +1,27 @@ +From 571637d6ea1f12f7b86ee223f33de1cc0351e17d Mon Sep 17 00:00:00 2001 +From: Chris Cowan +Date: Sat, 13 May 2023 21:39:55 -0700 +Subject: [PATCH 49/51] Fix BUILD_SHARED_LIBS build option on Windows + +This commit fixes the build error "unresolved external symbol GetModuleInformation" when the project is built on Windows with BUILD_SHARED_LIBS enabled. + +Gzdoom must be linked against "psapi". When BUILD_SHARED_LIBS is off (default), it gets linked because the discord-rpc library is linked against it and then statically linked into the project. The issue is fixed by making Gzdoom itself explicitly link against "psapi" too. +--- + src/CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 911e35dce..889a99dba 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -54,6 +54,7 @@ if( WIN32 ) + add_definitions( -D_WIN32 ) + + set( PROJECT_LIBRARIES ++ psapi + wsock32 + winmm + dinput8 +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0050-Add-missing-include-guards.patch b/games-fps/gzdoom/files/0050-Add-missing-include-guards.patch new file mode 100644 index 0000000..8168d8e --- /dev/null +++ b/games-fps/gzdoom/files/0050-Add-missing-include-guards.patch @@ -0,0 +1,212 @@ +From 7e650c79a9b06b509a33be59cda816b6272a670c Mon Sep 17 00:00:00 2001 +From: l2ksolkov +Date: Sun, 28 May 2023 20:29:24 -0700 +Subject: [PATCH 50/51] Add missing include guards + +--- + src/common/console/c_commandbuffer.h | 1 + + src/common/console/c_consolebuffer.h | 1 + + src/common/engine/serializer_internal.h | 1 + + src/common/filesystem/ancientzip.h | 1 + + src/common/platform/win32/winres.h | 1 + + src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h | 2 +- + src/common/scripting/jit/jitintern.h | 2 +- + src/common/textures/animlib.h | 1 + + src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h | 1 + + src/common/utility/weightedlist.h | 1 + + src/d_defcvars.h | 1 + + src/g_pch.h | 1 + + src/g_pch2.h | 1 + + src/gamedata/doomfont.h | 1 + + src/r_data/r_vanillatrans.h | 1 + + src/rendering/hwrenderer/hw_vertexbuilder.h | 2 +- + src/rendering/swrenderer/textures/warpbuffer.h | 1 + + 17 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/src/common/console/c_commandbuffer.h b/src/common/console/c_commandbuffer.h +index 179651c45..637027b27 100644 +--- a/src/common/console/c_commandbuffer.h ++++ b/src/common/console/c_commandbuffer.h +@@ -1,3 +1,4 @@ ++#pragma once + #include + #include "zstring.h" + +diff --git a/src/common/console/c_consolebuffer.h b/src/common/console/c_consolebuffer.h +index 58bc0edea..8d4e235d5 100644 +--- a/src/common/console/c_consolebuffer.h ++++ b/src/common/console/c_consolebuffer.h +@@ -32,6 +32,7 @@ + **--------------------------------------------------------------------------- + ** + */ ++#pragma once + + #include + #include +diff --git a/src/common/engine/serializer_internal.h b/src/common/engine/serializer_internal.h +index 31cf76c1a..05b6dcad0 100644 +--- a/src/common/engine/serializer_internal.h ++++ b/src/common/engine/serializer_internal.h +@@ -1,3 +1,4 @@ ++#pragma once + const char* UnicodeToString(const char* cc); + const char* StringToUnicode(const char* cc, int size = -1); + +diff --git a/src/common/filesystem/ancientzip.h b/src/common/filesystem/ancientzip.h +index 621505504..6241f775d 100644 +--- a/src/common/filesystem/ancientzip.h ++++ b/src/common/filesystem/ancientzip.h +@@ -1,3 +1,4 @@ ++#pragma once + #include "files.h" + #include "engineerrors.h" + +diff --git a/src/common/platform/win32/winres.h b/src/common/platform/win32/winres.h +index 6d78230d8..a2b8711a6 100644 +--- a/src/common/platform/win32/winres.h ++++ b/src/common/platform/win32/winres.h +@@ -10,6 +10,7 @@ + + // winres.h - Windows resource definitions + // extracted from WINUSER.H and COMMCTRL.H ++#pragma once + + #ifdef _AFX_MINREBUILD + #pragma component(minrebuild, off) +diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h +index f52af7ebc..8efe61738 100644 +--- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h ++++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h +@@ -1,4 +1,4 @@ +- ++#pragma once + #include "tarray.h" + #include "hwrenderer/data/buffers.h" + +diff --git a/src/common/scripting/jit/jitintern.h b/src/common/scripting/jit/jitintern.h +index aaf8d70a6..05dfd62df 100644 +--- a/src/common/scripting/jit/jitintern.h ++++ b/src/common/scripting/jit/jitintern.h +@@ -1,4 +1,4 @@ +- ++#pragma once + #include "jit.h" + + #include "types.h" +diff --git a/src/common/textures/animlib.h b/src/common/textures/animlib.h +index 23d0d89da..661f00fb2 100644 +--- a/src/common/textures/animlib.h ++++ b/src/common/textures/animlib.h +@@ -24,6 +24,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms + Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) + */ + //------------------------------------------------------------------------- ++#pragma once + + #include + ///////////////////////////////////////////////////////////////////////////// +diff --git a/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h b/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h +index 918b904fe..6e2a93108 100644 +--- a/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h ++++ b/src/common/textures/hires/hqnx_asm/hqnx_asm_Image.h +@@ -19,6 +19,7 @@ + //#ifdef WIN32 + //#define DLL __declspec(dllexport) + //#else ++#pragma once + #define DLL + //#endif + +diff --git a/src/common/utility/weightedlist.h b/src/common/utility/weightedlist.h +index cd6a4ba0e..fb956a462 100644 +--- a/src/common/utility/weightedlist.h ++++ b/src/common/utility/weightedlist.h +@@ -31,6 +31,7 @@ + **--------------------------------------------------------------------------- + ** + */ ++#pragma once + + #include + #include +diff --git a/src/d_defcvars.h b/src/d_defcvars.h +index 73f110c70..8bf3d7c18 100644 +--- a/src/d_defcvars.h ++++ b/src/d_defcvars.h +@@ -19,6 +19,7 @@ + // defcvars loader split from d_main.cpp + // + //----------------------------------------------------------------------------- ++#pragma once + + #define SHOULD_BLACKLIST(name) \ + if (#name[0]==CurrentFindCVar[0]) \ +diff --git a/src/g_pch.h b/src/g_pch.h +index bad3eda56..cf3dfdbd5 100644 +--- a/src/g_pch.h ++++ b/src/g_pch.h +@@ -1,3 +1,4 @@ ++#pragma once + #include + #include + #include +diff --git a/src/g_pch2.h b/src/g_pch2.h +index 4cd69197e..f5871488a 100644 +--- a/src/g_pch2.h ++++ b/src/g_pch2.h +@@ -1,4 +1,5 @@ + // This is separate because the files being compiled with it use different compiler settings which may affect how the header is compiled ++#pragma once + #include + #include + #include +diff --git a/src/gamedata/doomfont.h b/src/gamedata/doomfont.h +index 9b44a480f..b9d14db7d 100644 +--- a/src/gamedata/doomfont.h ++++ b/src/gamedata/doomfont.h +@@ -1,6 +1,7 @@ + // + // Globally visible constants. + // ++#pragma once + #define HU_FONTSTART uint8_t('!') // the first font characters + #define HU_FONTEND uint8_t('\377') // the last font characters + +diff --git a/src/r_data/r_vanillatrans.h b/src/r_data/r_vanillatrans.h +index 702fc8212..d6b6a5d9e 100644 +--- a/src/r_data/r_vanillatrans.h ++++ b/src/r_data/r_vanillatrans.h +@@ -30,6 +30,7 @@ + **--------------------------------------------------------------------------- + ** + */ ++#pragma once + + + void UpdateVanillaTransparency(); +diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.h b/src/rendering/hwrenderer/hw_vertexbuilder.h +index 4fbe9916f..0444613be 100644 +--- a/src/rendering/hwrenderer/hw_vertexbuilder.h ++++ b/src/rendering/hwrenderer/hw_vertexbuilder.h +@@ -1,4 +1,4 @@ +- ++#pragma once + #include "tarray.h" + #include "r_defs.h" + struct vertex_t; +diff --git a/src/rendering/swrenderer/textures/warpbuffer.h b/src/rendering/swrenderer/textures/warpbuffer.h +index 778706850..594903a53 100644 +--- a/src/rendering/swrenderer/textures/warpbuffer.h ++++ b/src/rendering/swrenderer/textures/warpbuffer.h +@@ -31,6 +31,7 @@ + **--------------------------------------------------------------------------- + ** + */ ++#pragma once + + #include "textures.h" + #include "texturemanager.h" +-- +2.39.3 + diff --git a/games-fps/gzdoom/files/0051-Update-service.zs.patch b/games-fps/gzdoom/files/0051-Update-service.zs.patch new file mode 100644 index 0000000..653001c --- /dev/null +++ b/games-fps/gzdoom/files/0051-Update-service.zs.patch @@ -0,0 +1,25 @@ +From d229f9bfaf95dd057f116f72704c74134a511ff6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= +Date: Wed, 14 Jun 2023 20:33:30 -0300 +Subject: [PATCH 51/51] Update service.zs + +--- + wadsrc/static/zscript/engine/service.zs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/wadsrc/static/zscript/engine/service.zs b/wadsrc/static/zscript/engine/service.zs +index 26102b0a2..8090fff37 100644 +--- a/wadsrc/static/zscript/engine/service.zs ++++ b/wadsrc/static/zscript/engine/service.zs +@@ -56,7 +56,7 @@ class Service abstract + } + + static Service Find(class serviceName){ +- return AllServices.GetIfExists(serviceName.GetClassName()); ++ return AllServices.Get(serviceName.GetClassName()); + } + } + +-- +2.39.3 + diff --git a/games-fps/gzdoom/gzdoom-4.10.0-r1.ebuild b/games-fps/gzdoom/gzdoom-4.10.0-r1.ebuild new file mode 100644 index 0000000..39a6a04 --- /dev/null +++ b/games-fps/gzdoom/gzdoom-4.10.0-r1.ebuild @@ -0,0 +1,140 @@ +# Copyright 1999-2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +inherit cmake desktop xdg flag-o-matic + +DESCRIPTION="A modder-friendly OpenGL source port based on the DOOM engine" +HOMEPAGE="https://zdoom.org" +SRC_URI="https://github.com/coelckers/${PN}/archive/g${PV}.tar.gz -> ${P}.tar.gz" + +LICENSE="Apache-2.0 BSD BZIP2 GPL-3 LGPL-2.1+ LGPL-3 MIT + non-free? ( Activision ChexQuest3 DOOM-COLLECTORS-EDITION freedist WidePix )" +SLOT="0" +KEYWORDS="~amd64 ~arm64" +IUSE="debug gles2 gtk +non-free openmp +swr telemetry vulkan" + +DEPEND=" + app-arch/bzip2 + media-libs/libjpeg-turbo:0= + media-libs/libsdl2[gles2?,opengl,vulkan?] + media-libs/libvpx:= + media-libs/openal + media-libs/zmusic + sys-libs/zlib + gtk? ( x11-libs/gtk+:3 )" +RDEPEND="${DEPEND}" + +S="${WORKDIR}/${PN}-g${PV}" + +PATCHES=( + "${FILESDIR}"/${PN}-4.7.1-Introduce-the-BUILD_NONFREE-option.patch + "${FILESDIR}"/0018-indicate-in-the-startup-window-title-when-GZDoom-is-.patch + "${FILESDIR}"/0002-Fix-PMapValueReader-warning-on-Clang-GCC.patch + "${FILESDIR}"/0020-new-characters-for-Doom-s-SmallFont-and-BigFont.patch + "${FILESDIR}"/0032-Mark-const-methods-as-const-in-pseudo-generics.patch + "${FILESDIR}"/0013-fixed-buffer-size-checks-for-raw-textures.patch + "${FILESDIR}"/0005-fixed-GC-FullGC-not-collecting-everything-anymore.patch + "${FILESDIR}"/0016-Fix-MapIterator-X-String-GetValue.patch + "${FILESDIR}"/0037-Update-service.zs.patch + "${FILESDIR}"/0004-fixed-some-bad-character-offsets-in-Doom-s-and-Raven.patch + "${FILESDIR}"/0009-Error-out-instead-of-crashing-for-vector-out-variabl.patch + "${FILESDIR}"/0012-Prevent-important-messages-from-being-accidentally-f.patch + "${FILESDIR}"/0007-Fixed-IsActorPlayingSound-s-default-argument.patch + "${FILESDIR}"/0030-Fixed-a-bug-where-calling-an-invalid-virtual-functio.patch + "${FILESDIR}"/0001-Add-casts-to-F32-Map-MapIterator-functions-to-get-ri.patch + "${FILESDIR}"/0042-Use-simpler-constructor-for-TArray-in-FBlockThingsIt.patch + "${FILESDIR}"/0044-updated-RapidJson-library.patch + "${FILESDIR}"/0023-convert-characters-to-Doom-patch-format.patch + "${FILESDIR}"/0026-Add-Missing-Read-Barriers-to-Map-Get-Functions.patch + "${FILESDIR}"/0049-Fix-BUILD_SHARED_LIBS-build-option-on-Windows.patch + "${FILESDIR}"/0036-fixed-typo-in-string-label.patch + "${FILESDIR}"/0043-Fix-possible-memory-corruption-in-TArray-Delete-inde.patch + "${FILESDIR}"/0021-4-non-letter-characters-for-Chex.patch + "${FILESDIR}"/0045-made-D_WriteUserInfoStrings-memory-safe.patch + "${FILESDIR}"/0010-Fix-StripLeftRight.patch + "${FILESDIR}"/0024-Mark-non-modifying-map-functions-as-const.patch + "${FILESDIR}"/0038-Allow-GAMEINFO-LOAD-to-load-directories.patch + "${FILESDIR}"/0011-Fixed-custom-height-and-width-not-saving.patch + "${FILESDIR}"/0033-Fixing-GLES-mode-to-work-on-real-GLES-hardware-and-O.patch + "${FILESDIR}"/0047-backported-RapidJSON-fix-from-Raze.patch + "${FILESDIR}"/0028-refactor-add-some-logs-to-help-understand-what-is-ha.patch + "${FILESDIR}"/0027-cleanup-of-the-Chex-Quest-small-font.patch + "${FILESDIR}"/0015-Fixed-a-bug-where-static-events-would-fail-to-halt-p.patch + "${FILESDIR}"/0046-avoid-arithmetics-with-literal-null-pointers-in-Pars.patch + "${FILESDIR}"/0040-Fixed-incorrect-parameter-type-in-A_CheckForResurrec.patch + "${FILESDIR}"/0025-Fix-iterator-invalidation-for-Map-Get.patch + "${FILESDIR}"/0014-Impel-people-to-include-demo-mods-in-bug-reports.patch + "${FILESDIR}"/0029-Added-check-for-invalid-class-on-in-VM-instantiation.patch + "${FILESDIR}"/0017-Fix-two-different-portable-names.patch + "${FILESDIR}"/0008-removed-clangformat-from-discord-rpc.patch + "${FILESDIR}"/0050-Add-missing-include-guards.patch + "${FILESDIR}"/0006-Fix-wrong-assumptions-about-actor-initialization-in-.patch + "${FILESDIR}"/0034-Fix-Software-Slope-Rendering-for-non-1.2-pixel-ratio.patch + "${FILESDIR}"/0035-Improve-Services.patch + "${FILESDIR}"/0031-GLES-Fix-first-wipe.patch + "${FILESDIR}"/0048-Fix-value-of-X-Y-when-Y-is-an-int-constant.patch + "${FILESDIR}"/0003-Fix-Quicksave-Rotation.patch + "${FILESDIR}"/0039-fixed-bad-character-offset.patch + "${FILESDIR}"/0041-Fix-TArray-allocating-0-bytes-in-constructor.patch + "${FILESDIR}"/0019-alt-HUD-use-NewSmallFont-for-drawing-player-s-coordi.patch + "${FILESDIR}"/0051-Update-service.zs.patch + "${FILESDIR}"/0022-Fixed-global-TerrainDef-array-not-being-exported-cor.patch +) + +src_prepare() { + rm -rf docs/licenses || die + rm -rf libraries/{bzip2,jpeg,zlib} || die + if ! use non-free ; then + rm -rf wadsrc_bm wadsrc_extra wadsrc_widepix || die + fi + + cmake_src_prepare +} + +src_configure() { + # https://bugs.gentoo.org/858749 + filter-lto + append-flags -fno-strict-aliasing + + local mycmakeargs=( + -DBUILD_SHARED_LIBS=OFF + -DINSTALL_DOCS_PATH="${EPREFIX}/usr/share/doc/${PF}" + -DINSTALL_PK3_PATH="${EPREFIX}/usr/share/doom" + -DINSTALL_SOUNDFONT_PATH="${EPREFIX}/usr/share/doom" + -DDYN_OPENAL=OFF + -DNO_GTK="$(usex !gtk)" + -DNO_OPENAL=OFF + -DHAVE_VULKAN="$(usex vulkan)" + -DHAVE_GLES2="$(usex gles2)" + -DNO_OPENMP="$(usex !openmp)" + -DZDOOM_ENABLE_SWR="$(usex swr)" + -DBUILD_NONFREE="$(usex non-free)" + ) + + use debug || append-cppflags -DNDEBUG + use telemetry || append-cppflags -DNO_SEND_STATS + + cmake_src_configure +} + +src_install() { + newicon src/posix/zdoom.xpm "${PN}.xpm" + make_desktop_entry "${PN}" "GZDoom" "${PN}" "Game;ActionGame" + cmake_src_install +} + +pkg_postinst() { + xdg_pkg_postinst + + if ! use non-free ; then + ewarn + ewarn "GZDoom installed without non-free components." + ewarn "Note: The non-free game_support.pk3 file is needed to play" + ewarn " games natively supported by GZDoom." + ewarn "A list of games natively supported by GZDoom is available" + ewarn "on the ZDoom wiki: https://zdoom.org/wiki/IWAD" + ewarn + fi +}