From 3471594a8ffa4f541dc8d7f18c140ab12b4aea4f Mon Sep 17 00:00:00 2001 From: halx99 Date: Sun, 11 Aug 2024 21:11:35 +0800 Subject: [PATCH] Release 2.1.5 (#2076) * Fix unexpected libpng used * Fix string format incorrect for tests * Fix #1751, use coroutine control AutoTest flow * Update CHANGELOG.md * Added OpenType font (.otf) to the noCompress list. (#2077) * Update 1k & copyright notice in some sources * Move doctest to axmol 3rdparty * Fix ci * Update 1kdist to v90 * Update 1kiss.ps1 * DrawNodeV2 0.95.1 (#2079) * Rename remaining legacy engine related spells and improve code style * Update 3rdparty README.md * Fix checkReallySupportsASTC does not work on ios device reported by @BIGCATDOG in https://github.com/axmolengine/axmol/issues/2078 * Fix ci * FastRNG: add missing include for AXASSERT (#2081) * Delete unused files * Improve FileUtils - Rename FileUtils::createDirectory to FileUtils::createDirectories - Use splitpath_cb to optimize FileUtils::createDirectories - Rename FileUtils::getFileShortName to FileUtils::getPathBaseName - Rename FileUtils::getFileExtension to FileUtils::getPathExtension - Add FileUtils::getPathDirName - Add FileUtils::getPathBaseNameNoExtension - Mark all renamed FileUtils stubs old name deprecated - Mark all FileUtils offthread APIs deprecated * Update box2d to v2.4.2 * Disable /sdl checks explicitly for winuwp For axmol deprecated policy, we need disable /sdl checks explicitly to avoid compiler traits invoking deprecated functions as error * Update cppwinrt to 2.0.240405.15 * Update simdjson to 3.10.0 * Fix box2d testbed compile error * Improve file path to url * Fix FileUtils::createDirectories unix logic * axmol-cmdline: remove arch suffix for host build output directory * Update CHANGELOG.md [skip ci] --------- Co-authored-by: Dani Alias Co-authored-by: aismann Co-authored-by: smilediver --- 1k/1kiss.ps1 | 20 +- 1k/fetch.ps1 | 21 +- 1k/manifest.ps1 | 4 +- 1k/setup-msvc.ps1 | 14 +- 3rdparty/CMakeLists.txt | 41 +- 3rdparty/README.md | 15 +- 3rdparty/box2d/include/box2d/b2_body.h | 19 +- 3rdparty/box2d/include/box2d/b2_collision.h | 25 +- 3rdparty/box2d/include/box2d/b2_fixture.h | 6 + 3rdparty/box2d/include/box2d/b2_gear_joint.h | 1 + 3rdparty/box2d/include/box2d/b2_joint.h | 7 +- 3rdparty/box2d/include/box2d/b2_math.h | 14 +- .../box2d/include/box2d/b2_polygon_shape.h | 20 +- 3rdparty/box2d/include/box2d/b2_rope.h | 2 + 3rdparty/box2d/include/box2d/b2_weld_joint.h | 2 +- 3rdparty/box2d/include/box2d/b2_world.h | 3 + 3rdparty/box2d/src/collision/b2_collision.cpp | 322 ++ 3rdparty/box2d/src/collision/b2_distance.cpp | 32 +- .../box2d/src/collision/b2_polygon_shape.cpp | 163 +- 3rdparty/box2d/src/common/b2_settings.cpp | 2 +- 3rdparty/box2d/src/dynamics/b2_body.cpp | 9 +- .../box2d/src/dynamics/b2_contact_solver.cpp | 2 +- .../box2d/src/dynamics/b2_distance_joint.cpp | 2 +- 3rdparty/box2d/src/dynamics/b2_gear_joint.cpp | 16 +- 3rdparty/box2d/src/dynamics/b2_island.cpp | 2 +- .../box2d/src/dynamics/b2_mouse_joint.cpp | 4 +- 3rdparty/box2d/src/dynamics/b2_world.cpp | 2 +- 3rdparty/box2d/src/rope/b2_rope.cpp | 2 +- 3rdparty/doctest/CMakeLists.txt | 10 + .../Source => 3rdparty/doctest}/doctest.cpp | 0 .../Source => 3rdparty/doctest}/doctest.h | 0 .../Source => 3rdparty/doctest}/doctest_fwd.h | 0 3rdparty/png/CMakeLists.txt | 5 +- 3rdparty/simdjson/simdjson.cpp | 46 +- 3rdparty/simdjson/simdjson.h | 648 +++- CHANGELOG.md | 44 +- cmake/Modules/AXConfigDefine.cmake | 5 +- core/2d/DrawNode.h | 2 +- core/2d/FontAtlas.cpp | 4 +- core/2d/FontAtlas.h | 6 +- core/2d/FontFNT.h | 6 +- core/2d/Label.h | 6 +- core/2d/MenuItem.h | 2 +- core/3d/Terrain.cpp | 4 +- core/audio/AudioEngineImpl.cpp | 2 +- core/base/Config.h | 2 +- core/base/Controller.h | 6 +- core/base/Director.cpp | 8 +- core/base/EventAcceleration.h | 6 +- core/base/EventController.h | 6 +- core/base/EventCustom.h | 6 +- core/base/EventFocus.h | 6 +- core/base/EventKeyboard.h | 6 +- core/base/EventListenerAcceleration.cpp | 2 +- core/base/EventListenerAcceleration.h | 6 +- core/base/EventListenerController.cpp | 2 +- core/base/EventListenerController.h | 6 +- core/base/EventListenerCustom.h | 6 +- core/base/EventListenerFocus.cpp | 2 +- core/base/EventListenerFocus.h | 6 +- core/base/EventListenerKeyboard.cpp | 2 +- core/base/EventListenerKeyboard.h | 6 +- core/base/EventListenerMouse.cpp | 2 +- core/base/EventListenerMouse.h | 6 +- core/base/EventListenerTouch.cpp | 4 +- core/base/EventListenerTouch.h | 6 +- core/base/EventMouse.h | 6 +- core/base/EventTouch.h | 6 +- core/base/FPSImages.cpp | 6 +- core/base/FPSImages.h | 4 +- core/base/GameController.h | 6 +- core/base/Macros.h | 4 +- core/base/Properties.h | 6 +- core/base/RefPtr.h | 4 +- core/base/ScriptSupport.cpp | 2 +- core/base/UTF8.h | 2 +- core/base/Utils.cpp | 32 + core/base/Utils.h | 2 + core/base/Value.h | 6 +- core/base/axstd.h | 32 + core/math/FastRNG.h | 1 + core/math/MathUtilNeon.inl | 6 +- core/media/MediaEngine.h | 27 - core/media/VlcMediaEngine.cpp | 2 +- core/network/Downloader-curl.cpp | 2 +- core/network/Downloader-wasm.cpp | 6 +- core/network/Downloader-wasm.h | 6 +- core/network/HttpClient-wasm.h | 7 +- core/network/WebSocket-wasm.cpp | 4 +- core/network/WebSocket-wasm.h | 4 +- core/platform/FileUtils.cpp | 96 +- core/platform/FileUtils.h | 38 +- core/platform/Image.cpp | 4 +- core/platform/PlatformConfig.h | 7 +- core/platform/PlatformMacros.h | 20 +- core/platform/android/Device-android.cpp | 2 +- core/platform/android/java/build.xml | 2 +- .../java/src/org/axmol/lib/BitmapHelper.java | 2 +- .../jni/Java_org_axmol_lib_AxmolEngine.cpp | 2 +- core/platform/apple/FileUtils-apple.h | 2 +- core/platform/apple/FileUtils-apple.mm | 2 +- core/platform/ios/DirectorCaller-ios.mm | 6 +- core/platform/ios/ES3Renderer-ios.m | 2 +- core/platform/ios/cocos2d-prefix.pch | 39 - core/platform/mac/cocos2d-prefix.pch | 39 - core/platform/win32/FileUtils-win32.cpp | 55 +- core/platform/win32/FileUtils-win32.h | 2 +- core/platform/winrt/Device-winrt.cpp | 2 +- core/platform/winrt/FileUtilsWinRT.cpp | 60 +- core/platform/winrt/FileUtilsWinRT.h | 2 +- core/renderer/TextureCache.cpp | 2 +- core/renderer/backend/PixelFormatUtils.cpp | 6 +- core/renderer/backend/metal/UtilsMTL.mm | 2 +- core/renderer/backend/opengl/DriverGL.cpp | 55 +- core/renderer/backend/opengl/UtilsGL.cpp | 2 +- core/ui/UIEditBox/Mac/UIEditBoxMac.h | 4 +- core/ui/UIEditBox/Mac/UIEditBoxMac.mm | 38 +- core/ui/UIEditBox/Mac/UIMultilineTextField.h | 2 +- core/ui/UIEditBox/Mac/UIMultilineTextField.m | 44 +- core/ui/UIEditBox/Mac/UIPasswordTextField.h | 2 +- core/ui/UIEditBox/Mac/UIPasswordTextField.m | 44 +- core/ui/UIEditBox/Mac/UISingleLineTextField.h | 2 +- core/ui/UIEditBox/Mac/UISingleLineTextField.m | 42 +- core/ui/UIEditBox/Mac/UITextInput.h | 26 +- core/ui/UIEditBox/UIEditBoxImpl-winrt.cpp | 2 +- core/ui/UIEditBox/UIEditBoxImpl-winrt.h | 2 +- core/ui/UIEditBox/iOS/UIEditBoxIOS.h | 2 +- core/ui/UIEditBox/iOS/UIEditBoxIOS.mm | 40 +- .../UIEditBox/iOS/UITextField+UITextInput.h | 4 +- .../UIEditBox/iOS/UITextField+UITextInput.mm | 54 +- core/ui/UIEditBox/iOS/UITextInput.h | 24 +- .../ui/UIEditBox/iOS/UITextView+UITextInput.h | 4 +- .../UIEditBox/iOS/UITextView+UITextInput.mm | 54 +- core/ui/UILayoutComponent.h | 6 +- core/ui/UILayoutManager.h | 6 +- core/ui/UIMediaPlayer.cpp | 2 +- core/ui/UIScale9Sprite.h | 6 +- core/ui/UIWebView/UIWebViewImpl-android.cpp | 8 +- core/ui/UIWebView/UIWebViewImpl-win32.h | 6 +- .../DrawNodeEx/src/DrawNodeEx/DrawNodeEx.cpp | 958 +++--- .../DrawNodeEx/src/DrawNodeEx/DrawNodeEx.h | 102 +- extensions/README.md | 4 +- manifest.json | 2 +- .../common/proj.android/app/build.gradle | 2 +- tests/cpp-tests/Source/Box2DTestBed/test.cpp | 12 +- .../Source/Box2DTestBed/tests/dump_loader.cpp | 3 +- .../Source/DrawNodeExTest/DrawNodeExTest.cpp | 3050 ++++++++++------- .../Source/DrawNodeExTest/DrawNodeExTest.h | 268 +- .../cpp-tests/Source/SpineTest/SpineTest.cpp | 16 +- tests/cpp-tests/Source/controller.cpp | 403 +-- tests/cpp-tests/Source/controller.h | 16 +- tests/unit-tests/CMakeLists.txt | 3 +- .../Source/core/platform/FileUtilsTests.cpp | 11 +- 153 files changed, 4631 insertions(+), 2941 deletions(-) create mode 100644 3rdparty/doctest/CMakeLists.txt rename {tests/unit-tests/Source => 3rdparty/doctest}/doctest.cpp (100%) rename {tests/unit-tests/Source => 3rdparty/doctest}/doctest.h (100%) rename {tests/unit-tests/Source => 3rdparty/doctest}/doctest_fwd.h (100%) delete mode 100644 core/platform/ios/cocos2d-prefix.pch delete mode 100644 core/platform/mac/cocos2d-prefix.pch diff --git a/1k/1kiss.ps1 b/1k/1kiss.ps1 index 8d98e9f5ebd3..e5eed2c63f5a 100644 --- a/1k/1kiss.ps1 +++ b/1k/1kiss.ps1 @@ -484,6 +484,9 @@ function devtool_url($filename) { function version_eq($ver1, $ver2) { return $ver1 -eq $ver2 } +function version_like($ver1, $ver2) { + return $ver1 -like $ver2 +} # $ver2: accept x.y.z-rc1 function version_ge($ver1, $ver2) { @@ -569,6 +572,7 @@ function find_prog($name, $path = $null, $mode = 'ONLY', $cmd = $null, $params = $checkVerCond = $null $minimalVer = '' $preferredVer = '' + $wildcardVer = '' $requiredVer = $manifest[$name] if ($requiredVer) { $preferredVer = $null @@ -591,7 +595,13 @@ function find_prog($name, $path = $null, $mode = 'ONLY', $cmd = $null, $params = $checkVerCond = '$(version_in_range $foundVer $minimalVer $preferredVer)' } else { - $checkVerCond = '$(version_eq $foundVer $preferredVer)' + if (!$preferredVer.Contains('*')) { + $checkVerCond = '$(version_eq $foundVer $preferredVer)' + } else { + $wildcardVer = $preferredVer + $preferredVer = $wildcardVer.TrimEnd('.*') + $checkVerCond = '$(version_like $foundVer $wildcardVer)' + } } } } @@ -645,7 +655,6 @@ function find_prog($name, $path = $null, $mode = 'ONLY', $cmd = $null, $params = } else { if ($preferredVer) { - # if (!$silent) { $1k.println("Not found $name, needs install: $preferredVer") } $found_rets = $null, $preferredVer } else { @@ -1593,6 +1602,7 @@ elseif ($Global:is_wasm) { } $is_host_target = $Global:is_win32 -or $Global:is_linux -or $Global:is_mac +$is_host_cpu = $HOST_CPU -eq $TARGET_CPU if (!$setupOnly) { $BUILD_DIR = $null @@ -1600,7 +1610,11 @@ if (!$setupOnly) { function resolve_out_dir($prefix) { if ($is_host_target) { - $out_dir = "${prefix}${TARGET_CPU}" + if (!$is_host_cpu) { + $out_dir = "${prefix}${TARGET_CPU}" + } else { + $out_dir = $prefix.TrimEnd("_") + } } else { $out_dir = "${prefix}${TARGET_OS}" diff --git a/1k/fetch.ps1 b/1k/fetch.ps1 index 38ddab689ee9..411c38fb27a9 100644 --- a/1k/fetch.ps1 +++ b/1k/fetch.ps1 @@ -50,8 +50,8 @@ function fetch_repo($url, $name, $dest, $ext) { if ($ext -eq '.zip') { Expand-Archive -Path $out -DestinationPath $prefix -Force } - elseif ($ext -match '\.tar(\..*)?$'){ - tar xf "$out" -C $prefix + elseif ($ext -match '\.tar(\..*)?$') { + tar xvf "$out" -C $prefix } } catch { @@ -62,7 +62,22 @@ function fetch_repo($url, $name, $dest, $ext) { if (!(Test-Path $dest -PathType Container)) { $original_lib_src = Join-Path $prefix $Script:url_pkg_name if (Test-Path $original_lib_src -PathType Container) { - Rename-Item $original_lib_src $dest -Force + $tries = 0 + do { + try { + Rename-Item $original_lib_src $dest -Force + if ($?) { + break + } + } + catch { + + } + + println "fetch.ps1: rename $original_lib_src to $dest failed, try after 1 seconds" + $tries += 1 + Start-Sleep -Seconds 1 + } while ($tries -lt 10) } else { throw "fetch.ps1: the package name mismatch for $out" diff --git a/1k/manifest.ps1 b/1k/manifest.ps1 index 9396c6b31314..efbc5ee8452b 100644 --- a/1k/manifest.ps1 +++ b/1k/manifest.ps1 @@ -11,9 +11,9 @@ if ($Global:is_axmol_app -or $Global:is_axmol_engine) { $manifest['nuget'] = '5.5.1' # since 5.6.0, requires .net 4.0 $manifest['glslcc'] = '1.9.5+' - $manifest['cmake'] = '3.29.3~3.30.1+' + $manifest['cmake'] = '3.29.3~3.30.2+' $manifest['emsdk'] = '3.1.63+' - $manifest['jdk'] = '17.0.10~17.0.11+' + $manifest['jdk'] = '17.0.10~17.0.12+' } # android sdk tools diff --git a/1k/setup-msvc.ps1 b/1k/setup-msvc.ps1 index 3839c47aed90..eb06c162dbe8 100644 --- a/1k/setup-msvc.ps1 +++ b/1k/setup-msvc.ps1 @@ -1,18 +1,22 @@ param( - $ver = '14.39' + $ver = '14.39', + $arch = 'x64' ) $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" $vs_installs = ConvertFrom-Json "$(&$vswhere -version '17.0' -format 'json')" $vs_installs -$vs_installer = '${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\setup.exe' +$vs_installer = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\setup.exe" $vs_path = $vs_installs[0].installationPath -$msvc_comp_id = "Microsoft.VisualStudio.Component.VC.$ver.17.9.x86.x64" # refer to: https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022 + +$vs_arch = @{x64 = 'x86.x64'; x86 = 'x86.x64'; arm64 = 'ARM64'; arm = 'ARM' }[$arch] +$msvc_comp_id = "Microsoft.VisualStudio.Component.VC.$ver.17.9.$vs_arch" # refer to: https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2022 echo "Installing $msvc_comp_id ..." &$vs_installer modify --quiet --installPath $vs_path --add $msvc_comp_id | Out-Host -if($?) { +if ($?) { echo 'setup msvc success.' -} else { +} +else { echo 'setup msvc fail' } diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 19883e48e2bf..926789190741 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -6,16 +6,23 @@ option(AX_WITH_WEBP "Build with internal webp support" ON) option(AX_WITH_CLIPPER2 "Build with internal Clipper2 support" ON) option(AX_WITH_POLY2TRI "Build with internal poly2tri support" ON) option(AX_WITH_FASTLZ "Build with internal fastlz support" ON) -option(AX_WITH_LZ4 "Build with internal lz4 support" OFF) + option(AX_WITH_CURL "Build with internal curl support" ON) option(AX_WITH_UNZIP "Build with internal unzip support" ON) option(AX_WITH_ASTCENC "Build with internal ASTCENC support" ON) option(AX_WITH_CARES "Build with internal c-ares support" OFF) -option(AX_WITH_YAML_CPP "Build with yaml-cpp support" OFF) option(AX_WITH_KCP "Build with internal kcp support" OFF) option(AX_WITH_OBOE "Build with oboe support" OFF) option(AX_WITH_LLHTTP "Build with internal LLHTTP support" ON) +# some libs not depended by axmol +option(AX_WITH_LZ4 "Build with internal lz4 support" OFF) +option(AX_WITH_YAML_CPP "Build with yaml-cpp support" OFF) + +if(LINUX OR MACOSX OR WINDOWS) + option(AX_WITH_DOCTEST "Build with doctest support" ON) +endif() + # by default, enable ios,macOS openal-soft framework for legal license LGPL-2.1 option(ALSOFT_OSX_FRAMEWORK "" ON) @@ -319,19 +326,6 @@ if (AX_WITH_FASTLZ) ax_add_3rd(fastlz) endif() -if(AX_WITH_LZ4) - if (NOT BUILD_SHARED_LIBS) - set(lz4_tgt lz4_static) - else() - set(lz4_tgt lz4_shared) - endif() - _1kfetch(lz4) - ax_add_3rd(${lz4_SOURCE_DIR}/build/cmake TARGETS ${lz4_tgt} OPTIONS - "LZ4_BUILD_CLI OFF" - "LZ4_BUILD_LEGACY_LZ4C OFF" - ) -endif() - if(AX_WITH_CLIPPER2) ax_add_3rd(clipper2) endif() @@ -470,6 +464,23 @@ if(AX_WITH_YAML_CPP) ) endif() +if(AX_WITH_LZ4) + if (NOT BUILD_SHARED_LIBS) + set(lz4_tgt lz4_static) + else() + set(lz4_tgt lz4_shared) + endif() + _1kfetch(lz4) + ax_add_3rd(${lz4_SOURCE_DIR}/build/cmake NO_LINK TARGETS ${lz4_tgt} OPTIONS + "LZ4_BUILD_CLI OFF" + "LZ4_BUILD_LEGACY_LZ4C OFF" + ) +endif() + +if(AX_WITH_DOCTEST) + ax_add_3rd(doctest NO_LINK) +endif() + # kcp if(AX_WITH_KCP) _1kfetch(kcp) diff --git a/3rdparty/README.md b/3rdparty/README.md index bb9df631800b..3718068ea7c8 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -11,7 +11,7 @@ ## Box2D - [![Upstream](https://img.shields.io/github/v/release/erincatto/box2d?label=Upstream)](https://github.com/erincatto/box2d) -- Version: 2.4.1 +- Version: 2.4.2 - License: MIT ## Bullet @@ -22,7 +22,7 @@ ## c-ares - [![Upstream](https://img.shields.io/github/v/release/c-ares/c-ares?label=Upstream)](https://github.com/c-ares/c-ares) -- Version: 1.32.2 +- Version: 1.33.0 - License: MIT ## Chipmunk2D @@ -47,9 +47,14 @@ ## curl - [![Upstream](https://img.shields.io/github/v/release/curl/curl?label=Upstream)](https://github.com/curl/curl) -- Version: 8.8.0 +- Version: 8.9.1 - License: Curl (MIT/X) +## doctest +- [![Upstream](https://img.shields.io/github/v/release/doctest/doctest?label=Upstream)](https://github.com/doctest/doctest) +- Version: 2.4.11 +- License: MIT + ## FastLZ - Upstream: https://github.com/ariya/FastLZ - Version: git 344eb40 (121) @@ -118,7 +123,7 @@ - luajit - Upstream: https://github.com/LuaJIT/LuaJIT - - Version: 2.1-5790d25 + - Version: 2.1-04dca79 - License: MIT - tolua @@ -213,7 +218,7 @@ ## simdjson - [![Upstream](https://img.shields.io/github/v/tag/simdjson/simdjson?label=Upstream)](https://github.com/simdjson/simdjson) -- Version: 3.9.5 +- Version: 3.10.0 - License: Apache-2.0 ## stb (stb_image) diff --git a/3rdparty/box2d/include/box2d/b2_body.h b/3rdparty/box2d/include/box2d/b2_body.h index ff4adec583b0..16b2bb002c78 100644 --- a/3rdparty/box2d/include/box2d/b2_body.h +++ b/3rdparty/box2d/include/box2d/b2_body.h @@ -243,7 +243,7 @@ class B2_API b2Body /// Get the mass data of the body. /// @return a struct containing the mass, inertia and center of the body. - void GetMassData(b2MassData* data) const; + b2MassData GetMassData() const; /// Set the mass properties to override the mass properties of the fixtures. /// Note that this changes the center of mass position. @@ -377,6 +377,7 @@ class B2_API b2Body /// Get the user data pointer that was provided in the body definition. b2BodyUserData& GetUserData(); + const b2BodyUserData& GetUserData() const; /// Get the parent world of this body. b2World* GetWorld(); @@ -401,7 +402,6 @@ class B2_API b2Body friend class b2PrismaticJoint; friend class b2PulleyJoint; friend class b2RevoluteJoint; - friend class b2RopeJoint; friend class b2WeldJoint; friend class b2WheelJoint; @@ -548,11 +548,13 @@ inline float b2Body::GetInertia() const return m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); } -inline void b2Body::GetMassData(b2MassData* data) const +inline b2MassData b2Body::GetMassData() const { - data->mass = m_mass; - data->I = m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); - data->center = m_sweep.localCenter; + b2MassData data; + data.mass = m_mass; + data.I = m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); + data.center = m_sweep.localCenter; + return data; } inline b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint) const @@ -733,6 +735,11 @@ inline b2BodyUserData& b2Body::GetUserData() return m_userData; } +inline const b2BodyUserData& b2Body::GetUserData() const +{ + return m_userData; +} + inline void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake) { if (m_type != b2_dynamicBody) diff --git a/3rdparty/box2d/include/box2d/b2_collision.h b/3rdparty/box2d/include/box2d/b2_collision.h index 4c4592061291..055704e7c8d6 100644 --- a/3rdparty/box2d/include/box2d/b2_collision.h +++ b/3rdparty/box2d/include/box2d/b2_collision.h @@ -244,7 +244,7 @@ B2_API void b2CollideEdgeAndCircle(b2Manifold* manifold, /// Compute the collision manifold between an edge and a polygon. B2_API void b2CollideEdgeAndPolygon(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, - const b2PolygonShape* circleB, const b2Transform& xfB); + const b2PolygonShape* polygonB, const b2Transform& xfB); /// Clipping for contact manifolds. B2_API int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], @@ -255,6 +255,29 @@ B2_API bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, const b2Shape* shapeB, int32 indexB, const b2Transform& xfA, const b2Transform& xfB); +/// Convex hull used for polygon collision +struct b2Hull +{ + b2Vec2 points[b2_maxPolygonVertices]; + int32 count; +}; + +/// Compute the convex hull of a set of points. Returns an empty hull if it fails. +/// Some failure cases: +/// - all points very close together +/// - all points on a line +/// - less than 3 points +/// - more than b2_maxPolygonVertices points +/// This welds close points and removes collinear points. +b2Hull b2ComputeHull(const b2Vec2* points, int32 count); + +/// This determines if a hull is valid. Checks for: +/// - convexity +/// - collinear points +/// This is expensive and should not be called at runtime. +bool b2ValidateHull(const b2Hull& hull); + + // ---------------- Inline Functions ------------------------------------------ inline bool b2AABB::IsValid() const diff --git a/3rdparty/box2d/include/box2d/b2_fixture.h b/3rdparty/box2d/include/box2d/b2_fixture.h index f12789b5e04d..47d321df5ec1 100644 --- a/3rdparty/box2d/include/box2d/b2_fixture.h +++ b/3rdparty/box2d/include/box2d/b2_fixture.h @@ -157,6 +157,7 @@ class B2_API b2Fixture /// Get the user data that was assigned in the fixture definition. Use this to /// store your application specific data. b2FixtureUserData& GetUserData(); + const b2FixtureUserData& GetUserData() const; /// Test a point for containment in this fixture. /// @param p a point in world coordinates. @@ -280,6 +281,11 @@ inline b2FixtureUserData& b2Fixture::GetUserData() return m_userData; } +inline const b2FixtureUserData& b2Fixture::GetUserData() const +{ + return m_userData; +} + inline b2Body* b2Fixture::GetBody() { return m_body; diff --git a/3rdparty/box2d/include/box2d/b2_gear_joint.h b/3rdparty/box2d/include/box2d/b2_gear_joint.h index 1c40687a0845..a7e4fa5197d7 100644 --- a/3rdparty/box2d/include/box2d/b2_gear_joint.h +++ b/3rdparty/box2d/include/box2d/b2_gear_joint.h @@ -114,6 +114,7 @@ class B2_API b2GearJoint : public b2Joint float m_constant; float m_ratio; + float m_tolerance; float m_impulse; diff --git a/3rdparty/box2d/include/box2d/b2_joint.h b/3rdparty/box2d/include/box2d/b2_joint.h index 2b4d586cd2f3..586b13ad1866 100644 --- a/3rdparty/box2d/include/box2d/b2_joint.h +++ b/3rdparty/box2d/include/box2d/b2_joint.h @@ -44,7 +44,6 @@ enum b2JointType e_wheelJoint, e_weldJoint, e_frictionJoint, - e_ropeJoint, e_motorJoint }; @@ -138,6 +137,7 @@ class B2_API b2Joint /// Get the user data pointer. b2JointUserData& GetUserData(); + const b2JointUserData& GetUserData() const; /// Short-cut function to determine if either body is enabled. bool IsEnabled() const; @@ -220,6 +220,11 @@ inline b2JointUserData& b2Joint::GetUserData() return m_userData; } +inline const b2JointUserData& b2Joint::GetUserData() const +{ + return m_userData; +} + inline bool b2Joint::GetCollideConnected() const { return m_collideConnected; diff --git a/3rdparty/box2d/include/box2d/b2_math.h b/3rdparty/box2d/include/box2d/b2_math.h index 479e667be391..c98cf35dfcb2 100644 --- a/3rdparty/box2d/include/box2d/b2_math.h +++ b/3rdparty/box2d/include/box2d/b2_math.h @@ -41,7 +41,7 @@ inline bool b2IsValid(float x) struct B2_API b2Vec2 { /// Default constructor does nothing (for performance). - b2Vec2() {} + b2Vec2() = default; /// Construct using coordinates. b2Vec2(float xIn, float yIn) : x(xIn), y(yIn) {} @@ -132,7 +132,7 @@ struct B2_API b2Vec2 struct B2_API b2Vec3 { /// Default constructor does nothing (for performance). - b2Vec3() {} + b2Vec3() = default; /// Construct using coordinates. b2Vec3(float xIn, float yIn, float zIn) : x(xIn), y(yIn), z(zIn) {} @@ -171,7 +171,7 @@ struct B2_API b2Vec3 struct B2_API b2Mat22 { /// The default constructor does nothing (for performance). - b2Mat22() {} + b2Mat22() = default; /// Construct this matrix using columns. b2Mat22(const b2Vec2& c1, const b2Vec2& c2) @@ -245,7 +245,7 @@ struct B2_API b2Mat22 struct B2_API b2Mat33 { /// The default constructor does nothing (for performance). - b2Mat33() {} + b2Mat33() = default; /// Construct this matrix using columns. b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3) @@ -286,7 +286,7 @@ struct B2_API b2Mat33 /// Rotation struct B2_API b2Rot { - b2Rot() {} + b2Rot() = default; /// Initialize from an angle in radians explicit b2Rot(float angle) @@ -338,7 +338,7 @@ struct B2_API b2Rot struct B2_API b2Transform { /// The default constructor does nothing. - b2Transform() {} + b2Transform() = default; /// Initialize using a position vector and a rotation. b2Transform(const b2Vec2& position, const b2Rot& rotation) : p(position), q(rotation) {} @@ -367,6 +367,8 @@ struct B2_API b2Transform /// we must interpolate the center of mass position. struct B2_API b2Sweep { + b2Sweep() = default; + /// Get the interpolated transform at a specific time. /// @param transform the output transform /// @param beta is a factor in [0,1], where 0 indicates alpha0. diff --git a/3rdparty/box2d/include/box2d/b2_polygon_shape.h b/3rdparty/box2d/include/box2d/b2_polygon_shape.h index 5a4e563f84ce..8a208b72b66d 100644 --- a/3rdparty/box2d/include/box2d/b2_polygon_shape.h +++ b/3rdparty/box2d/include/box2d/b2_polygon_shape.h @@ -25,6 +25,8 @@ #include "b2_api.h" #include "b2_shape.h" +struct b2Hull; + /// A solid convex polygon. It is assumed that the interior of the polygon is to /// the left of each edge. /// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices. @@ -43,9 +45,13 @@ class B2_API b2PolygonShape : public b2Shape /// Create a convex hull from the given array of local points. /// The count must be in the range [3, b2_maxPolygonVertices]. /// @warning the points may be re-ordered, even if they form a convex polygon - /// @warning collinear points are handled but not removed. Collinear points - /// may lead to poor stacking behavior. - void Set(const b2Vec2* points, int32 count); + /// @warning if this fails then the polygon is invalid + /// @returns true if valid + bool Set(const b2Vec2* points, int32 count); + + /// Create a polygon from a given convex hull (see b2ComputeHull). + /// @warning the hull must be valid or this will crash or have unexpected behavior + void Set(const b2Hull& hull); /// Build vertices to represent an axis-aligned box centered on the local origin. /// @param hx the half-width. @@ -84,12 +90,4 @@ class B2_API b2PolygonShape : public b2Shape int32 m_count; }; -inline b2PolygonShape::b2PolygonShape() -{ - m_type = e_polygon; - m_radius = b2_polygonRadius; - m_count = 0; - m_centroid.SetZero(); -} - #endif diff --git a/3rdparty/box2d/include/box2d/b2_rope.h b/3rdparty/box2d/include/box2d/b2_rope.h index 47f5fc44207d..0c4f819595e7 100644 --- a/3rdparty/box2d/include/box2d/b2_rope.h +++ b/3rdparty/box2d/include/box2d/b2_rope.h @@ -55,6 +55,8 @@ struct B2_API b2RopeTuning bendingModel = b2_pbdAngleBendingModel; damping = 0.0f; stretchStiffness = 1.0f; + stretchHertz = 1.0f; + stretchDamping = 0.0f; bendStiffness = 0.5f; bendHertz = 1.0f; bendDamping = 0.0f; diff --git a/3rdparty/box2d/include/box2d/b2_weld_joint.h b/3rdparty/box2d/include/box2d/b2_weld_joint.h index f226c8a46423..38501f20ab05 100644 --- a/3rdparty/box2d/include/box2d/b2_weld_joint.h +++ b/3rdparty/box2d/include/box2d/b2_weld_joint.h @@ -85,7 +85,7 @@ class B2_API b2WeldJoint : public b2Joint float GetReferenceAngle() const { return m_referenceAngle; } /// Set/get stiffness in N*m - void SetStiffness(float hz) { m_stiffness = hz; } + void SetStiffness(float stiffness) { m_stiffness = stiffness; } float GetStiffness() const { return m_stiffness; } /// Set/get damping in N*m*s diff --git a/3rdparty/box2d/include/box2d/b2_world.h b/3rdparty/box2d/include/box2d/b2_world.h index 57d37096c419..afd73bd4657a 100644 --- a/3rdparty/box2d/include/box2d/b2_world.h +++ b/3rdparty/box2d/include/box2d/b2_world.h @@ -221,6 +221,9 @@ class B2_API b2World friend class b2ContactManager; friend class b2Controller; + b2World(const b2World&) = delete; + void operator=(const b2World&) = delete; + void Solve(const b2TimeStep& step); void SolveTOI(const b2TimeStep& step); diff --git a/3rdparty/box2d/src/collision/b2_collision.cpp b/3rdparty/box2d/src/collision/b2_collision.cpp index 8a0501be3509..750bff00fe7d 100644 --- a/3rdparty/box2d/src/collision/b2_collision.cpp +++ b/3rdparty/box2d/src/collision/b2_collision.cpp @@ -256,3 +256,325 @@ bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, return output.distance < 10.0f * b2_epsilon; } + +// quickhull recursion +static b2Hull b2RecurseHull(b2Vec2 p1, b2Vec2 p2, b2Vec2* ps, int32 count) +{ + b2Hull hull; + hull.count = 0; + + if (count == 0) + { + return hull; + } + + // create an edge vector pointing from p1 to p2 + b2Vec2 e = p2 - p1; + e.Normalize(); + + // discard points left of e and find point furthest to the right of e + b2Vec2 rightPoints[b2_maxPolygonVertices]{}; + int32 rightCount = 0; + + int32 bestIndex = 0; + float bestDistance = b2Cross(ps[bestIndex] - p1, e); + if (bestDistance > 0.0f) + { + rightPoints[rightCount++] = ps[bestIndex]; + } + + for (int32 i = 1; i < count; ++i) + { + float distance = b2Cross(ps[i] - p1, e); + if (distance > bestDistance) + { + bestIndex = i; + bestDistance = distance; + } + + if (distance > 0.0f) + { + rightPoints[rightCount++] = ps[i]; + } + } + + if (bestDistance < 2.0f * b2_linearSlop) + { + return hull; + } + + b2Vec2 bestPoint = ps[bestIndex]; + + // compute hull to the right of p1-bestPoint + b2Hull hull1 = b2RecurseHull(p1, bestPoint, rightPoints, rightCount); + + // compute hull to the right of bestPoint-p2 + b2Hull hull2 = b2RecurseHull(bestPoint, p2, rightPoints, rightCount); + + // stich together hulls + for (int32 i = 0; i < hull1.count; ++i) + { + hull.points[hull.count++] = hull1.points[i]; + } + + hull.points[hull.count++] = bestPoint; + + for (int32 i = 0; i < hull2.count; ++i) + { + hull.points[hull.count++] = hull2.points[i]; + } + + b2Assert(hull.count < b2_maxPolygonVertices); + + return hull; +} + +// quickhull algorithm +// - merges vertices based on b2_linearSlop +// - removes collinear points using b2_linearSlop +// - returns an empty hull if it fails +b2Hull b2ComputeHull(const b2Vec2* points, int32 count) +{ + b2Hull hull; + hull.count = 0; + + if (count < 3 || count > b2_maxPolygonVertices) + { + // check your data + return hull; + } + + count = b2Min(count, b2_maxPolygonVertices); + + b2AABB aabb = { {b2_maxFloat, b2_maxFloat}, {-b2_maxFloat, -b2_maxFloat} }; + + // Perform aggressive point welding. First point always remains. + // Also compute the bounding box for later. + b2Vec2 ps[b2_maxPolygonVertices]; + int32 n = 0; + const float tolSqr = 16.0f * b2_linearSlop * b2_linearSlop; + for (int32 i = 0; i < count; ++i) + { + aabb.lowerBound = b2Min(aabb.lowerBound, points[i]); + aabb.upperBound = b2Max(aabb.upperBound, points[i]); + + b2Vec2 vi = points[i]; + + bool unique = true; + for (int32 j = 0; j < i; ++j) + { + b2Vec2 vj = points[j]; + + float distSqr = b2DistanceSquared(vi, vj); + if (distSqr < tolSqr) + { + unique = false; + break; + } + } + + if (unique) + { + ps[n++] = vi; + } + } + + if (n < 3) + { + // all points very close together, check your data and check your scale + return hull; + } + + // Find an extreme point as the first point on the hull + b2Vec2 c = aabb.GetCenter(); + int32 i1 = 0; + float dsq1 = b2DistanceSquared(c, ps[i1]); + for (int32 i = 1; i < n; ++i) + { + float dsq = b2DistanceSquared(c, ps[i]); + if (dsq > dsq1) + { + i1 = i; + dsq1 = dsq; + } + } + + // remove p1 from working set + b2Vec2 p1 = ps[i1]; + ps[i1] = ps[n - 1]; + n = n - 1; + + int32 i2 = 0; + float dsq2 = b2DistanceSquared(p1, ps[i2]); + for (int32 i = 1; i < n; ++i) + { + float dsq = b2DistanceSquared(p1, ps[i]); + if (dsq > dsq2) + { + i2 = i; + dsq2 = dsq; + } + } + + // remove p2 from working set + b2Vec2 p2 = ps[i2]; + ps[i2] = ps[n - 1]; + n = n - 1; + + // split the points into points that are left and right of the line p1-p2. + b2Vec2 rightPoints[b2_maxPolygonVertices - 2]; + int32 rightCount = 0; + + b2Vec2 leftPoints[b2_maxPolygonVertices - 2]; + int32 leftCount = 0; + + b2Vec2 e = p2 - p1; + e.Normalize(); + + for (int32 i = 0; i < n; ++i) + { + float d = b2Cross(ps[i] - p1, e); + + // slop used here to skip points that are very close to the line p1-p2 + if (d >= 2.0f * b2_linearSlop) + { + rightPoints[rightCount++] = ps[i]; + } + else if (d <= -2.0f * b2_linearSlop) + { + leftPoints[leftCount++] = ps[i]; + } + } + + // compute hulls on right and left + b2Hull hull1 = b2RecurseHull(p1, p2, rightPoints, rightCount); + b2Hull hull2 = b2RecurseHull(p2, p1, leftPoints, leftCount); + + if (hull1.count == 0 && hull2.count == 0) + { + // all points collinear + return hull; + } + + // stitch hulls together, preserving CCW winding order + hull.points[hull.count++] = p1; + + for (int32 i = 0; i < hull1.count; ++i) + { + hull.points[hull.count++] = hull1.points[i]; + } + + hull.points[hull.count++] = p2; + + for (int32 i = 0; i < hull2.count; ++i) + { + hull.points[hull.count++] = hull2.points[i]; + } + + b2Assert(hull.count <= b2_maxPolygonVertices); + + // merge collinear + bool searching = true; + while (searching && hull.count > 2) + { + searching = false; + + for (int32 i = 0; i < hull.count; ++i) + { + int32 i1 = i; + int32 i2 = (i + 1) % hull.count; + int32 i3 = (i + 2) % hull.count; + + b2Vec2 p1 = hull.points[i1]; + b2Vec2 p2 = hull.points[i2]; + b2Vec2 p3 = hull.points[i3]; + + b2Vec2 e = p3 - p1; + e.Normalize(); + + b2Vec2 v = p2 - p1; + float distance = b2Cross(p2 - p1, e); + if (distance <= 2.0f * b2_linearSlop) + { + // remove midpoint from hull + for (int32 j = i2; j < hull.count - 1; ++j) + { + hull.points[j] = hull.points[j + 1]; + } + hull.count -= 1; + + // continue searching for collinear points + searching = true; + + break; + } + } + } + + if (hull.count < 3) + { + // all points collinear, shouldn't be reached since this was validated above + hull.count = 0; + } + + return hull; +} + +bool b2ValidateHull(const b2Hull& hull) +{ + if (hull.count < 3 || b2_maxPolygonVertices < hull.count) + { + return false; + } + + // test that every point is behind every edge + for (int32 i = 0; i < hull.count; ++i) + { + // create an edge vector + int32 i1 = i; + int32 i2 = i < hull.count - 1 ? i1 + 1 : 0; + b2Vec2 p = hull.points[i1]; + b2Vec2 e = hull.points[i2] - p; + e.Normalize(); + + for (int32 j = 0; j < hull.count; ++j) + { + // skip points that subtend the current edge + if (j == i1 || j == i2) + { + continue; + } + + float distance = b2Cross(hull.points[j] - p, e); + if (distance >= 0.0f) + { + return false; + } + } + } + + // test for collinear points + for (int32 i = 0; i < hull.count; ++i) + { + int32 i1 = i; + int32 i2 = (i + 1) % hull.count; + int32 i3 = (i + 2) % hull.count; + + b2Vec2 p1 = hull.points[i1]; + b2Vec2 p2 = hull.points[i2]; + b2Vec2 p3 = hull.points[i3]; + + b2Vec2 e = p3 - p1; + e.Normalize(); + + b2Vec2 v = p2 - p1; + float distance = b2Cross(p2 - p1, e); + if (distance <= b2_linearSlop) + { + // p1-p2-p3 are collinear + return false; + } + } + + return true; +} diff --git a/3rdparty/box2d/src/collision/b2_distance.cpp b/3rdparty/box2d/src/collision/b2_distance.cpp index 244132408a0c..16fa3cc3d986 100644 --- a/3rdparty/box2d/src/collision/b2_distance.cpp +++ b/3rdparty/box2d/src/collision/b2_distance.cpp @@ -569,31 +569,29 @@ void b2Distance(b2DistanceOutput* output, // Cache the simplex. simplex.WriteCache(cache); - // Apply radii if requested. + // Apply radii if requested if (input->useRadii) { - float rA = proxyA->m_radius; - float rB = proxyB->m_radius; - - if (output->distance > rA + rB && output->distance > b2_epsilon) - { - // Shapes are still no overlapped. - // Move the witness points to the outer surface. - output->distance -= rA + rB; - b2Vec2 normal = output->pointB - output->pointA; - normal.Normalize(); - output->pointA += rA * normal; - output->pointB -= rB * normal; - } - else + if (output->distance < b2_epsilon) { - // Shapes are overlapped when radii are considered. - // Move the witness points to the middle. + // Shapes are too close to safely compute normal b2Vec2 p = 0.5f * (output->pointA + output->pointB); output->pointA = p; output->pointB = p; output->distance = 0.0f; } + else + { + // Keep closest points on perimeter even if overlapped, this way + // the points move smoothly. + float rA = proxyA->m_radius; + float rB = proxyB->m_radius; + b2Vec2 normal = output->pointB - output->pointA; + normal.Normalize(); + output->distance = b2Max(0.0f, output->distance - rA - rB); + output->pointA += rA * normal; + output->pointB -= rB * normal; + } } } diff --git a/3rdparty/box2d/src/collision/b2_polygon_shape.cpp b/3rdparty/box2d/src/collision/b2_polygon_shape.cpp index 368fb801ff65..165919b46fa7 100644 --- a/3rdparty/box2d/src/collision/b2_polygon_shape.cpp +++ b/3rdparty/box2d/src/collision/b2_polygon_shape.cpp @@ -25,6 +25,14 @@ #include +b2PolygonShape::b2PolygonShape() +{ + m_type = e_polygon; + m_radius = b2_polygonRadius; + m_count = 0; + m_centroid.SetZero(); +} + b2Shape* b2PolygonShape::Clone(b2BlockAllocator* allocator) const { void* mem = allocator->Allocate(sizeof(b2PolygonShape)); @@ -115,128 +123,37 @@ static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count) return c; } -void b2PolygonShape::Set(const b2Vec2* vertices, int32 count) +bool b2PolygonShape::Set(const b2Vec2* vertices, int32 count) { - b2Assert(3 <= count && count <= b2_maxPolygonVertices); - if (count < 3) - { - SetAsBox(1.0f, 1.0f); - return; - } - - int32 n = b2Min(count, b2_maxPolygonVertices); + b2Hull hull = b2ComputeHull(vertices, count); - // Perform welding and copy vertices into local buffer. - b2Vec2 ps[b2_maxPolygonVertices]; - int32 tempCount = 0; - for (int32 i = 0; i < n; ++i) + if (hull.count < 3) { - b2Vec2 v = vertices[i]; - - bool unique = true; - for (int32 j = 0; j < tempCount; ++j) - { - if (b2DistanceSquared(v, ps[j]) < ((0.5f * b2_linearSlop) * (0.5f * b2_linearSlop))) - { - unique = false; - break; - } - } - - if (unique) - { - ps[tempCount++] = v; - } + return false; } - n = tempCount; - if (n < 3) - { - // Polygon is degenerate. - b2Assert(false); - SetAsBox(1.0f, 1.0f); - return; - } - - // Create the convex hull using the Gift wrapping algorithm - // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm - - // Find the right most point on the hull - int32 i0 = 0; - float x0 = ps[0].x; - for (int32 i = 1; i < n; ++i) - { - float x = ps[i].x; - if (x > x0 || (x == x0 && ps[i].y < ps[i0].y)) - { - i0 = i; - x0 = x; - } - } - - int32 hull[b2_maxPolygonVertices]; - int32 m = 0; - int32 ih = i0; - - for (;;) - { - b2Assert(m < b2_maxPolygonVertices); - hull[m] = ih; - - int32 ie = 0; - for (int32 j = 1; j < n; ++j) - { - if (ie == ih) - { - ie = j; - continue; - } - - b2Vec2 r = ps[ie] - ps[hull[m]]; - b2Vec2 v = ps[j] - ps[hull[m]]; - float c = b2Cross(r, v); - if (c < 0.0f) - { - ie = j; - } - - // Collinearity check - if (c == 0.0f && v.LengthSquared() > r.LengthSquared()) - { - ie = j; - } - } + Set(hull); - ++m; - ih = ie; + return true; +} - if (ie == i0) - { - break; - } - } - - if (m < 3) - { - // Polygon is degenerate. - b2Assert(false); - SetAsBox(1.0f, 1.0f); - return; - } +void b2PolygonShape::Set(const b2Hull& hull) +{ + b2Assert(hull.count >= 3); - m_count = m; + m_count = hull.count; - // Copy vertices. - for (int32 i = 0; i < m; ++i) + // Copy vertices + for (int32 i = 0; i < hull.count; ++i) { - m_vertices[i] = ps[hull[i]]; + m_vertices[i] = hull.points[i]; } // Compute normals. Ensure the edges have non-zero length. - for (int32 i = 0; i < m; ++i) + for (int32 i = 0; i < m_count; ++i) { int32 i1 = i; - int32 i2 = i + 1 < m ? i + 1 : 0; + int32 i2 = i + 1 < m_count ? i + 1 : 0; b2Vec2 edge = m_vertices[i2] - m_vertices[i1]; b2Assert(edge.LengthSquared() > b2_epsilon * b2_epsilon); m_normals[i] = b2Cross(edge, 1.0f); @@ -244,7 +161,7 @@ void b2PolygonShape::Set(const b2Vec2* vertices, int32 count) } // Compute the polygon centroid. - m_centroid = ComputeCentroid(m_vertices, m); + m_centroid = ComputeCentroid(m_vertices, m_count); } bool b2PolygonShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const @@ -432,28 +349,18 @@ void b2PolygonShape::ComputeMass(b2MassData* massData, float density) const bool b2PolygonShape::Validate() const { - for (int32 i = 0; i < m_count; ++i) + if (m_count < 3 || b2_maxPolygonVertices < m_count) { - int32 i1 = i; - int32 i2 = i < m_count - 1 ? i1 + 1 : 0; - b2Vec2 p = m_vertices[i1]; - b2Vec2 e = m_vertices[i2] - p; - - for (int32 j = 0; j < m_count; ++j) - { - if (j == i1 || j == i2) - { - continue; - } + return false; + } - b2Vec2 v = m_vertices[j] - p; - float c = b2Cross(e, v); - if (c < 0.0f) - { - return false; - } - } + b2Hull hull; + for (int32 i = 0; i < m_count; ++i) + { + hull.points[i] = m_vertices[i]; } - return true; + hull.count = m_count; + + return b2ValidateHull(hull); } diff --git a/3rdparty/box2d/src/common/b2_settings.cpp b/3rdparty/box2d/src/common/b2_settings.cpp index 9b66769ac19f..dde28bb3abd7 100644 --- a/3rdparty/box2d/src/common/b2_settings.cpp +++ b/3rdparty/box2d/src/common/b2_settings.cpp @@ -27,7 +27,7 @@ #include #include -b2Version b2_version = {2, 4, 0}; +b2Version b2_version = {2, 4, 1}; // Memory allocators. Modify these to use your own allocator. void* b2Alloc_Default(int32 size) diff --git a/3rdparty/box2d/src/dynamics/b2_body.cpp b/3rdparty/box2d/src/dynamics/b2_body.cpp index 574666442966..00f36856dde1 100644 --- a/3rdparty/box2d/src/dynamics/b2_body.cpp +++ b/3rdparty/box2d/src/dynamics/b2_body.cpp @@ -244,6 +244,8 @@ void b2Body::DestroyFixture(b2Fixture* fixture) // You tried to remove a shape that is not attached to this body. b2Assert(found); + const float density = fixture->m_density; + // Destroy any contacts associated with the fixture. b2ContactEdge* edge = m_contactList; while (edge) @@ -278,8 +280,11 @@ void b2Body::DestroyFixture(b2Fixture* fixture) --m_fixtureCount; - // Reset the mass data. - ResetMassData(); + // Reset the mass data + if (density > 0.0f) + { + ResetMassData(); + } } void b2Body::ResetMassData() diff --git a/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp b/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp index e6f432a2365c..d6c08fb17972 100644 --- a/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp +++ b/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp @@ -775,7 +775,7 @@ bool b2ContactSolver::SolveTOIPositionConstraints(int32 toiIndexA, int32 toiInde } float mB = 0.0f; - float iB = 0.; + float iB = 0.0f; if (indexB == toiIndexA || indexB == toiIndexB) { mB = pc->invMassB; diff --git a/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp b/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp index e54dbaf4f774..221309ef00ab 100644 --- a/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp +++ b/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp @@ -392,7 +392,7 @@ void b2DistanceJoint::Draw(b2Draw* draw) const b2Vec2 pB = b2Mul(xfB, m_localAnchorB); b2Vec2 axis = pB - pA; - float length = axis.Normalize(); + axis.Normalize(); b2Color c1(0.7f, 0.7f, 0.7f); b2Color c2(0.3f, 0.9f, 0.3f); diff --git a/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp b/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp index ff36d3e10da8..5fb547245e93 100644 --- a/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp +++ b/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp @@ -82,6 +82,9 @@ b2GearJoint::b2GearJoint(const b2GearJointDef* def) m_localAxisC.SetZero(); coordinateA = aA - aC - m_referenceAngleA; + + // position error is measured in radians + m_tolerance = b2_angularSlop; } else { @@ -94,6 +97,9 @@ b2GearJoint::b2GearJoint(const b2GearJointDef* def) b2Vec2 pC = m_localAnchorC; b2Vec2 pA = b2MulT(xfC.q, b2Mul(xfA.q, m_localAnchorA) + (xfA.p - xfC.p)); coordinateA = b2Dot(pA - pC, m_localAxisC); + + // position error is measured in meters + m_tolerance = b2_linearSlop; } m_bodyD = m_joint2->GetBodyA(); @@ -291,8 +297,6 @@ bool b2GearJoint::SolvePositionConstraints(const b2SolverData& data) b2Rot qA(aA), qB(aB), qC(aC), qD(aD); - float linearError = 0.0f; - float coordinateA, coordinateB; b2Vec2 JvAC, JvBD; @@ -373,8 +377,12 @@ bool b2GearJoint::SolvePositionConstraints(const b2SolverData& data) data.positions[m_indexD].c = cD; data.positions[m_indexD].a = aD; - // TODO_ERIN not implemented - return linearError < b2_linearSlop; + if (b2Abs(C) < m_tolerance) + { + return true; + } + + return false; } b2Vec2 b2GearJoint::GetAnchorA() const diff --git a/3rdparty/box2d/src/dynamics/b2_island.cpp b/3rdparty/box2d/src/dynamics/b2_island.cpp index 48d89a850fb6..34413056b1f4 100644 --- a/3rdparty/box2d/src/dynamics/b2_island.cpp +++ b/3rdparty/box2d/src/dynamics/b2_island.cpp @@ -29,8 +29,8 @@ #include "box2d/b2_timer.h" #include "box2d/b2_world.h" +#include "b2_contact_solver.h" #include "b2_island.h" -#include "dynamics/b2_contact_solver.h" /* Position Correction Notes diff --git a/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp b/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp index 1ea6dd42034c..dbc214fae749 100644 --- a/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp +++ b/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp @@ -84,8 +84,6 @@ void b2MouseJoint::InitVelocityConstraints(const b2SolverData& data) b2Rot qB(aB); - float mass = m_bodyB->GetMass(); - float d = m_damping; float k = m_stiffness; @@ -118,7 +116,7 @@ void b2MouseJoint::InitVelocityConstraints(const b2SolverData& data) m_C *= m_beta; // Cheat with some damping - wB *= 0.98f; + wB *= b2Max(0.0f, 1.0f - 0.02f * (60.0f * data.step.dt)); if (data.step.warmStarting) { diff --git a/3rdparty/box2d/src/dynamics/b2_world.cpp b/3rdparty/box2d/src/dynamics/b2_world.cpp index 1a0f7913124e..78ec084c800b 100644 --- a/3rdparty/box2d/src/dynamics/b2_world.cpp +++ b/3rdparty/box2d/src/dynamics/b2_world.cpp @@ -515,7 +515,7 @@ void b2World::Solve(const b2TimeStep& step) b2Body* other = je->other; - // Don't simulate joints connected to diabled bodies. + // Don't simulate joints connected to disabled bodies. if (other->IsEnabled() == false) { continue; diff --git a/3rdparty/box2d/src/rope/b2_rope.cpp b/3rdparty/box2d/src/rope/b2_rope.cpp index d2425a2af48f..71fbe79ee9f7 100644 --- a/3rdparty/box2d/src/rope/b2_rope.cpp +++ b/3rdparty/box2d/src/rope/b2_rope.cpp @@ -243,7 +243,7 @@ void b2Rope::SetTuning(const b2RopeTuning& tuning) void b2Rope::Step(float dt, int32 iterations, const b2Vec2& position) { - if (dt == 0.0) + if (dt == 0.0f) { return; } diff --git a/3rdparty/doctest/CMakeLists.txt b/3rdparty/doctest/CMakeLists.txt new file mode 100644 index 000000000000..2480de13de7a --- /dev/null +++ b/3rdparty/doctest/CMakeLists.txt @@ -0,0 +1,10 @@ +set(lib_name doctest) +set(target_name ${lib_name}) + +project(${lib_name}) + +add_library(${target_name} STATIC + doctest.cpp +) + +target_include_directories(${target_name} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) diff --git a/tests/unit-tests/Source/doctest.cpp b/3rdparty/doctest/doctest.cpp similarity index 100% rename from tests/unit-tests/Source/doctest.cpp rename to 3rdparty/doctest/doctest.cpp diff --git a/tests/unit-tests/Source/doctest.h b/3rdparty/doctest/doctest.h similarity index 100% rename from tests/unit-tests/Source/doctest.h rename to 3rdparty/doctest/doctest.h diff --git a/tests/unit-tests/Source/doctest_fwd.h b/3rdparty/doctest/doctest_fwd.h similarity index 100% rename from tests/unit-tests/Source/doctest_fwd.h rename to 3rdparty/doctest/doctest_fwd.h diff --git a/3rdparty/png/CMakeLists.txt b/3rdparty/png/CMakeLists.txt index 76b96150ce9d..66455e53cdb6 100644 --- a/3rdparty/png/CMakeLists.txt +++ b/3rdparty/png/CMakeLists.txt @@ -52,7 +52,10 @@ add_library(${target_name} STATIC ${libpng_intel_sources} ) -set(PNG_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE STRING "png include dir" FORCE) +# cmake builtin FindPNG.cmake detect cached variable PNG_PNG_INCLUDE_DIR +set(PNG_PNG_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "png include dir" FORCE) + +set(PNG_INCLUDE_DIR "${PNG_PNG_INCLUDE_DIR}" CACHE INTERNAL "" FORCE) target_include_directories(${target_name} PUBLIC "${PNG_INCLUDE_DIR}") if(_PNG_ISA_SIMD) diff --git a/3rdparty/simdjson/simdjson.cpp b/3rdparty/simdjson/simdjson.cpp index 375b9b78445e..b5dd72438532 100644 --- a/3rdparty/simdjson/simdjson.cpp +++ b/3rdparty/simdjson/simdjson.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2024-07-04 16:26:22 -0400. Do not edit! */ +/* auto-generated on 2024-08-01 09:31:50 -0400. Do not edit! */ /* including simdjson.cpp: */ /* begin file simdjson.cpp */ #define SIMDJSON_SRC_SIMDJSON_CPP @@ -40,6 +40,16 @@ #endif #endif +// C++ 23 +#if !defined(SIMDJSON_CPLUSPLUS23) && (SIMDJSON_CPLUSPLUS >= 202302L) +#define SIMDJSON_CPLUSPLUS23 1 +#endif + +// C++ 20 +#if !defined(SIMDJSON_CPLUSPLUS20) && (SIMDJSON_CPLUSPLUS >= 202002L) +#define SIMDJSON_CPLUSPLUS20 1 +#endif + // C++ 17 #if !defined(SIMDJSON_CPLUSPLUS17) && (SIMDJSON_CPLUSPLUS >= 201703L) #define SIMDJSON_CPLUSPLUS17 1 @@ -5954,7 +5964,7 @@ class dom_parser_implementation { * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. * @@ -5971,7 +5981,7 @@ class dom_parser_implementation { * Unescape a NON-valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. * @@ -12482,7 +12492,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -13357,7 +13367,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -18701,7 +18711,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -19576,7 +19586,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -24913,7 +24923,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -25788,7 +25798,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -31396,7 +31406,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -32271,7 +32281,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -38453,7 +38463,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -39328,7 +39338,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -44477,7 +44487,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -45352,7 +45362,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -50492,7 +50502,7 @@ simdjson_inline error_code json_structural_indexer::finish(dom_parser_implementa } parser.n_structural_indexes = uint32_t(indexer.tail - parser.structural_indexes.get()); /*** - * The On Demand API requires special padding. + * The On-Demand API requires special padding. * * This is related to https://github.com/simdjson/simdjson/issues/906 * Basically, we want to make sure that if the parsing continues beyond the last (valid) @@ -51367,7 +51377,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ @@ -54568,7 +54578,7 @@ simdjson_inline bool handle_unicode_codepoint_wobbly(const uint8_t **src_ptr, * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. */ diff --git a/3rdparty/simdjson/simdjson.h b/3rdparty/simdjson/simdjson.h index 0912825aab9d..ddb6f2e4e0a6 100644 --- a/3rdparty/simdjson/simdjson.h +++ b/3rdparty/simdjson/simdjson.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-07-04 16:26:22 -0400. Do not edit! */ +/* auto-generated on 2024-08-01 09:31:50 -0400. Do not edit! */ /* including simdjson.h: */ /* begin file simdjson.h */ #ifndef SIMDJSON_H @@ -60,6 +60,16 @@ #endif #endif +// C++ 23 +#if !defined(SIMDJSON_CPLUSPLUS23) && (SIMDJSON_CPLUSPLUS >= 202302L) +#define SIMDJSON_CPLUSPLUS23 1 +#endif + +// C++ 20 +#if !defined(SIMDJSON_CPLUSPLUS20) && (SIMDJSON_CPLUSPLUS >= 202002L) +#define SIMDJSON_CPLUSPLUS20 1 +#endif + // C++ 17 #if !defined(SIMDJSON_CPLUSPLUS17) && (SIMDJSON_CPLUSPLUS >= 201703L) #define SIMDJSON_CPLUSPLUS17 1 @@ -2356,7 +2366,7 @@ namespace std { #define SIMDJSON_SIMDJSON_VERSION_H /** The version of simdjson being used (major.minor.revision) */ -#define SIMDJSON_VERSION "3.9.5" +#define SIMDJSON_VERSION "3.10.0" namespace simdjson { enum { @@ -2367,11 +2377,11 @@ enum { /** * The minor version (major.MINOR.revision) of simdjson being used. */ - SIMDJSON_VERSION_MINOR = 9, + SIMDJSON_VERSION_MINOR = 10, /** * The revision (major.minor.REVISION) of simdjson being used. */ - SIMDJSON_VERSION_REVISION = 5 + SIMDJSON_VERSION_REVISION = 0 }; } // namespace simdjson @@ -3099,7 +3109,7 @@ class dom_parser_implementation { * Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. * @@ -3116,7 +3126,7 @@ class dom_parser_implementation { * Unescape a NON-valid UTF-8 string from src to dst, stopping at a final unescaped quote. There * must be an unescaped quote terminating the string. It returns the final output * position as pointer. In case of error (e.g., the string has bad escaped codes), - * then null_nullptrptr is returned. It is assumed that the output buffer is large + * then null_ptr is returned. It is assumed that the output buffer is large * enough. E.g., if src points at 'joe"', then dst needs to have four free bytes + * SIMDJSON_PADDING bytes. * @@ -4279,6 +4289,11 @@ class array { */ inline simdjson_result at(size_t index) const noexcept; + /** + * Implicitly convert object to element + */ + inline operator element() const noexcept; + private: simdjson_inline array(const internal::tape_ref &tape) noexcept; internal::tape_ref tape; @@ -6160,6 +6175,11 @@ class object { */ inline simdjson_result at_key_case_insensitive(std::string_view key) const noexcept; + /** + * Implicitly convert object to element + */ + inline operator element() const noexcept; + private: simdjson_inline object(const internal::tape_ref &tape) noexcept; @@ -6771,6 +6791,10 @@ inline simdjson_result array::at(size_t index) const noexcept { return INDEX_OUT_OF_BOUNDS; } +inline array::operator element() const noexcept { + return element(tape); +} + // // array::iterator inline implementation // @@ -6979,6 +7003,10 @@ inline simdjson_result object::at_key_case_insensitive(std::string_view return NO_SUCH_FIELD; } +inline object::operator element() const noexcept { + return element(tape); +} + // // object::iterator inline implementation // @@ -33659,8 +33687,8 @@ namespace arm64 { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -33973,6 +34001,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -35620,21 +35659,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -35668,6 +35723,8 @@ struct simdjson_result : public arm64::implementation_si simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -35842,8 +35899,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -37895,6 +37952,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -37962,6 +38027,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -38329,11 +38400,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -39220,6 +39303,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -44065,8 +44153,8 @@ namespace fallback { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -44379,6 +44467,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -46026,21 +46125,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -46074,6 +46189,8 @@ struct simdjson_result : public fallback::implementat simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -46248,8 +46365,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -48301,6 +48418,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -48368,6 +48493,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -48735,11 +48866,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -49626,6 +49769,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -54963,8 +55111,8 @@ namespace haswell { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -55277,6 +55425,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -56924,21 +57083,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -56972,6 +57147,8 @@ struct simdjson_result : public haswell::implementatio simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -57146,8 +57323,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -59199,6 +59376,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -59266,6 +59451,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -59633,11 +59824,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -60524,6 +60727,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -65860,8 +66068,8 @@ namespace icelake { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -66174,6 +66382,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -67821,21 +68040,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -67869,6 +68104,8 @@ struct simdjson_result : public icelake::implementatio simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -68043,8 +68280,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -70096,6 +70333,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -70163,6 +70408,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -70530,11 +70781,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -71421,6 +71684,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -76872,8 +77140,8 @@ namespace ppc64 { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -77186,6 +77454,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -78833,21 +79112,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -78881,6 +79176,8 @@ struct simdjson_result : public ppc64::implementation_si simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -79055,8 +79352,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -81108,6 +81405,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -81175,6 +81480,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -81542,11 +81853,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -82433,6 +82756,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -88207,8 +88535,8 @@ namespace westmere { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -88521,6 +88849,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -90168,21 +90507,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -90216,6 +90571,8 @@ struct simdjson_result : public westmere::implementat simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -90390,8 +90747,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -92443,6 +92800,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -92510,6 +92875,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -92877,11 +93248,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -93768,6 +94151,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -99013,8 +99401,8 @@ namespace lsx { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -99327,6 +99715,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -100974,21 +101373,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -101022,6 +101437,8 @@ struct simdjson_result : public lsx::implementation_simdjs simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -101196,8 +101613,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -103249,6 +103666,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -103316,6 +103741,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -103683,11 +104114,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -104574,6 +105017,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } @@ -109832,8 +110280,8 @@ namespace lasx { namespace ondemand { /** - * The default batch size for document_stream instances for this On Demand kernel. - * Note that different On Demand kernel may use a different DEFAULT_BATCH_SIZE value + * The default batch size for document_stream instances for this On-Demand kernel. + * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value * in the future. */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -110146,6 +110594,17 @@ class parser { */ simdjson_inline simdjson_result unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept; +#if SIMDJSON_DEVELOPMENT_CHECKS + /** + * Returns true if string_buf_loc is outside of the allocated range for the + * the string buffer. When true, it indicates that the string buffer has overflowed. + * This is a development-time check that is not needed in production. It can be + * used to detect buffer overflows in the string buffer and usafe usage of the + * string buffer. + */ + bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept; +#endif + private: /** @private [for benchmarking access] The implementation to use */ std::unique_ptr implementation{}; @@ -111793,21 +112252,37 @@ class field : public std::pair { * This consumes the key: once you have called unescaped_key(), you cannot * call it again nor can you call key(). */ - simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement) noexcept; + simdjson_inline simdjson_warn_unused simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + /** + * Get the key as a string_view (for higher speed, consider raw_key). + * We deliberately use a more cumbersome name (unescaped_key) to force users + * to think twice about using it. The content is stored in the receiver. + * + * This consumes the key: once you have called unescaped_key(), you cannot + * call it again nor can you call key(). + */ + template + simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept; /** * Get the key as a raw_json_string. Can be used for direct comparison with - * an unescaped C string: e.g., key() == "test". + * an unescaped C string: e.g., key() == "test". This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key() for a similar function which returns + * a more convenient std::string_view result. */ simdjson_inline raw_json_string key() const noexcept; /** * Get the unprocessed key as a string_view. This includes the quotes and may include - * some spaces after the last quote. + * some spaces after the last quote. This does not count as + * consumption of the content: you can safely call it repeatedly. + * See escaped_key(). */ simdjson_inline std::string_view key_raw_json_token() const noexcept; /** * Get the key as a string_view. This does not include the quotes and * the string is unprocessed key so it may contain escape characters - * (e.g., \uXXXX or \n). Use unescaped_key() to get the unescaped key. + * (e.g., \uXXXX or \n). It does not count as a consumption of the content: + * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key. */ simdjson_inline std::string_view escaped_key() const noexcept; /** @@ -111841,6 +112316,8 @@ struct simdjson_result : public lasx::implementation_simd simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result unescaped_key(bool allow_replacement = false) noexcept; + template + simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result key() noexcept; simdjson_inline simdjson_result key_raw_json_token() noexcept; simdjson_inline simdjson_result escaped_key() noexcept; @@ -112015,8 +112492,8 @@ class object { /** * Reset the iterator so that we are pointing back at the * beginning of the object. You should still consume values only once even if you - * can iterate through the object more than once. If you unescape a string within - * the object more than once, you have unsafe code. Note that rewinding an object + * can iterate through the object more than once. If you unescape a string or a key + * within the object more than once, you have unsafe code. Note that rewinding an object * means that you may need to reparse it anew: it is not a free operation. * * @returns true if the object contains some elements (not empty) @@ -114068,6 +114545,14 @@ simdjson_inline simdjson_warn_unused simdjson_result field::un return answer; } +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; +} + simdjson_inline raw_json_string field::key() const noexcept { SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. return first; @@ -114135,6 +114620,12 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} + simdjson_inline simdjson_result simdjson_result::value() noexcept { if (error()) { return error(); } return std::move(first.value()); @@ -114502,11 +114993,23 @@ simdjson_inline token_position json_iterator::position() const noexcept { } simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape(in, _string_buf_loc, allow_replacement); +#endif } simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else return parser->unescape_wobbly(in, _string_buf_loc); +#endif } simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { @@ -115393,6 +115896,11 @@ simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capa _max_depth = new_max_depth; return SUCCESS; } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); +} +#endif simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } diff --git a/CHANGELOG.md b/CHANGELOG.md index e7dff7b4f6c1..381e79cf4123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,22 +1,60 @@ -## axmol-2.1.5 ?? 2024 +## axmol-2.1.5 Aug.11 2024 -### Significant changes relative to 2.1.5: +### Significant changes relative to 2.1.4: - Add render I420 video support by @halx99 in https://github.com/axmolengine/axmol/pull/2050 , also fix issue #2049 reported by @SimplyJpk +- Refactor math simd by @halx99 in https://github.com/axmolengine/axmol/pull/2070, proposed by @huiguochen and @smilediver + - Implement NEON transformVertices & transformIndices by @smilediver in https://github.com/axmolengine/axmol/pull/2065 + - Implement SSE transformVertices & transformIndices, proposed by @huiguochen + - Add cmake option `AX_WASM_ISA_SIMD` to support build wasm with SIMD support, supports values `sse`, `neon` + - Rewrite all neon inline asm code with NEON intrinsics, this will allow WASM and winuwp-arm64 can compile with NEON intrinsic +- Improve FileUtils by @halx99 + - Rename FileUtils::createDirectory to FileUtils::createDirectories + - Use splitpath_cb to optimize FileUtils::createDirectories + - Rename FileUtils::getFileShortName to FileUtils::getPathBaseName + - Rename FileUtils::getFileExtension to FileUtils::getPathExtension + - Add FileUtils::getPathDirName + - Add FileUtils::getPathBaseNameNoExtension + - Mark all renamed FileUtils stubs old name deprecated + - Mark all FileUtils offthread APIs deprecated +- Remove arch suffix of host default build output directory for axmol cmdline ### Bug Fixes -- Use correct starting index of index buffer by @rh101 in https://github.com/axmolengine/axmol/pull/2052 +- Fix checkReallySupportsASTC does not work on ios device reported by @BIGCATDOG in https://github.com/axmolengine/axmol/issues/2078 +- Fix ImGui index draw info incorrect by @rh101 in https://github.com/axmolengine/axmol/pull/2052 - Fix ArchLinux setup dependencies always fail by @halx99 - Fix android VolatileTexture memory leak when addImage(img,k,fmt) +- Fix cmake prebuilt link error by @IamSanjid in https://github.com/axmolengine/axmol/pull/2058 +- Fix prebuilt openssl dll path incorrect for winuwp by @halx99 +- Fix #2060, make http request/respose reference counter thread-safe by @halx99 in https://github.com/axmolengine/axmol/pull/2064, reported by @qq461787436 +- Fix Curl downloader not observing set task limits by @smilediver in https://github.com/axmolengine/axmol/pull/2067 +- Fix a regression introduced by 2.1.4 that live2d compile error by @halx99, reported by @Sevael +- Fix unexpected libpng from system used +- Fix #1751, use coroutine control AutoTest flow ### Improvements +- Enhance Color4F and method naming change by @rh101 in https://github.com/axmolengine/axmol/pull/2072 +- Improve FastRNG implementation by @DelinWorks in https://github.com/axmolengine/axmol/pull/2056 + - Move FastRNG to ax ns and more improvements by @DelinWorks in https://github.com/axmolengine/axmol/pull/2057 + - Add missing include for AXASSERT by @smilediver in https://github.com/axmolengine/axmol/pull/2081 - Handle premultiplied alpha for grayscale PNGs by @j-jorge in https://github.com/axmolengine/axmol/pull/2047 +- Optimize ProgramState::setTexture() to avoid vector (de)allocations by @smilediver in https://github.com/axmolengine/axmol/pull/2061 +- Add OpenType font (.otf) to the noCompress list by @danialias in https://github.com/axmolengine/axmol/pull/2077 +- Update DrawNodeEx aka DrawNodeV2 to 0.95.1 by @aismann in https://github.com/axmolengine/axmol/pull/2079 + +### sdks updates + +- cppwinrt: 2.0.240111.5 ==> 2.0.240405.15 ### 3rdparty updates +- box2d: 2.4.1 ==> 2.4.2 +- curl: 8.8.0 ==> 8.9.1 +- simdjson: 3.9.5 ==> 3.10.0 - lz4: 1.9.4 ==> 1.10.0 +- c-ares: 1.32.2 ==> 1.33.0 ## axmol-2.1.4 Jun.20 2024 diff --git a/cmake/Modules/AXConfigDefine.cmake b/cmake/Modules/AXConfigDefine.cmake index 6e3e569e8913..507286326b4a 100644 --- a/cmake/Modules/AXConfigDefine.cmake +++ b/cmake/Modules/AXConfigDefine.cmake @@ -12,7 +12,10 @@ if (WINRT) # The minmal deploy target version: Windows 10, version 1809 (Build 10.0.17763) for building msix package # refer to: https://learn.microsoft.com/en-us/windows/msix/supported-platforms?source=recommendations set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION "10.0.17763" CACHE STRING "") - set(AX_CPPWINRT_VERSION "2.0.240111.5" CACHE STRING "") + set(AX_CPPWINRT_VERSION "2.0.240405.15" CACHE STRING "") + # For axmol deprecated policy, we need disable /sdl checks explicitly to avoid compiler traits invoking deprecated functions as error + set(CMAKE_C_FLAGS "/sdl- ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "/sdl- ${CMAKE_CXX_FLAGS}") endif() # config c standard diff --git a/core/2d/DrawNode.h b/core/2d/DrawNode.h index 17c9b41d8ed5..ead0417f3eef 100644 --- a/core/2d/DrawNode.h +++ b/core/2d/DrawNode.h @@ -397,7 +397,7 @@ class AX_DLL DrawNode : public Node // Get CocosStudio guide lines width. float getLineWidth(); - void setIsConvex(bool isConvex) { _isConvex = isConvex; }; // Set backwards compatible with cocos2dx/axmol 2.0 + void setIsConvex(bool isConvex) { _isConvex = isConvex; }; // Set backwards compatible with axmol 2.0 /** * When isolated is set, the position of the node is no longer affected by parent nodes. diff --git a/core/2d/FontAtlas.cpp b/core/2d/FontAtlas.cpp index e6aedf857a08..05ff22a72d73 100644 --- a/core/2d/FontAtlas.cpp +++ b/core/2d/FontAtlas.cpp @@ -49,8 +49,8 @@ NS_AX_BEGIN const int FontAtlas::CacheTextureWidth = 512; const int FontAtlas::CacheTextureHeight = 512; -const char* FontAtlas::CMD_PURGE_FONTATLAS = "__cc_PURGE_FONTATLAS"; -const char* FontAtlas::CMD_RESET_FONTATLAS = "__cc_RESET_FONTATLAS"; +const char* FontAtlas::CMD_PURGE_FONTATLAS = "__ax_PURGE_FONTATLAS"; +const char* FontAtlas::CMD_RESET_FONTATLAS = "__ax_RESET_FONTATLAS"; void FontAtlas::loadFontAtlas(std::string_view fontatlasFile, hlookup::string_map& outAtlasMap) { diff --git a/core/2d/FontAtlas.h b/core/2d/FontAtlas.h index 50bb63fa78ac..80baaff97614 100644 --- a/core/2d/FontAtlas.h +++ b/core/2d/FontAtlas.h @@ -25,8 +25,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef _CCFontAtlas_h_ -#define _CCFontAtlas_h_ +#ifndef _AX_FONTATLAS_H_ +#define _AX_FONTATLAS_H_ /// @cond DO_NOT_SHOW @@ -184,4 +184,4 @@ class AX_DLL FontAtlas : public Object NS_AX_END /// @endcond -#endif /* defined(__cocos2d_libs__CCFontAtlas__) */ +#endif /* defined(_AX_FONTATLAS_H_) */ diff --git a/core/2d/FontFNT.h b/core/2d/FontFNT.h index 8e219f0b5bcc..d412e793cabf 100644 --- a/core/2d/FontFNT.h +++ b/core/2d/FontFNT.h @@ -25,8 +25,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef _CCFontFNT_h_ -#define _CCFontFNT_h_ +#ifndef _AX_FONTFNT_H_ +#define _AX_FONTFNT_H_ /// @cond DO_NOT_SHOW @@ -190,4 +190,4 @@ class AX_DLL FontFNT : public Font NS_AX_END -#endif /* defined(__cocos2d_libs__CCFontFNT__) */ +#endif /* defined(_AX_FONTFNT_H_) */ diff --git a/core/2d/Label.h b/core/2d/Label.h index b3aefec03fab..eff25f4a7a3d 100644 --- a/core/2d/Label.h +++ b/core/2d/Label.h @@ -25,8 +25,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef _COCOS2D_CCLABEL_H_ -#define _COCOS2D_CCLABEL_H_ +#ifndef _AX_LABEL_H_ +#define _AX_LABEL_H_ #include "2d/Node.h" #include "renderer/CustomCommand.h" @@ -945,4 +945,4 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol NS_AX_END -#endif /*__COCOS2D_CCLABEL_H */ +#endif /*_AX_LABEL_H */ diff --git a/core/2d/MenuItem.h b/core/2d/MenuItem.h index 489f1725603f..ec6825d2cb51 100644 --- a/core/2d/MenuItem.h +++ b/core/2d/MenuItem.h @@ -33,7 +33,7 @@ THE SOFTWARE. // C++ includes #include -// cocos2d includes +// axmol includes #include "2d/Node.h" #include "base/Protocols.h" diff --git a/core/3d/Terrain.cpp b/core/3d/Terrain.cpp index 70571422bd78..c55b140efeb1 100644 --- a/core/3d/Terrain.cpp +++ b/core/3d/Terrain.cpp @@ -50,7 +50,7 @@ NS_AX_BEGIN namespace { // It's used for creating a default texture when lightMap is nullpter -static unsigned char cc_2x2_white_image[] = { +static unsigned char ax_2x2_white_image[] = { // RGBA8888 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; } // namespace @@ -267,7 +267,7 @@ Terrain::Terrain() #endif #ifdef AX_USE_METAL auto image = new Image(); - bool AX_UNUSED isOK = image->initWithRawData(cc_2x2_white_image, sizeof(cc_2x2_white_image), 2, 2, 8); + bool AX_UNUSED isOK = image->initWithRawData(ax_2x2_white_image, sizeof(ax_2x2_white_image), 2, 2, 8); AXASSERT(isOK, "The 2x2 empty texture was created unsuccessfully."); _dummyTexture = new Texture2D(); _dummyTexture->initWithImage(image); diff --git a/core/audio/AudioEngineImpl.cpp b/core/audio/AudioEngineImpl.cpp index 3a9449ffb16f..1a692c11586f 100644 --- a/core/audio/AudioEngineImpl.cpp +++ b/core/audio/AudioEngineImpl.cpp @@ -930,7 +930,7 @@ void AudioEngineImpl::_updatePlayers(bool forStop) } // don't invoke finish callback when stop/stopAll to avoid stack overflow - if (UTILS_LIKELY(!forStop)) + if (AX_LIKELY(!forStop)) { if (!_finishCallbacks.empty()) { diff --git a/core/base/Config.h b/core/base/Config.h index 1e0324747768..4b4c27ef07bf 100644 --- a/core/base/Config.h +++ b/core/base/Config.h @@ -329,7 +329,7 @@ THE SOFTWARE. #endif /** @def AX_STRIP_FPS - * Whether to strip FPS related data and functions, such as cc_fps_images_png + * Whether to strip FPS related data and functions, such as ax_fps_images_png */ #ifndef AX_STRIP_FPS # define AX_STRIP_FPS 0 diff --git a/core/base/Controller.h b/core/base/Controller.h index e8c5d35c60d1..8e5ecfa4f2fd 100644 --- a/core/base/Controller.h +++ b/core/base/Controller.h @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCController__ -#define __cocos2d_libs__CCController__ +#ifndef _AX_CONTROLLER_H_ +#define _AX_CONTROLLER_H_ #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || \ AX_TARGET_PLATFORM == AX_PLATFORM_MAC || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || \ defined(_WIN32) /* win32 & winuwp */ || \ @@ -251,4 +251,4 @@ class AX_DLL Controller NS_AX_END #endif -#endif /* defined(__cocos2d_libs__CCController__) */ +#endif /* defined(_AX_CONTROLLER_H_) */ diff --git a/core/base/Director.cpp b/core/base/Director.cpp index b1993841b74d..f83fc7062b93 100644 --- a/core/base/Director.cpp +++ b/core/base/Director.cpp @@ -1287,8 +1287,8 @@ void Director::calculateMPF() void Director::getFPSImageData(unsigned char** datapointer, ssize_t* length) { // FIXME: fixed me if it should be used - *datapointer = cc_fps_images_png; - *length = cc_fps_images_len(); + *datapointer = ax_fps_images_png; + *length = ax_fps_images_len(); } void Director::createStatsLabel() @@ -1306,7 +1306,7 @@ void Director::createStatsLabel() AX_SAFE_RELEASE_NULL(_FPSLabel); AX_SAFE_RELEASE_NULL(_drawnBatchesLabel); AX_SAFE_RELEASE_NULL(_drawnVerticesLabel); - _textureCache->removeTextureForKey("/cc_fps_images"); + _textureCache->removeTextureForKey("/ax_fps_images"); FileUtils::getInstance()->purgeCachedEntries(); } @@ -1324,7 +1324,7 @@ void Director::createStatsLabel() return; } - texture = _textureCache->addImage(image, "/cc_fps_images", PixelFormat::RGBA4); + texture = _textureCache->addImage(image, "/ax_fps_images", PixelFormat::RGBA4); AX_SAFE_RELEASE(image); /* diff --git a/core/base/EventAcceleration.h b/core/base/EventAcceleration.h index 98631b730bfe..645968482ebc 100644 --- a/core/base/EventAcceleration.h +++ b/core/base/EventAcceleration.h @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCAccelerometerEvent__ -#define __cocos2d_libs__CCAccelerometerEvent__ +#ifndef _AX_ACCELEROMETEREVENT_H_ +#define _AX_ACCELEROMETEREVENT_H_ #include "base/Event.h" #include "base/Types.h" @@ -58,4 +58,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCAccelerometerEvent__) */ +#endif /* defined(_AX_ACCELEROMETEREVENT_H_) */ diff --git a/core/base/EventController.h b/core/base/EventController.h index 2d6fd31f8025..6dc4005e607f 100644 --- a/core/base/EventController.h +++ b/core/base/EventController.h @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__EventController__ -#define __cocos2d_libs__EventController__ +#ifndef _AX_EVENTCONTROLLER_H_ +#define _AX_EVENTCONTROLLER_H_ #include "platform/PlatformMacros.h" #include "base/Event.h" @@ -111,4 +111,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__EventController__) */ +#endif /* defined(_AX_EVENTCONTROLLER_H_) */ diff --git a/core/base/EventCustom.h b/core/base/EventCustom.h index ffc3842bf62c..7ce7a568906a 100644 --- a/core/base/EventCustom.h +++ b/core/base/EventCustom.h @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCCustomEvent__ -#define __cocos2d_libs__CCCustomEvent__ +#ifndef _AX_CUSTOMEVENT_H_ +#define _AX_CUSTOMEVENT_H_ #include #include "base/Event.h" @@ -77,4 +77,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCCustomEvent__) */ +#endif /* defined(_AX_CUSTOMEVENT_H_) */ diff --git a/core/base/EventFocus.h b/core/base/EventFocus.h index 2e478e590132..849a9a22e763 100644 --- a/core/base/EventFocus.h +++ b/core/base/EventFocus.h @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCEventFocus__ -#define __cocos2d_libs__CCEventFocus__ +#ifndef _AX_EVENTFOCUS_H_ +#define _AX_EVENTFOCUS_H_ #include "base/Event.h" @@ -67,4 +67,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCEventFocus__) */ +#endif /* defined(_AX_EVENTFOCUS_H_) */ diff --git a/core/base/EventKeyboard.h b/core/base/EventKeyboard.h index 10bcb711f660..884e1c66153a 100644 --- a/core/base/EventKeyboard.h +++ b/core/base/EventKeyboard.h @@ -24,8 +24,8 @@ ****************************************************************************/ -#ifndef __cocos2d_libs__CCKeyboardEvent__ -#define __cocos2d_libs__CCKeyboardEvent__ +#ifndef _AX_KEYBOARDEVENT_H_ +#define _AX_KEYBOARDEVENT_H_ #include "base/Event.h" @@ -240,4 +240,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCKeyboardEvent__) */ +#endif /* defined(_AX_KEYBOARDEVENT_H_) */ diff --git a/core/base/EventListenerAcceleration.cpp b/core/base/EventListenerAcceleration.cpp index 83d4f69df646..34bb8fa7e8df 100644 --- a/core/base/EventListenerAcceleration.cpp +++ b/core/base/EventListenerAcceleration.cpp @@ -30,7 +30,7 @@ NS_AX_BEGIN -const std::string EventListenerAcceleration::LISTENER_ID = "__cc_acceleration"; +const std::string EventListenerAcceleration::LISTENER_ID = "__ax_acceleration"; EventListenerAcceleration::EventListenerAcceleration() {} diff --git a/core/base/EventListenerAcceleration.h b/core/base/EventListenerAcceleration.h index 42cfbb1178a6..34d5ef6d90f7 100644 --- a/core/base/EventListenerAcceleration.h +++ b/core/base/EventListenerAcceleration.h @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCAccelerometerListener__ -#define __cocos2d_libs__CCAccelerometerListener__ +#ifndef _AX_ACCELEROMETERLISTENER_H_ +#define _AX_ACCELEROMETERLISTENER_H_ #include "base/EventListener.h" #include "base/Types.h" @@ -76,4 +76,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCAccelerometerListener__) */ +#endif /* defined(_AX_ACCELEROMETERLISTENER_H_) */ diff --git a/core/base/EventListenerController.cpp b/core/base/EventListenerController.cpp index d5ca85e12ef9..647ce1ca303c 100644 --- a/core/base/EventListenerController.cpp +++ b/core/base/EventListenerController.cpp @@ -31,7 +31,7 @@ NS_AX_BEGIN -const std::string EventListenerController::LISTENER_ID = "__cc_controller"; +const std::string EventListenerController::LISTENER_ID = "__ax_controller"; EventListenerController* EventListenerController::create() { diff --git a/core/base/EventListenerController.h b/core/base/EventListenerController.h index fced0b03f78b..07a8612297f9 100644 --- a/core/base/EventListenerController.h +++ b/core/base/EventListenerController.h @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__EventListenerController__ -#define __cocos2d_libs__EventListenerController__ +#ifndef _AX_EVENTLISTENERCONTROLLER_H_ +#define _AX_EVENTLISTENERCONTROLLER_H_ #include "platform/PlatformMacros.h" #include "base/EventListener.h" @@ -77,4 +77,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__EventListenerController__) */ +#endif /* defined(_AX_EVENTLISTENERCONTROLLER_H_) */ diff --git a/core/base/EventListenerCustom.h b/core/base/EventListenerCustom.h index 3057facea689..430f4beeb747 100644 --- a/core/base/EventListenerCustom.h +++ b/core/base/EventListenerCustom.h @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCCustomEventListener__ -#define __cocos2d_libs__CCCustomEventListener__ +#ifndef _AX_CUSTOMEVENTLISTENER_H_ +#define _AX_CUSTOMEVENTLISTENER_H_ #include "base/EventListener.h" @@ -89,4 +89,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCCustomEventListener__) */ +#endif /* defined(_AX_CUSTOMEVENTLISTENER_H_) */ diff --git a/core/base/EventListenerFocus.cpp b/core/base/EventListenerFocus.cpp index acf8f390e329..7e3b6d1a503a 100644 --- a/core/base/EventListenerFocus.cpp +++ b/core/base/EventListenerFocus.cpp @@ -31,7 +31,7 @@ NS_AX_BEGIN -const std::string EventListenerFocus::LISTENER_ID = "__cc_focus_event"; +const std::string EventListenerFocus::LISTENER_ID = "__ax_focus_event"; EventListenerFocus::EventListenerFocus() : onFocusChanged(nullptr) {} diff --git a/core/base/EventListenerFocus.h b/core/base/EventListenerFocus.h index 9126350bd269..f9ce696f012b 100644 --- a/core/base/EventListenerFocus.h +++ b/core/base/EventListenerFocus.h @@ -25,8 +25,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCEventListenerFocus__ -#define __cocos2d_libs__CCEventListenerFocus__ +#ifndef _AX_EVENTLISTENERFOCUS_H_ +#define _AX_EVENTLISTENERFOCUS_H_ #include "base/EventListener.h" @@ -80,4 +80,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCEventListenerFocus__) */ +#endif /* defined(_AX_EVENTLISTENERFOCUS_H_) */ diff --git a/core/base/EventListenerKeyboard.cpp b/core/base/EventListenerKeyboard.cpp index 7f6f7df8e776..33863ff43a24 100644 --- a/core/base/EventListenerKeyboard.cpp +++ b/core/base/EventListenerKeyboard.cpp @@ -29,7 +29,7 @@ NS_AX_BEGIN -const std::string EventListenerKeyboard::LISTENER_ID = "__cc_keyboard"; +const std::string EventListenerKeyboard::LISTENER_ID = "__ax_keyboard"; bool EventListenerKeyboard::checkAvailable() { diff --git a/core/base/EventListenerKeyboard.h b/core/base/EventListenerKeyboard.h index e3f29e02ee2d..a3d75fcb59ab 100644 --- a/core/base/EventListenerKeyboard.h +++ b/core/base/EventListenerKeyboard.h @@ -24,8 +24,8 @@ ****************************************************************************/ -#ifndef __cocos2d_libs__CCKeyboardEventListener__ -#define __cocos2d_libs__CCKeyboardEventListener__ +#ifndef _AX_KEYBOARDEVENTLISTENER_H_ +#define _AX_KEYBOARDEVENTLISTENER_H_ #include "base/EventListener.h" #include "base/EventKeyboard.h" @@ -69,4 +69,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCKeyboardEventListener__) */ +#endif /* defined(_AX_KEYBOARDEVENTLISTENER_H_) */ diff --git a/core/base/EventListenerMouse.cpp b/core/base/EventListenerMouse.cpp index 75b6ea114fb5..f21fe328b9c3 100644 --- a/core/base/EventListenerMouse.cpp +++ b/core/base/EventListenerMouse.cpp @@ -28,7 +28,7 @@ NS_AX_BEGIN -const std::string EventListenerMouse::LISTENER_ID = "__cc_mouse"; +const std::string EventListenerMouse::LISTENER_ID = "__ax_mouse"; bool EventListenerMouse::checkAvailable() { diff --git a/core/base/EventListenerMouse.h b/core/base/EventListenerMouse.h index 04362b8fbe5f..2a5be6a42909 100644 --- a/core/base/EventListenerMouse.h +++ b/core/base/EventListenerMouse.h @@ -24,8 +24,8 @@ ****************************************************************************/ -#ifndef __cocos2d_libs__CCMouseEventListener__ -#define __cocos2d_libs__CCMouseEventListener__ +#ifndef _AX_MOUSEEVENTLISTENER_H_ +#define _AX_MOUSEEVENTLISTENER_H_ #include "base/EventListener.h" #include "base/EventMouse.h" @@ -72,4 +72,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCMouseEventListener__) */ +#endif /* defined(_AX_MOUSEEVENTLISTENER_H_) */ diff --git a/core/base/EventListenerTouch.cpp b/core/base/EventListenerTouch.cpp index bda593680ca0..9ff6afaf373d 100644 --- a/core/base/EventListenerTouch.cpp +++ b/core/base/EventListenerTouch.cpp @@ -33,7 +33,7 @@ NS_AX_BEGIN -const std::string EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one"; +const std::string EventListenerTouchOneByOne::LISTENER_ID = "__ax_touch_one_by_one"; EventListenerTouchOneByOne::EventListenerTouchOneByOne() : onTouchBegan(nullptr) @@ -119,7 +119,7 @@ EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone() ///////// -const std::string EventListenerTouchAllAtOnce::LISTENER_ID = "__cc_touch_all_at_once"; +const std::string EventListenerTouchAllAtOnce::LISTENER_ID = "__ax_touch_all_at_once"; EventListenerTouchAllAtOnce::EventListenerTouchAllAtOnce() : onTouchesBegan(nullptr), onTouchesMoved(nullptr), onTouchesEnded(nullptr), onTouchesCancelled(nullptr) diff --git a/core/base/EventListenerTouch.h b/core/base/EventListenerTouch.h index 2750e463272a..683922afaf6c 100644 --- a/core/base/EventListenerTouch.h +++ b/core/base/EventListenerTouch.h @@ -25,8 +25,8 @@ ****************************************************************************/ -#ifndef __cocos2d_libs__CCTouchEventListener__ -#define __cocos2d_libs__CCTouchEventListener__ +#ifndef _AX_TOUCHEVENTLISTENER_H_ +#define _AX_TOUCHEVENTLISTENER_H_ #include "base/EventListener.h" #include @@ -136,4 +136,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCTouchEventListener__) */ +#endif /* defined(_AX_TOUCHEVENTLISTENER_H_) */ diff --git a/core/base/EventMouse.h b/core/base/EventMouse.h index e92a0cfdb3e7..aa07415b5c67 100644 --- a/core/base/EventMouse.h +++ b/core/base/EventMouse.h @@ -24,8 +24,8 @@ ****************************************************************************/ -#ifndef __cocos2d_libs__CCMouseEvent__ -#define __cocos2d_libs__CCMouseEvent__ +#ifndef _AX_MOUSEEVENT_H_ +#define _AX_MOUSEEVENT_H_ #include "base/Event.h" #include "math/Math.h" @@ -203,4 +203,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__CCMouseEvent__) */ +#endif /* defined(_AX_MOUSEEVENT_H_) */ diff --git a/core/base/EventTouch.h b/core/base/EventTouch.h index 9f6500b7dfe1..05993f7527e0 100644 --- a/core/base/EventTouch.h +++ b/core/base/EventTouch.h @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__TouchEvent__ -#define __cocos2d_libs__TouchEvent__ +#ifndef _AX_TOUCHEVENT_H_ +#define _AX_TOUCHEVENT_H_ #include "base/Event.h" #include @@ -100,4 +100,4 @@ NS_AX_END // end of base group /// @} -#endif /* defined(__cocos2d_libs__TouchEvent__) */ +#endif /* defined(_AX_TOUCHEVENT_H_) */ diff --git a/core/base/FPSImages.cpp b/core/base/FPSImages.cpp index cc36cfe6a395..4cd12443af39 100644 --- a/core/base/FPSImages.cpp +++ b/core/base/FPSImages.cpp @@ -28,7 +28,7 @@ #if !AX_STRIP_FPS -unsigned char cc_fps_images_png[] = { +unsigned char ax_fps_images_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x03, 0xe7, 0x00, 0x00, 0x00, 0x36, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa5, 0x74, 0xe8, 0xab, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, @@ -1511,9 +1511,9 @@ unsigned char cc_fps_images_png[] = { 0x37, 0x3a, 0x35, 0x32, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x3d, 0xc7, 0x95, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; -unsigned int cc_fps_images_len(void) +unsigned int ax_fps_images_len(void) { - return sizeof(cc_fps_images_png); + return sizeof(ax_fps_images_png); } #endif // #if !AX_STRIP_FPS diff --git a/core/base/FPSImages.h b/core/base/FPSImages.h index 8858b7ea4a38..c28d57cf772c 100644 --- a/core/base/FPSImages.h +++ b/core/base/FPSImages.h @@ -30,8 +30,8 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW #if !AX_STRIP_FPS -extern unsigned char cc_fps_images_png[]; -extern unsigned int cc_fps_images_len(void); +extern unsigned char ax_fps_images_png[]; +extern unsigned int ax_fps_images_len(void); #endif /// @endcond diff --git a/core/base/GameController.h b/core/base/GameController.h index 7f9b1fc0f891..c147250d2b91 100644 --- a/core/base/GameController.h +++ b/core/base/GameController.h @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCGameController__ -#define __cocos2d_libs__CCGameController__ +#ifndef _AX_GAMECONTROLLER_H_ +#define _AX_GAMECONTROLLER_H_ /// @cond DO_NOT_SHOW #include "base/Controller.h" @@ -32,4 +32,4 @@ #include "base/EventListenerController.h" /// @endcond -#endif /* defined(__cocos2d_libs__CCGameController__) */ +#endif /* defined(_AX_GAMECONTROLLER_H_) */ diff --git a/core/base/Macros.h b/core/base/Macros.h index 8678b53be622..fe7f9469ddac 100644 --- a/core/base/Macros.h +++ b/core/base/Macros.h @@ -40,14 +40,14 @@ THE SOFTWARE. #ifndef AXASSERT # if _AX_DEBUG > 0 # if AX_ENABLE_SCRIPT_BINDING -extern bool AX_DLL cc_assert_script_compatible(const char* msg); +extern bool AX_DLL ax_assert_script_compatible(const char* msg); # define AXASSERT(cond, msg) \ do \ { \ if (!(cond)) \ { \ const char* m = (msg); \ - if (m && *m && !cc_assert_script_compatible(m)) \ + if (m && *m && !ax_assert_script_compatible(m)) \ AXLOGE("Assert failed: {}", m); \ AX_ASSERT(cond); \ } \ diff --git a/core/base/Properties.h b/core/base/Properties.h index 7c1178ff4a3a..10aced0b55af 100644 --- a/core/base/Properties.h +++ b/core/base/Properties.h @@ -21,8 +21,8 @@ This file was modified to fit the cocos2d-x project */ -#ifndef __cocos2d_libs__CCProperties__ -#define __cocos2d_libs__CCProperties__ +#ifndef _AX_PROPERTIES_H_ +#define _AX_PROPERTIES_H_ #include #include @@ -602,4 +602,4 @@ class AX_DLL Properties }; } -#endif // __cocos2d_libs__CCProperties__ +#endif // _AX_PROPERTIES_H_ diff --git a/core/base/RefPtr.h b/core/base/RefPtr.h index 47be8c6304e9..dc2afaf20d9e 100644 --- a/core/base/RefPtr.h +++ b/core/base/RefPtr.h @@ -82,10 +82,10 @@ struct ReferencedObject }; /** - * Wrapper class which maintains a strong reference to a cocos2dx ax::Object* type object. + * Wrapper class which maintains a strong reference to a axmol ax::Object* type object. * Similar in concept to a boost smart pointer. * - * Enables the use of the RAII idiom with Cocos2dx objects and helps automate some of the more + * Enables the use of the RAII idiom with axmol objects and helps automate some of the more * mundane tasks of pointer initialization and cleanup. * * The class itself is modelled on C++ 11 std::shared_ptr, and trys to keep some of the methods diff --git a/core/base/ScriptSupport.cpp b/core/base/ScriptSupport.cpp index 158bfff9dfd3..61e5876fa0ab 100644 --- a/core/base/ScriptSupport.cpp +++ b/core/base/ScriptSupport.cpp @@ -31,7 +31,7 @@ # include "base/Scheduler.h" # include "2d/Node.h" -bool AX_DLL cc_assert_script_compatible(const char* msg) +bool AX_DLL ax_assert_script_compatible(const char* msg) { ax::ScriptEngineProtocol* engine = ax::ScriptEngineManager::getInstance()->getScriptEngine(); if (engine && engine->handleAssert(msg)) diff --git a/core/base/UTF8.h b/core/base/UTF8.h index 5f20404b4a44..5d09b5e7a280 100644 --- a/core/base/UTF8.h +++ b/core/base/UTF8.h @@ -270,4 +270,4 @@ class AX_DLL StringUTF8 NS_AX_END -#endif /** defined(__cocos2dx__ccUTF8__) */ +#endif /** defined(AXMOL__UTF8_H) */ diff --git a/core/base/Utils.cpp b/core/base/Utils.cpp index 1f949d4999de..6df3d48badda 100644 --- a/core/base/Utils.cpp +++ b/core/base/Utils.cpp @@ -56,6 +56,7 @@ THE SOFTWARE. #include "base/base64.h" #include "base/axstd.h" +#include "yasio/string_view.hpp" using namespace std::string_view_literals; @@ -827,6 +828,37 @@ std::string urlDecode(std::string_view st) return decoded; } +AX_DLL std::string& filePathToUrl(std::string&& path) +{ + // + // file uri helper: https://www.ietf.org/rfc/rfc3986.txt + // + static constexpr std::string_view LOCAL_FILE_URL_PREFIX = "file:///"sv; // The localhost file prefix + + // windows: file:///D:/xxx/xxx.mp4 + // unix: file:///home/xxx/xxx.mp4 + // android_asset: + // - file:///android_asset/xxx/xxx.mp4 + // - asset://android_asset/xxx/xxx.mp4 + if (!path.empty()) + { + if (path[0] == '/') + path.insert(0, LOCAL_FILE_URL_PREFIX.data(), LOCAL_FILE_URL_PREFIX.length() - 1); + else if (!cxx20::ic::starts_with(path, LOCAL_FILE_URL_PREFIX)) + { +#if !defined(__ANDROID__) + path.insert(0, LOCAL_FILE_URL_PREFIX.data(), LOCAL_FILE_URL_PREFIX.length()); +#else + if (!cxx20::starts_with(path, "assets/"sv)) // not android asset + path.insert(0, LOCAL_FILE_URL_PREFIX.data(), LOCAL_FILE_URL_PREFIX.length()); + else + path.replace(0, "assets/"sv.length(), "file:///android_asset/"); +#endif + } + } + return path; +} + AX_DLL std::string base64Encode(const void* in, size_t inlen) { size_t n = ax::base64::encoded_size(inlen); diff --git a/core/base/Utils.h b/core/base/Utils.h index aabc0c1aab2f..ff1fd694df3a 100644 --- a/core/base/Utils.h +++ b/core/base/Utils.h @@ -423,6 +423,8 @@ AX_DLL std::string urlEncode(std::string_view s); AX_DLL std::string urlDecode(std::string_view st); +AX_DLL std::string& filePathToUrl(std::string&& path); + /** * Encodes bytes into a 64base buffer * @returns base64 encoded string diff --git a/core/base/Value.h b/core/base/Value.h index bc31627c4d0a..ac23c33116cd 100644 --- a/core/base/Value.h +++ b/core/base/Value.h @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#ifndef __cocos2d_libs__CCValue__ -#define __cocos2d_libs__CCValue__ +#ifndef _AX_VALUE_H_ +#define _AX_VALUE_H_ #include "platform/PlatformMacros.h" #include "base/Macros.h" @@ -289,4 +289,4 @@ inline const ax::Value& optValue(const ValueMap& dictionary, std::string_view ke NS_AX_END -#endif /* defined(__cocos2d_libs__CCValue__) */ +#endif /* defined(_AX_VALUE_H_) */ diff --git a/core/base/axstd.h b/core/base/axstd.h index c86e1c0c6c9f..875f02921efa 100644 --- a/core/base/axstd.h +++ b/core/base/axstd.h @@ -126,4 +126,36 @@ inline void split_of_cb(std::string_view s, const char* delims, _Fn&& func) split_of_cb(s.data(), s.length(), delims, std::move(func)); } +template +inline void splitpath_cb(_Elem* s, _Pred&& pred, _Fn&& func) // will convert '\\' to '/' +{ + _Elem* _Start = s; // the start of every string + _Elem* _Ptr = s; // source string iterator + while (pred(_Ptr)) + { + if ('\\' == *_Ptr || '/' == *_Ptr) + { + if (_Ptr != _Start) + { + auto _Ch = *_Ptr; + *_Ptr = '\0'; + bool should_brk = func(s); +#if defined(_WIN32) + *_Ptr = '\\'; +#else // For unix linux like system. + *_Ptr = '/'; +#endif + if (should_brk) + return; + } + _Start = _Ptr + 1; + } + ++_Ptr; + } + if (_Start < _Ptr) + { + func(s); + } +} + } // namespace axstd diff --git a/core/math/FastRNG.h b/core/math/FastRNG.h index 8733b52ff5c4..799c3d69efaf 100644 --- a/core/math/FastRNG.h +++ b/core/math/FastRNG.h @@ -25,6 +25,7 @@ #ifndef __FAST_RNG_H__ #define __FAST_RNG_H__ +#include "base/Macros.h" #include "math/MathBase.h" #include #include diff --git a/core/math/MathUtilNeon.inl b/core/math/MathUtilNeon.inl index 42773e51637c..d85324ddc541 100644 --- a/core/math/MathUtilNeon.inl +++ b/core/math/MathUtilNeon.inl @@ -57,7 +57,7 @@ struct MathUtilNeon inline static void multiplyMatrix(const _xm128_t* m, float scalar, _xm128_t* dst) { _xm128_t s = vdupq_n_f32(scalar); - UTILS_UNROLL + AX_UNROLL for (int i = 0; i < 4; ++i) { dst[i] = vmulq_f32(m[i], s); @@ -68,7 +68,7 @@ struct MathUtilNeon { float32x4_t product[4]; float32x4_t val; - UTILS_UNROLL + AX_UNROLL for (int i = 0; i < 4; ++i) { val = vmulq_n_f32(m1[0], vgetq_lane_f32(m2[i], 0)); @@ -82,7 +82,7 @@ struct MathUtilNeon inline static void negateMatrix(const _xm128_t* m, _xm128_t* dst) { - UTILS_UNROLL + AX_UNROLL for (int i = 0; i < 4; ++i) { dst[i] = vnegq_f32(m[i]); diff --git a/core/media/MediaEngine.h b/core/media/MediaEngine.h index 210889f4786f..b5c66d510e80 100644 --- a/core/media/MediaEngine.h +++ b/core/media/MediaEngine.h @@ -181,33 +181,6 @@ struct MEVideoFrame #endif }; -// -// file uri helper: https://www.ietf.org/rfc/rfc3986.txt -// -static constexpr std::string_view LOCAL_FILE_URI_PREFIX = "file:///"sv; // The localhost file prefix - -inline std::string& path2uri(std::string& path) -{ - // windows: file:///D:/xxx/xxx.mp4 - // unix: file:///home/xxx/xxx.mp4 - // android_asset: - // - file:///android_asset/xxx/xxx.mp4 - // - asset://android_asset/xxx/xxx.mp4 - if (!path.empty()) - { - if (path[0] == '/') - path.insert(0, LOCAL_FILE_URI_PREFIX.data(), LOCAL_FILE_URI_PREFIX.length() - 1); - else - { - if (!cxx20::starts_with(path, "assets/"sv)) // not android asset - path.insert(0, LOCAL_FILE_URI_PREFIX.data(), LOCAL_FILE_URI_PREFIX.length()); - else - path.replace(0, "assets/"sv.length(), "file:///android_asset/"); - } - } - return path; -} - // // redisigned corss-platform MediaEngine, inspired from microsoft media foundation: IMFMediaEngine // diff --git a/core/media/VlcMediaEngine.cpp b/core/media/VlcMediaEngine.cpp index 10c17978a39a..422a2714f6ba 100644 --- a/core/media/VlcMediaEngine.cpp +++ b/core/media/VlcMediaEngine.cpp @@ -457,7 +457,7 @@ bool VlcMediaEngine::transferVideoFrame() return false; std::unique_lock lck(_frameBuffer1Mtx); - if (UTILS_LIKELY(!_frameBuffer1.empty())) + if (AX_LIKELY(!_frameBuffer1.empty())) { _frameBuffer2.swap(_frameBuffer1); lck.unlock(); // unlock immidiately before invoke user callback (maybe upload buffer to GPU) diff --git a/core/network/Downloader-curl.cpp b/core/network/Downloader-curl.cpp index 514c31d949f0..089891ba8c5f 100644 --- a/core/network/Downloader-curl.cpp +++ b/core/network/Downloader-curl.cpp @@ -151,7 +151,7 @@ class DownloadTaskCURL : public IDownloadTask dir = _tempFileName.substr(0, found + 1); if (!FileUtils::getInstance()->isDirectoryExistInternal(dir)) { - if (!FileUtils::getInstance()->createDirectory(dir)) + if (!FileUtils::getInstance()->createDirectories(dir)) { _errCode = DownloadTask::ERROR_CREATE_DIR_FAILED; _errCodeInternal = 0; diff --git a/core/network/Downloader-wasm.cpp b/core/network/Downloader-wasm.cpp index 50553ad2dbdf..dd9a0124af16 100644 --- a/core/network/Downloader-wasm.cpp +++ b/core/network/Downloader-wasm.cpp @@ -1,9 +1,7 @@ /**************************************************************************** - Copyright (c) 2015-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - http://www.cocos2d-x.org + https://axmol.dev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -263,4 +261,4 @@ namespace ax { namespace network { coTask->task.reset(); } } -} // namespace cocos2d::network +} // namespace ax::network diff --git a/core/network/Downloader-wasm.h b/core/network/Downloader-wasm.h index 03690bf0ec56..2dedcdb847c5 100644 --- a/core/network/Downloader-wasm.h +++ b/core/network/Downloader-wasm.h @@ -1,10 +1,8 @@ /**************************************************************************** - Copyright (c) 2015-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - http://www.cocos2d-x.org + https://axmol.dev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -64,5 +62,5 @@ namespace ax { namespace network static void onLoad(emscripten_fetch_t *fetch); }; -}} // namespace cocos2d::network +}} // namespace ax::network diff --git a/core/network/HttpClient-wasm.h b/core/network/HttpClient-wasm.h index 4d2d54de0ba7..618000a1ba6e 100644 --- a/core/network/HttpClient-wasm.h +++ b/core/network/HttpClient-wasm.h @@ -1,10 +1,7 @@ /**************************************************************************** - Copyright (c) 2012 greathqy - Copyright (c) 2012 cocos2d-x.org - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - http://www.cocos2d-x.org + https://axmol.dev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/core/network/WebSocket-wasm.cpp b/core/network/WebSocket-wasm.cpp index e7f021b7b0e2..92e86592ccca 100644 --- a/core/network/WebSocket-wasm.cpp +++ b/core/network/WebSocket-wasm.cpp @@ -1,9 +1,7 @@ /**************************************************************************** - Copyright (c) 2015-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - http://www.cocos2d-x.org + https://axmol.dev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/core/network/WebSocket-wasm.h b/core/network/WebSocket-wasm.h index 980f334074bb..c87be25523b4 100644 --- a/core/network/WebSocket-wasm.h +++ b/core/network/WebSocket-wasm.h @@ -1,9 +1,7 @@ /**************************************************************************** - Copyright (c) 2015-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - http://www.cocos2d-x.org + https://axmol.dev/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/core/platform/FileUtils.cpp b/core/platform/FileUtils.cpp index 93fed6b59b32..a8ba2ea4b922 100644 --- a/core/platform/FileUtils.cpp +++ b/core/platform/FileUtils.cpp @@ -980,7 +980,7 @@ void FileUtils::isDirectoryExist(std::string_view fullPath, std::function callback) const { performOperationOffthread( - [path = std::string{dirPath}]() -> bool { return FileUtils::getInstance()->createDirectory(path); }, + [path = std::string{dirPath}]() -> bool { return FileUtils::getInstance()->createDirectories(path); }, std::move(callback)); } @@ -1133,9 +1133,9 @@ bool FileUtils::isDirectoryExistInternal(std::string_view dirPath) const return false; } -bool FileUtils::createDirectory(std::string_view path) const +bool FileUtils::createDirectories(std::string_view path) const { - AXASSERT(false, "FileUtils not support createDirectory"); + AXASSERT(false, "FileUtils not support createDirectories"); return false; } @@ -1190,67 +1190,30 @@ bool FileUtils::isDirectoryExistInternal(std::string_view dirPath) const return false; } -bool FileUtils::createDirectory(std::string_view path) const +bool FileUtils::createDirectories(std::string_view path) const { AXASSERT(!path.empty(), "Invalid path"); if (isDirectoryExist(path)) return true; - // Split the path - size_t start = 0; - size_t found = path.find_first_of("/\\", start); - std::string_view subpath; - std::vector dirs; - - if (found != std::string::npos) - { - while (true) + bool fail{false}; + std::string mpath{path}; + axstd::splitpath_cb(&mpath.front(), [](char* ptr) { return *ptr != '\0'; }, [&fail](const char* subpath) { + struct stat st; + if (stat(subpath, &st) != 0) { - subpath = path.substr(start, found - start + 1); - if (!subpath.empty()) - dirs.emplace_back(std::string{subpath}); - start = found + 1; - found = path.find_first_of("/\\", start); - if (found == std::string::npos) - { - if (start < path.length()) - { - dirs.emplace_back(std::string{path.substr(start)}); - } - break; - } - } - } - - DIR* dir = NULL; - - // Create path recursively - std::string strSubpath; - for (const auto& iter : dirs) - { - strSubpath += iter; - dir = opendir(strSubpath.c_str()); - - if (!dir) - { - // directory doesn't exist, should create a new one - - int ret = mkdir(strSubpath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + int ret = mkdir(subpath, S_IRWXU | S_IRWXG | S_IRWXO); if (ret != 0 && (errno != EEXIST)) - { - // current directory can not be created, sub directories can not be created too - // should return - return false; - } + fail = true; } else - { - // directory exists, should close opened dir - closedir(dir); - } - } - return true; + fail = !S_ISDIR(st.st_mode); + + return fail; + }); + + return fail; } namespace @@ -1379,32 +1342,45 @@ bool FileUtils::isPopupNotify() const return s_popupNotify; } -std::string FileUtils::getFileExtension(std::string_view filePath) const +std::string FileUtils::getFileExtension(std::string_view filePath) { std::string fileExtension; size_t pos = filePath.find_last_of('.'); if (pos != std::string::npos) { fileExtension = filePath.substr(pos, filePath.length()); - std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); } return fileExtension; } -std::string FileUtils::getFileShortName(std::string_view filePath) +std::string FileUtils::getPathBaseName(std::string_view filePath) { - // std::string fileExtension; size_t pos = filePath.find_last_of("/\\"); if (pos != std::string::npos) - { return std::string{filePath.substr(pos + 1)}; - } return std::string{filePath}; } +std::string FileUtils::getPathBaseNameNoExtension(std::string_view filePath) +{ + size_t pos = filePath.find_last_of("/\\"); + size_t dot = filePath.find_last_of('.'); + if (pos != std::string::npos) + return std::string{filePath.substr(pos + 1, dot != std::string_view::npos ? dot - (pos + 1) : dot)}; + + return std::string{filePath.substr(0, dot)}; +} + +std::string FileUtils::getPathDirName(std::string_view filePath) { + auto pos = filePath.find_last_of("/\\"); + if (pos != std::string_view::npos) + return std::string{filePath.substr(0, pos)}; + return std::string{filePath}; +} + void FileUtils::valueMapCompact(ValueMap& /*valueMap*/) const {} void FileUtils::valueVectorCompact(ValueVector& /*valueVector*/) const {} diff --git a/core/platform/FileUtils.h b/core/platform/FileUtils.h index 58d44e8ef0cf..6f3761f885ce 100644 --- a/core/platform/FileUtils.h +++ b/core/platform/FileUtils.h @@ -564,14 +564,29 @@ class AX_DLL FileUtils * @param filePath The path of the file, it could be a relative or absolute path. * @return suffix for filename in lower case or empty if a dot not found. */ - virtual std::string getFileExtension(std::string_view filePath) const; + static std::string getFileExtension(std::string_view filePath); /** * Gets filename shotName * @param filePath The path of the file, it could be a relative or absolute path. * @return fileName.Extension without path */ - static std::string getFileShortName(std::string_view filePath); + AX_DEPRECATED_ATTRIBUTE static std::string getFileShortName(std::string_view filePath) { return getPathBaseName(filePath); } + + /* + * @since axmol-2.1.5 + */ + static std::string getPathBaseName(std::string_view filePath); + + /* + * @since axmol-2.1.5 + */ + static std::string getPathBaseNameNoExtension(std::string_view filePath); + + /* + * @since axmol-2.1.5 + */ + static std::string getPathDirName(std::string_view filePath); /** * Checks whether the path is an absolute path. @@ -609,7 +624,8 @@ class AX_DLL FileUtils * @param dirPath The path of the directory, it must be an absolute path. * @return True if the directory have been created successfully, false if not. */ - virtual bool createDirectory(std::string_view dirPath) const; + virtual bool createDirectories(std::string_view dirPath) const; + AX_DEPRECATED_ATTRIBUTE bool createDirectory(std::string_view dirPath) const { return createDirectories(dirPath); } /** * Create a directory, async off the main cocos thread. @@ -618,7 +634,7 @@ class AX_DLL FileUtils * @param callback The function that will be called when the operation is complete. Will have one boolean * argument, true if the directory was successfully, false otherwise. */ - virtual void createDirectory(std::string_view dirPath, std::function callback) const; + AX_DEPRECATED_ATTRIBUTE void createDirectory(std::string_view dirPath, std::function callback) const; /** * Removes a directory. @@ -635,7 +651,7 @@ class AX_DLL FileUtils * @param callback The function that will be called when the operation is complete. Will have one boolean * argument, true if the directory was successfully removed, false otherwise. */ - virtual void removeDirectory(std::string_view dirPath, std::function callback) const; + AX_DEPRECATED_ATTRIBUTE void removeDirectory(std::string_view dirPath, std::function callback) const; /** * Removes a file. @@ -652,7 +668,7 @@ class AX_DLL FileUtils * @param callback The function that will be called when the operation is complete. Will have one boolean * argument, true if the file was successfully removed, false otherwise. */ - virtual void removeFile(std::string_view filepath, std::function callback) const; + AX_DEPRECATED_ATTRIBUTE virtual void removeFile(std::string_view filepath, std::function callback) const; /** * Renames a file under the given directory. @@ -673,7 +689,7 @@ class AX_DLL FileUtils * @param callback The function that will be called when the operation is complete. Will have one boolean * argument, true if the file was successfully renamed, false otherwise. */ - virtual void renameFile(std::string_view path, + AX_DEPRECATED_ATTRIBUTE virtual void renameFile(std::string_view path, std::string_view oldname, std::string_view name, std::function callback) const; @@ -695,7 +711,7 @@ class AX_DLL FileUtils * @param callback The function that will be called when the operation is complete. Will have one boolean * argument, true if the file was successfully renamed, false otherwise. */ - virtual void renameFile(std::string_view oldfullpath, + AX_DEPRECATED_ATTRIBUTE void renameFile(std::string_view oldfullpath, std::string_view newfullpath, std::function callback) const; @@ -716,7 +732,7 @@ class AX_DLL FileUtils * @param callback The function that will be called when the operation is complete. Will have one long * argument, the file size. */ - virtual void getFileSize(std::string_view filepath, std::function callback) const; + AX_DEPRECATED_ATTRIBUTE void getFileSize(std::string_view filepath, std::function callback) const; /** * List all files in a directory. @@ -735,7 +751,7 @@ class AX_DLL FileUtils * @js NA * @lua NA */ - virtual void listFilesAsync(std::string_view dirPath, std::function)> callback) const; + AX_DEPRECATED_ATTRIBUTE void listFilesAsync(std::string_view dirPath, std::function)> callback) const; /** * List all files recursively in a directory. @@ -754,7 +770,7 @@ class AX_DLL FileUtils * @js NA * @lua NA */ - virtual void listFilesRecursivelyAsync(std::string_view dirPath, + AX_DEPRECATED_ATTRIBUTE void listFilesRecursivelyAsync(std::string_view dirPath, std::function)> callback) const; /** Returns the full path cache. */ diff --git a/core/platform/Image.cpp b/core/platform/Image.cpp index 08566ac3feb0..d8c91c55d8c1 100644 --- a/core/platform/Image.cpp +++ b/core/platform/Image.cpp @@ -1914,7 +1914,7 @@ bool Image::initWithETC2Data(uint8_t* data, ssize_t dataLen, bool ownData) // etc2_decode_image always decode to RGBA8888 _dataLen = _width * _height * 4; _data = static_cast(malloc(_dataLen)); - if (UTILS_UNLIKELY(etc2_decode_image(format, static_cast(data) + pixelOffset, + if (AX_UNLIKELY(etc2_decode_image(format, static_cast(data) + pixelOffset, static_cast(_data), _width, _height) != 0)) { // software decode fail, release pixels data @@ -1999,7 +1999,7 @@ bool Image::initWithASTCData(uint8_t* data, ssize_t dataLen, bool ownData) _dataLen = _width * _height * 4; _data = static_cast(malloc(_dataLen)); - if (UTILS_UNLIKELY(astc_decompress_image(static_cast(data) + ASTC_HEAD_SIZE, + if (AX_UNLIKELY(astc_decompress_image(static_cast(data) + ASTC_HEAD_SIZE, static_cast(dataLen) - ASTC_HEAD_SIZE, _data, _width, _height, block_x, block_y) != 0)) { diff --git a/core/platform/PlatformConfig.h b/core/platform/PlatformConfig.h index 39da4778f91c..ba4eef281cfb 100644 --- a/core/platform/PlatformConfig.h +++ b/core/platform/PlatformConfig.h @@ -174,14 +174,15 @@ Linux: Desktop GL/Vulkan #ifdef AX_SSE_INTRINSICS // axmol math ISA require SSE2 at latest -# include # if defined(__SSE4_1__) # include +# else +# include # endif -using _xm128_t = __m128; +typedef __m128 _xm128_t; #elif defined(AX_NEON_INTRINSICS) # include -using _xm128_t = float32x4_t; +typedef float32x4_t _xm128_t; #endif /// @endcond diff --git a/core/platform/PlatformMacros.h b/core/platform/PlatformMacros.h index 98f3bde1c915..a48c4779e604 100644 --- a/core/platform/PlatformMacros.h +++ b/core/platform/PlatformMacros.h @@ -465,25 +465,25 @@ public: \ */ #if __has_builtin(__builtin_expect) # ifdef __cplusplus -# define UTILS_LIKELY(exp) (__builtin_expect(!!(exp), true)) -# define UTILS_UNLIKELY(exp) (__builtin_expect(!!(exp), false)) +# define AX_LIKELY(exp) (__builtin_expect(!!(exp), true)) +# define AX_UNLIKELY(exp) (__builtin_expect(!!(exp), false)) # else -# define UTILS_LIKELY(exp) (__builtin_expect(!!(exp), 1)) -# define UTILS_UNLIKELY(exp) (__builtin_expect(!!(exp), 0)) +# define AX_LIKELY(exp) (__builtin_expect(!!(exp), 1)) +# define AX_UNLIKELY(exp) (__builtin_expect(!!(exp), 0)) # endif #else -# define UTILS_LIKELY(exp) (!!(exp)) -# define UTILS_UNLIKELY(exp) (!!(exp)) +# define AX_LIKELY(exp) (!!(exp)) +# define AX_UNLIKELY(exp) (!!(exp)) #endif #if defined(_MSC_VER) // MSVC does not support loop unrolling hints -# define UTILS_UNROLL -# define UTILS_NOUNROLL +# define AX_UNROLL +# define AX_NOUNROLL #else // C++11 allows pragmas to be specified as part of defines using the _Pragma syntax. -# define UTILS_UNROLL _Pragma("unroll") -# define UTILS_NOUNROLL _Pragma("nounroll") +# define AX_UNROLL _Pragma("unroll") +# define AX_NOUNROLL _Pragma("nounroll") #endif #endif // __AX_PLATFORM_MACROS_H__ diff --git a/core/platform/android/Device-android.cpp b/core/platform/android/Device-android.cpp index 0b792e0cf1b6..b9fa53715e70 100644 --- a/core/platform/android/Device-android.cpp +++ b/core/platform/android/Device-android.cpp @@ -213,7 +213,7 @@ void Device::selectionChanged() NS_AX_END -// this method is called by Cocos2dxBitmap +// this method is called by BitmapHelper extern "C" { /** * this method is called by java code to init width, height and pixels data diff --git a/core/platform/android/java/build.xml b/core/platform/android/java/build.xml index 885e6eed8a7f..6d49d6e3dd62 100644 --- a/core/platform/android/java/build.xml +++ b/core/platform/android/java/build.xml @@ -1,5 +1,5 @@ - +