diff --git a/.github/workflows/cmake-single-platform.yml b/.github/workflows/cmake-single-platform.yml
index 5ba9abb..a0a9ffa 100644
--- a/.github/workflows/cmake-single-platform.yml
+++ b/.github/workflows/cmake-single-platform.yml
@@ -1,4 +1,4 @@
-name: CMake on a single platform
+name: CMake build all
on:
push:
@@ -11,7 +11,7 @@ env:
BUILD_TYPE: Release
jobs:
- build:
+ build-x86:
runs-on: windows-latest
steps:
@@ -22,7 +22,12 @@ jobs:
- name: Get Tag Name
shell: bash
- run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
+ run: |
+ if [[ "${{ github.ref }}" == refs/tags/* ]]; then
+ echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
+ else
+ echo "TAG_NAME=${{ github.head_ref }}" >> $GITHUB_ENV
+ fi
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -G "Visual Studio 17 2022" -A Win32 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
@@ -43,5 +48,44 @@ jobs:
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
- name: windows-x86-${{ env.TAG_NAME }}
+ name: mysims-windows-x86-${{ env.TAG_NAME }}
path: ${{ github.workspace }}/artifact/
+ build-x64:
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ submodules: true
+
+ - name: Get Tag Name
+ shell: bash
+ run: |
+ if [[ "${{ github.ref }}" == refs/tags/* ]]; then
+ echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
+ else
+ echo "TAG_NAME=${{ github.head_ref }}" >> $GITHUB_ENV
+ fi
+
+ - name: Configure CMake
+ run: cmake -B ${{github.workspace}}/build -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+ - name: Build
+ run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+ - name: Test
+ working-directory: ${{github.workspace}}/build
+ run: ctest -C ${{env.BUILD_TYPE}}
+
+ - name: Prepare Artifact
+ run: |
+ mkdir -p ${{ github.workspace }}/artifact/mods/basemod
+ cp -r ${{ github.workspace }}/basemod/* ${{ github.workspace }}/artifact/mods/basemod/
+ cp ${{ github.workspace }}/build/Release/WSOCK32.dll ${{ github.workspace }}/artifact/
+
+ - name: Upload Artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: mysims-cozybundle-windows-x64-${{ env.TAG_NAME }}
+ path: ${{ github.workspace }}/artifact/
diff --git a/.gitignore b/.gitignore
index 1b68a19..77e91ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,8 +2,10 @@
cmake
old
run
-cmake-build-debug-visual-studio
-cmake-build-release-visual-studio
+cmake-build-debug64-msvc
+cmake-build-release64-msvc
+cmake-build-debug32-msvc
+cmake-build-release32-msvc
src/Version.h
.idea
build/
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index c070a53..f52a700 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,9 @@
[submodule "libs/pugixml"]
path = libs/pugixml
url = https://github.com/zeux/pugixml.git
+[submodule "libs/googletest"]
+ path = libs/googletest
+ url = https://github.com/google/googletest.git
+[submodule "libs/directxtex"]
+ path = libs/directxtex
+ url = https://github.com/microsoft/DirectXTex.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7ffcc35..b0f8f99 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,44 +4,111 @@ project(MySimsModLoader)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+option(BUILD_TESTS "Build tests" ON)
+
# Disable sigmatch tests to speed up compilation
set(SIGMATCH_BUILD_TESTS OFF CACHE BOOL "Disable sigmatch tests" FORCE)
+add_subdirectory(libs/directxtex)
add_subdirectory(libs/minhook)
add_subdirectory(libs/sigmatch)
add_subdirectory(libs/pugixml)
-add_library(MySimsModLoader SHARED src/Main.cpp
- src/dsound.h
- src/modloader/ModLoader.cpp
- src/modloader/ModLoader.h
- src/util/Logger.cpp
- src/util/Logger.h
- src/util/Console.cpp
- src/util/Console.h
- src/assets/Assets.cpp
- src/assets/Assets.h
- src/mods/Mods.cpp
- src/mods/Mods.h
- src/Hooks/Hooks.cpp
- src/Hooks/Hooks.h
- src/signatures/Signatures.cpp
- src/signatures/Signatures.h
- src/mods/Mod.cpp
- src/mods/Mod.h
- src/util/File.cpp
- src/util/File.h
- src/assets/Asset.cpp
- src/assets/Asset.h
- src/util/FNV.cpp
- src/util/FNV.h
- src/signatures/lua.h
- src/signatures/sigdef.h
- src/hooks/LuaHook.cpp
- src/hooks/LuaHook.h
+set(SOURCES
+ src/Main.cpp
+ src/core/modloader/ModLoader.cpp
+ src/core/modloader/ModLoader.h
+ src/core/system/Logger.cpp
+ src/core/system/Logger.h
+ src/core/system/Console.cpp
+ src/core/system/Console.h
+ src/core/assets/Assets.cpp
+ src/core/assets/Assets.h
+ src/core/modloader/Mods.cpp
+ src/core/modloader/Mods.h
+ src/core/hooks/Hooks.cpp
+ src/core/hooks/Hooks.h
+ src/core/signatures/Signatures.cpp
+ src/core/signatures/Signatures.h
+ src/core/modloader/Mod.cpp
+ src/core/modloader/Mod.h
+ src/core/assets/Asset.cpp
+ src/core/assets/Asset.h
+ src/core/hash/FNV.cpp
+ src/core/hash/FNV.h
+ src/include/lua.h
+ src/core/signatures/sigdef.h
+ src/core/hooks/LuaHook.cpp
+ src/core/hooks/LuaHook.h
src/include/hash_sha256.h
+ src/core/resource/IdResolver.cpp
+ src/core/resource/IdResolver.h
+ src/core/hooks/Config.h
+ src/formats/materials/Material.h
+ src/formats/materials/Material.cpp
+ src/formats/xml/CharacterDef.h
+ src/formats/xml/CharacterDef.cpp
+ src/formats/xml/ObjectDef.h
+ src/formats/xml/ObjectDef.cpp
+ src/formats/xml/World.h
+ src/formats/xml/World.cpp
+ src/core/system/CrashHandler.cpp
+ src/core/system/CrashHandler.h
+ src/core/resource/CustomDatabase.cpp
+ src/core/resource/CustomDatabase.h
+ src/EA/io/FileStream.cpp
+ src/EA/io/FileStream.h
+ src/EA/io/IStream.h
+ src/tweakers/Swarm/SwarmTweaker.h
+ src/tweakers/Swarm/SwarmTweaker.cpp
+ src/EA/io/MemoryStream.cpp
+ src/EA/io/MemoryStream.h
+ src/tweakers/Tweakers.h
+ src/EA/ResourceMan/KeyFilter.h
+ src/EA/ResourceMan/RecordInfo.h
+ src/core/resource/CustomRecord.cpp
+ src/core/resource/CustomRecord.h
+ src/EA/ResourceMan/IDatabase.h
+ src/EA/ResourceMan/IRecord.h
+ src/EA/IO/Constants.h
+ src/EA/IO/SubFileStream.cpp
+ src/EA/IO/SubFileStream.h
+ src/tweakers/Clothing/ClothingTweaker.cpp
+ src/tweakers/Clothing/ClothingTweaker.h
+ src/EA/ResourceMan/ResourceKey.cpp
+ src/formats/materials/MaterialParameter.cpp
+ src/include/refpack.h
+ src/core/hooks/ArgscriptHook.cpp
+ src/core/hooks/ArgscriptHook.h
+ src/formats/materials/MaterialSet.cpp
+ src/formats/materials/MaterialSet.h
+ src/formats/builders/MaterialBuilder.cpp
+ src/formats/builders/MaterialBuilder.h
+ src/formats/builders/MaterialSetBuilder.cpp
+ src/formats/builders/MaterialSetBuilder.h
+ src/tweakers/Material/MaterialTweaker.cpp
+ src/tweakers/Material/MaterialTweaker.h
+ src/tweakers/Tweakers.cpp
+ src/EA/ResourceMan/IResource.h
+ src/core/util/StreamUtil.cpp
+ src/core/util/StreamUtil.h
+ src/tweakers/Clothing/SkintoneVariantGenerator.cpp
+ src/tweakers/Clothing/SkintoneVariantGenerator.h
)
+if (CMAKE_GENERATOR_PLATFORM STREQUAL "x64")
+ list(APPEND SOURCES
+ src/platform/w64/wsock.def
+ src/platform/w64/wsock.h)
+
+else ()
+ list(APPEND SOURCES
+ src/platform/w32/dsound.def
+ src/platform/w32/dsound.h)
+endif ()
+
+add_library(MySimsModLoader SHARED ${SOURCES})
+
add_custom_target(version
${CMAKE_COMMAND} -D SRC=${CMAKE_SOURCE_DIR}/src/Version.h.in
-D DST=${CMAKE_SOURCE_DIR}/src/Version.h
@@ -50,11 +117,96 @@ add_custom_target(version
add_dependencies(MySimsModLoader version)
+add_compile_definitions(CHAR8_T_DEFINED)
+
+add_definitions(-D_CHAR16T)
+add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+add_definitions(-D_SCL_SECURE_NO_WARNINGS)
+add_definitions(-DEASTL_OPENSOURCE=1)
+
+add_definitions(-DPROJECT_ROOT="${CMAKE_SOURCE_DIR}")
+
+target_include_directories(MySimsModLoader PRIVATE
+ libs/eastl/include
+ libs/eastl/test/packages/EABase/include/Common
+)
+
target_include_directories(MySimsModLoader PRIVATE libs/pugixml/src)
target_include_directories(MySimsModLoader PRIVATE libs/minhook/include)
target_include_directories(MySimsModLoader PRIVATE libs/sigmatch/include)
+target_include_directories(MySimsModLoader PRIVATE libs/directxtex)
+target_link_libraries(MySimsModLoader PRIVATE DirectXTex)
target_link_libraries(MySimsModLoader PRIVATE minhook)
target_link_libraries(MySimsModLoader PRIVATE pugixml-static)
-set_target_properties(MySimsModLoader PROPERTIES OUTPUT_NAME "dsound")
\ No newline at end of file
+set_target_properties(MySimsModLoader PROPERTIES OUTPUT_NAME "dsound")
+
+if (CMAKE_GENERATOR_PLATFORM STREQUAL "x64")
+ target_compile_definitions(MySimsModLoader PRIVATE VERSION_COZY_BUNDLE)
+ set_target_properties(MySimsModLoader PROPERTIES OUTPUT_NAME "WSOCK32")
+else ()
+ target_compile_definitions(MySimsModLoader PRIVATE VERSION_TACO_BELL)
+endif()
+
+if (BUILD_TESTS)
+ # For Windows: Prevent overriding the parent project's compiler/linker settings
+ # As per documentation: http://google.github.io/googletest/quickstart-cmake.html
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+ add_subdirectory(libs/googletest)
+
+ enable_testing()
+
+ add_executable(Tests
+ # Tests
+ tests/CharacterDefTest.cpp
+ tests/MaterialTest.cpp
+ tests/ObjectDefTest.cpp
+ tests/MaterialSetTest.cpp
+ # Format
+ src/formats/xml/CharacterDef.h
+ src/formats/xml/CharacterDef.cpp
+ src/formats/xml/ObjectDef.h
+ src/formats/xml/ObjectDef.cpp
+ src/formats/materials/Material.h
+ src/formats/materials/Material.cpp
+ src/formats/materials/MaterialParameter.h
+ src/formats/materials/MaterialParameter.cpp
+ src/formats/materials/MaterialSet.h
+ src/formats/materials/MaterialSet.cpp
+ # EA
+ src/EA/IO/MemoryStream.h
+ src/EA/IO/MemoryStream.cpp
+ src/EA/IO/FileStream.h
+ src/EA/IO/FileStream.cpp
+ src/EA/ResourceMan/ResourceKey.h
+ src/EA/ResourceMan/ResourceKey.cpp
+ # Utilities
+ src/core/system/Logger.h
+ src/core/system/Logger.cpp
+ src/core/util/StreamUtil.cpp
+ src/core/util/StreamUtil.h)
+
+ target_include_directories(Tests PRIVATE
+ libs/eastl/include
+ libs/eastl/test/packages/EABase/include/Common
+ )
+
+ # Set a define to indicate that we are running unit tests
+ target_compile_definitions(Tests PRIVATE -DUNIT_TESTING)
+
+ target_include_directories(Tests PRIVATE libs/pugixml/src)
+ target_include_directories(Tests PRIVATE src)
+
+ target_compile_definitions(Tests PRIVATE
+ TEST_ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/assets/"
+ )
+
+ target_link_libraries(Tests PRIVATE
+ GTest::gmock
+ GTest::gtest_main
+ pugixml-static)
+
+ include(GoogleTest)
+ gtest_discover_tests(Tests)
+endif ()
\ No newline at end of file
diff --git a/README.md b/README.md
index 2cdcdc5..390b79b 100644
--- a/README.md
+++ b/README.md
@@ -11,23 +11,34 @@ For any questions visit the [MySims Clubhouse](https://discord.gg/2j9mU6zNJH) mo
## Supported versions
-|Version|Supported|
-|-|-|
-|MySims Release / Origin (EA App)|✔️|
+|Version| Supported |
+|-|--|
+|MySims Release / Origin (EA App)|❌️|
|MySims Taco Bell Edition|✔️|
-|MySims EA App / Steam|When it releases|
-|MySims Kingdom EA App / Steam|When it releases|
+|MySims EA App / Steam|✔️|
+|MySims Kingdom EA App / Steam|✔️|
## Installation
+### Cozy Bundle
+
1. Go to the latest [Release](https://github.com/ThuverX/MySimsModLoader/releases)
-2. Download the file `windows-x86`
-3. Unzip it into your game folder, next to `MySims.exe` (`MySims/bin/`)
+2. Download the file `mysims-cozybundle-windows-x64`
+3. Unzip it into your game folder, next to `MySims.exe`
+ - In the end you should have `mods`, `WSOCK32.dll` and `MySims.exe` in the same folder.
+4. Done! Launch the game like normal.
+
+### Taco Bell Edition
+
+1. Go to the latest [Release](https://github.com/ThuverX/MySimsModLoader/releases)
+2. Download the file `mysims-windows-x86`
+3. Unzip it into your game folder, next to `MySims.exe` (`MySims/bin`)
- In the end you should have `mods`, `dsound.dll` and `MySims.exe` in the same folder.
4. Done! Launch the game like normal.
+
## Uninstallation
-1. Remove `dsound.dll`
+1. Remove `dsound.dll` or `WSOCK32.dll`
2. Optionally remove the `mods` folder
## Installing mods
@@ -41,8 +52,6 @@ To uninstall simply remove that folder from the `mods`.
Making mods is currently limited to texture and lua based mods. For now take a look at these places:
- ⚠️ WORK IN PROGRESS [Wiki](https://thuverx.github.io/mysims-research/Modding/index.html)
-- ⚠️ UNRELEASED [MySims Editor](https://github.com/ThuverX/MySimsEditor) to modify and create game files like worlds and models.
-- [Examples](examples).
## Building
1. **Clone the repository**:
@@ -52,9 +61,9 @@ Making mods is currently limited to texture and lua based mods. For now take a l
```
2. **Generate the build files using CMake**:
```sh
- cmake -B build -G "Visual Studio 17 2022" -A Win32
- ```
- > ⚠️ **Make sure to specify `-A Win32`** to build in **x86 mode**!
+ cmake -B build -G "Visual Studio 17 2022" -A Win32 # For TacoBell ⚠️ Make sure to specify `-A Win32` to build in x86 mode!
+ cmake -B build -G "Visual Studio 17 2022" # For Cozy Bundle
+ ```
3. **Build the project**:
```sh
@@ -64,6 +73,8 @@ Making mods is currently limited to texture and lua based mods. For now take a l
## Acknowledgements
- This project could never have been done without the awesome work done for the [Spore ModAPI](https://github.com/emd4600/Spore-ModAPI).
+ - Not only are a lot of formats very similar.
+ - This project also includes EASTL taken from the [Spore ModAPI](https://github.com/emd4600/Spore-ModAPI) repository.
- Honorary mention to [MorcuTool](https://github.com/Olivercomet/MorcuTool) for getting me interested in making this modloader.
## Contributors
diff --git a/basemod/lua/ea.lua b/basemod/lua/ea.lua
index 105bc4e..a8a77f3 100644
--- a/basemod/lua/ea.lua
+++ b/basemod/lua/ea.lua
@@ -12,7 +12,38 @@ if EA then
[251] = "NONE"
}
- function EA:LogLevel(class, level, ... )
- print("[" .. levels[level] .. "]", unpack(arg))
+ function EA:ShouldOutput(class, level)
+ return true
+ end
+
+ function LogLevel(class, level, ... )
+ if level ~= 25 then
+ print("[" .. class .. " " .. levels[level] .. "]", unpack(arg))
+ end
+ end
+
+ function EA:Log(class, ... )
+ LogLevel(class, self._defaultLogLevel, unpack(arg))
+ end
+
+ function EA:Trace( class, ... )
+ LogLevel(class, self._defaultLogLevel, unpack(arg))
+ end
+
+ function EA:LogI( class, ... )
+ LogLevel(class, EA.kLevelInfo, unpack(arg))
+ end
+
+ function EA:LogD( class, ... )
+ LogLevel(class, EA.kLevelDebug, unpack(arg))
+ end
+
+
+ function EA:LogW( class, ... )
+ LogLevel(class, EA.kLevelWarn, unpack(arg))
+ end
+
+ function EA:LogE( class,... )
+ LogLevel(class, EA.kLevelError, unpack(arg))
end
end
\ No newline at end of file
diff --git a/basemod/mod.xml b/basemod/mod.xml
index da496b9..17d8791 100644
--- a/basemod/mod.xml
+++ b/basemod/mod.xml
@@ -2,7 +2,6 @@
BaseMod
Basemod for MSML
ThuverX
-
lua/hooks.lua
lua/ea.lua
diff --git a/examples/greener-grass/assets/flowers.dds b/examples/greener-grass/assets/0x00000000!0x000000000B25E40B.dds
similarity index 100%
rename from examples/greener-grass/assets/flowers.dds
rename to examples/greener-grass/assets/0x00000000!0x000000000B25E40B.dds
diff --git a/examples/greener-grass/assets/grass.dds b/examples/greener-grass/assets/0x00000000!0x0000000061805F86.dds
similarity index 100%
rename from examples/greener-grass/assets/grass.dds
rename to examples/greener-grass/assets/0x00000000!0x0000000061805F86.dds
diff --git a/examples/greener-grass/assets/0x00000000!0x00000000EE93FAC8.dds b/examples/greener-grass/assets/0x00000000!0x00000000EE93FAC8.dds
new file mode 100644
index 0000000..0738528
Binary files /dev/null and b/examples/greener-grass/assets/0x00000000!0x00000000EE93FAC8.dds differ
diff --git a/examples/greener-grass/mod.xml b/examples/greener-grass/mod.xml
index 7d416ed..b2b647f 100644
--- a/examples/greener-grass/mod.xml
+++ b/examples/greener-grass/mod.xml
@@ -5,9 +5,4 @@
lua/playerhook.lua
-
- assets/grass.dds
- assets/grass.dds
- assets/flowers.dds
-
\ No newline at end of file
diff --git a/libs/directxtex b/libs/directxtex
new file mode 160000
index 0000000..e8c2e30
--- /dev/null
+++ b/libs/directxtex
@@ -0,0 +1 @@
+Subproject commit e8c2e30f195783258960cc8d929841667aa82e1d
diff --git a/libs/eastl/.appveyor.yml b/libs/eastl/.appveyor.yml
new file mode 100644
index 0000000..9751ffc
--- /dev/null
+++ b/libs/eastl/.appveyor.yml
@@ -0,0 +1,24 @@
+version: 1.0.{build}
+
+os:
+ - Visual Studio 2015
+ - Visual Studio 2013
+
+platform:
+ - x86
+ - x64
+
+build_script:
+ - cmd: mkdir build
+ - cmd: cd build
+ - cmd: cmake .. -DEASTL_BUILD_BENCHMARK:BOOL=ON -DEASTL_BUILD_TESTS:BOOL=ON
+ - cmd: cmake --build . --config Debug
+ - cmd: cmake --build . --config Release
+
+test_script:
+ - cmd: cd test
+ - cmd: ctest -C Release -V
+ - cmd: cd ..
+ - cmd: cd benchmark
+ - cmd: ctest -C Release -V
+ - cmd: cd ..
diff --git a/libs/eastl/.clang-format b/libs/eastl/.clang-format
new file mode 100644
index 0000000..ccd1128
--- /dev/null
+++ b/libs/eastl/.clang-format
@@ -0,0 +1,32 @@
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-
+Language : Cpp
+BasedOnStyle : Google
+Standard : Auto
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-
+AccessModifierOffset : -4
+AlignTrailingComments : true
+AllowAllParametersOfDeclarationOnNextLine : false
+AllowShortBlocksOnASingleLine : true
+AllowShortFunctionsOnASingleLine : true
+AllowShortIfStatementsOnASingleLine : false
+AllowShortLoopsOnASingleLine : false
+BinPackParameters : false
+BreakBeforeBraces : Allman
+BreakBeforeTernaryOperators : false
+BreakConstructorInitializersBeforeComma : true
+ColumnLimit : 120
+Cpp11BracedListStyle : true
+DerivePointerAlignment : true
+DerivePointerBinding : false
+IndentWidth : 4
+KeepEmptyLinesAtTheStartOfBlocks : true
+MaxEmptyLinesToKeep : 2
+NamespaceIndentation : Inner
+PointerBindsToType : true
+SpacesBeforeTrailingComments : 1
+SpacesInAngles : false
+SpacesInSquareBrackets : false
+TabWidth : 4
+UseTab : ForIndentation
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-
diff --git a/libs/eastl/.gitattributes b/libs/eastl/.gitattributes
new file mode 100644
index 0000000..e0800fd
--- /dev/null
+++ b/libs/eastl/.gitattributes
@@ -0,0 +1,3 @@
+# Auto detect text files and perform LF normalization
+# http://git-scm.com/docs/gitattributes
+* text=auto
diff --git a/libs/eastl/.gitignore b/libs/eastl/.gitignore
new file mode 100644
index 0000000..5dd7ab0
--- /dev/null
+++ b/libs/eastl/.gitignore
@@ -0,0 +1,36 @@
+tags
+**/*.swp
+**/*.swo
+.swp
+*.swp
+.swo
+-.d
+eastl_build_out
+build_bench
+bench.bat
+build.bat
+
+## CMake generated files
+CMakeCache.txt
+cmake_install.cmake
+
+## Patch files
+*.patch
+
+## For Visual Studio Generated projects
+*.sln
+**/*.vcxproj
+**/*.vcxproj.filters
+*.VC.opendb
+*.sdf
+.vs/*
+**/Debug/*
+CMakeFiles/*
+EASTL.dir/**
+RelWithDebInfo/*
+Release/*
+Win32/*
+x64/*
+MinSizeRel/*
+build/*
+Testing/*
diff --git a/libs/eastl/.p4ignore b/libs/eastl/.p4ignore
new file mode 100644
index 0000000..f4eb09f
--- /dev/null
+++ b/libs/eastl/.p4ignore
@@ -0,0 +1,2 @@
+/.git/
+tags
diff --git a/libs/eastl/.travis.yml b/libs/eastl/.travis.yml
new file mode 100644
index 0000000..6570e47
--- /dev/null
+++ b/libs/eastl/.travis.yml
@@ -0,0 +1,58 @@
+language: cpp
+
+os:
+ - linux
+ - osx
+
+compiler:
+ - gcc
+ - clang
+
+addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.8
+ - g++-4.8
+ - clang
+
+matrix:
+ exclude:
+ - os: osx
+ compiler: gcc
+
+install:
+# Linux Setup
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget --no-check-certificate http://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz ;fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xzf cmake-3.4.3-Linux-x86_64.tar.gz ;fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8" ;fi ;fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export PATH=$PWD/cmake-3.4.3-Linux-x86_64/bin:$PATH ;fi
+# OSX Setup
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then wget --no-check-certificate http://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz ;fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then tar -xzf cmake-3.4.3-Darwin-x86_64.tar.gz ;fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH=$PWD/cmake-3.4.3-Darwin-x86_64/CMake.app/Contents/bin:$PATH ;fi
+
+script:
+# Debug Build
+ - mkdir build_debug
+ - cd build_debug
+ - cmake .. -DEASTL_BUILD_BENCHMARK:BOOL=ON -DEASTL_BUILD_TESTS:BOOL=ON
+ - cmake --build . --config Debug
+ - cd ..
+# Release Build
+ - mkdir build_release
+ - cd build_release
+ - cmake .. -DEASTL_BUILD_BENCHMARK:BOOL=ON -DEASTL_BUILD_TESTS:BOOL=ON
+ - cmake --build . --config Release
+ # - cd ..
+
+after_success:
+# Run Release Tests
+ - cd test
+ - ctest -C Release -V
+ - cd ..
+# Run Release Benchmarks
+ - cd benchmark
+ - ctest -C Release -V
+
diff --git a/libs/eastl/3RDPARTYLICENSES.TXT b/libs/eastl/3RDPARTYLICENSES.TXT
new file mode 100644
index 0000000..9c286fb
--- /dev/null
+++ b/libs/eastl/3RDPARTYLICENSES.TXT
@@ -0,0 +1,103 @@
+Additional licenses also apply to this software package as detailed below.
+
+
+
+HP STL comes with the following license:
+
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 1994
+// Hewlett-Packard Company
+//
+// Permission to use, copy, modify, distribute and sell this software
+// and its documentation for any purpose is hereby granted without fee,
+// provided that the above copyright notice appear in all copies and
+// that both that copyright notice and this permission notice appear
+// in supporting documentation. Hewlett-Packard Company makes no
+// representations about the suitability of this software for any
+// purpose. It is provided "as is" without express or implied warranty.
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+libc++ comes with the following license:
+
+==============================================================================
+libc++ License
+==============================================================================
+
+The libc++ library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2015 by the contributors listed at
+http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2014 by the contributors listed at
+http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
diff --git a/libs/eastl/CMakeLists.txt b/libs/eastl/CMakeLists.txt
new file mode 100644
index 0000000..045ebb9
--- /dev/null
+++ b/libs/eastl/CMakeLists.txt
@@ -0,0 +1,85 @@
+#-------------------------------------------------------------------------------------------
+# Copyright (C) Electronic Arts Inc. All rights reserved.
+#-------------------------------------------------------------------------------------------
+cmake_minimum_required(VERSION 3.1)
+project(EASTL)
+
+#-------------------------------------------------------------------------------------------
+# Options
+#-------------------------------------------------------------------------------------------
+option(EASTL_BUILD_BENCHMARK "Enable generation of build files for benchmark" OFF)
+option(EASTL_BUILD_TESTS "Enable generation of build files for tests" OFF)
+
+#-------------------------------------------------------------------------------------------
+# Sub-projects
+#-------------------------------------------------------------------------------------------
+add_subdirectory(test/packages/EABase)
+
+if(EASTL_BUILD_TESTS OR EASTL_BUILD_BENCHMARK)
+ add_subdirectory(test/packages/EAAssert)
+ add_subdirectory(test/packages/EAStdC)
+ add_subdirectory(test/packages/EAMain)
+ add_subdirectory(test/packages/EATest)
+ add_subdirectory(test/packages/EAThread)
+endif()
+
+if(EASTL_BUILD_BENCHMARK)
+ add_subdirectory(benchmark)
+endif()
+
+if(EASTL_BUILD_TESTS)
+ add_subdirectory(test)
+endif()
+
+#-------------------------------------------------------------------------------------------
+# Defines
+#-------------------------------------------------------------------------------------------
+add_definitions(-D_CHAR16T)
+add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+add_definitions(-D_SCL_SECURE_NO_WARNINGS)
+add_definitions(-DEASTL_OPENSOURCE=1)
+
+#-------------------------------------------------------------------------------------------
+# Library definition
+#-------------------------------------------------------------------------------------------
+file(GLOB EASTL_SOURCES "source/*.cpp" "include/EASTL/*.h")
+add_library(EASTL ${EASTL_SOURCES})
+
+#-------------------------------------------------------------------------------------------
+# Compiler Flags
+#-------------------------------------------------------------------------------------------
+set_property(TARGET EASTL PROPERTY CXX_STANDARD 11)
+
+if(EASTL_BUILD_TESTS OR EASTL_BUILD_BENCHMARK)
+ set_property(TARGET EAStdC EATest PROPERTY CXX_STANDARD 11)
+endif()
+
+if( UNIX AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" )
+ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fasm-blocks" )
+endif()
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+endif()
+
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
+endif()
+
+#-------------------------------------------------------------------------------------------
+# Include dirs
+#-------------------------------------------------------------------------------------------
+target_include_directories(EASTL PUBLIC include)
+
+#-------------------------------------------------------------------------------------------
+# Libraries
+#-------------------------------------------------------------------------------------------
+target_link_libraries(EASTL EABase)
+
+#-------------------------------------------------------------------------------------------
+# Installation
+#-------------------------------------------------------------------------------------------
+install(TARGETS EASTL DESTINATION lib)
+install(DIRECTORY include/EASTL DESTINATION include)
+install(DIRECTORY test/packages/EABase/include/Common/EABase DESTINATION include)
diff --git a/libs/eastl/CONTRIBUTING.md b/libs/eastl/CONTRIBUTING.md
new file mode 100644
index 0000000..74bd209
--- /dev/null
+++ b/libs/eastl/CONTRIBUTING.md
@@ -0,0 +1,71 @@
+## Contributing
+
+Before you can contribute, EA must have a Contributor License Agreement (CLA) on file that has been signed by each contributor.
+You can sign here: [Go to CLA](https://goo.gl/KPylZ3)
+
+### Pull Request Policy
+
+All code contributions to EASTL are submitted as [Github pull requests](https://help.github.com/articles/using-pull-requests/). All pull requests will be reviewed by an EASTL maintainer according to the guidelines found in the next section.
+
+Your pull request should:
+
+* merge cleanly
+* come with tests
+ * tests should be minimal and stable
+ * fail before your fix is applied
+* pass the test suite
+* code formatting is encoded in clang format
+ * limit using clang format on new code
+ * do not deviate from style already established in the files
+
+
+### Running the Unit Tests
+
+EASTL uses CMake as its build system.
+
+* Create and navigate to "your_build_folder":
+ * mkdir your_build_folder && cd your_build_folder
+* Generate build scripts:
+ * cmake eastl_source_folder -DEASTL_BUILD_TESTS:BOOL=ON
+* Build unit tests for "your_config":
+ * cmake --build . --config your_config
+* Run the unit tests for "your_config" from the test folder:
+ * cd test && ctest -C your_config
+
+Here is an example batch file.
+```batch
+set build_folder=out
+mkdir %build_folder%
+pushd %build_folder%
+call cmake .. -DEASTL_BUILD_TESTS:BOOL=ON
+call cmake --build . --config Release
+call cmake --build . --config Debug
+call cmake --build . --config RelWithDebInfo
+call cmake --build . --config MinSizeRel
+pushd test
+call ctest -C Release
+call ctest -C Debug
+call ctest -C RelWithDebInfo
+call ctest -C MinSizeRel
+popd
+popd
+```
+
+Here is an example bash file
+```bash
+build_folder=out
+mkdir $build_folder
+pushd $build_folder
+cmake .. -DEASTL_BUILD_TESTS:BOOL=ON
+cmake --build . --config Release
+cmake --build . --config Debug
+cmake --build . --config RelWithDebInfo
+cmake --build . --config MinSizeRel
+pushd test
+ctest -C Release
+ctest -C Debug
+ctest -C RelWithDebInfo
+ctest -C MinSizeRel
+popd
+popd
+```
diff --git a/libs/eastl/LICENSE b/libs/eastl/LICENSE
new file mode 100644
index 0000000..8a049d0
--- /dev/null
+++ b/libs/eastl/LICENSE
@@ -0,0 +1,27 @@
+/*
+Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/libs/eastl/README.md b/libs/eastl/README.md
new file mode 100644
index 0000000..f928e4f
--- /dev/null
+++ b/libs/eastl/README.md
@@ -0,0 +1,43 @@
+# EA Standard Template Library
+
+[](https://travis-ci.org/electronicarts/EASTL) [](https://ci.appveyor.com/project/rparolin/eastl) [](https://gitter.im/electronicarts/EASTL?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+EASTL stands for Electronic Arts Standard Template Library. It is a C++ template library of containers, algorithms, and iterators useful for runtime and tool development across multiple platforms. It is a fairly extensive and robust implementation of such a library and has an emphasis on high performance above all other considerations.
+
+
+## Usage
+
+If you are familiar with the C++ STL or have worked with other templated container/algorithm libraries, you probably don't need to read this. If you have no familiarity with C++ templates at all, then you probably will need more than this document to get you up to speed. In this case, you need to understand that templates, when used properly, are powerful vehicles for the ease of creation of optimized C++ code. A description of C++ templates is outside the scope of this documentation, but there is plenty of such documentation on the Internet.
+
+EASTL is suitable for any tools and shipping applications where the functionality of EASTL is useful. Modern compilers are capable of producing good code with templates and many people are using them in both current generation and future generation applications on multiple platforms from embedded systems to servers and mainframes.
+
+
+## Documentation
+
+Please see [EASTL Introduction](https://rawgit.com/electronicarts/EASTL/master/doc/EASTL%20Introduction.html).
+
+
+## Compiling sources
+
+Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on compiling and testing the source.
+
+## Credits
+
+EASTL was created by Paul Pedriana and he maintained the project for roughly 10 years.
+
+Roberto Parolin is the current EASTL owner within EA and is responsible for the open source repository.
+
+Significant EASTL contributions were made by (in alphabetical order):
+
+* Avery Lee
+* Colin Andrews
+* JP Flouret
+* Matt Newport
+* Paul Pedriana
+* Roberto Parolin
+* Simon Everett
+
+
+## License
+
+Modified BSD License (3-Clause BSD license) see the file LICENSE in the project root.
diff --git a/libs/eastl/include/EASTL/algorithm.h b/libs/eastl/include/EASTL/algorithm.h
new file mode 100644
index 0000000..19c6401
--- /dev/null
+++ b/libs/eastl/include/EASTL/algorithm.h
@@ -0,0 +1,4167 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// This file implements some of the primary algorithms from the C++ STL
+// algorithm library. These versions are just like that STL versions and so
+// are redundant. They are provided solely for the purpose of projects that
+// either cannot use standard C++ STL or want algorithms that have guaranteed
+// identical behaviour across platforms.
+///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Definitions
+//
+// You will notice that we are very particular about the templated typenames
+// we use here. You will notice that we follow the C++ standard closely in
+// these respects. Each of these typenames have a specific meaning;
+// this is why we don't just label templated arguments with just letters
+// such as T, U, V, A, B. Here we provide a quick reference for the typenames
+// we use. See the C++ standard, section 25-8 for more details.
+// --------------------------------------------------------------
+// typename Meaning
+// --------------------------------------------------------------
+// T The value type.
+// Compare A function which takes two arguments and returns the lesser of the two.
+// Predicate A function which takes one argument returns true if the argument meets some criteria.
+// BinaryPredicate A function which takes two arguments and returns true if some criteria is met (e.g. they are equal).
+// StrickWeakOrdering A BinaryPredicate that compares two objects, returning true if the first precedes the second. Like Compare but has additional requirements. Used for sorting routines.
+// Function A function which takes one argument and applies some operation to the target.
+// Size A count or size.
+// Generator A function which takes no arguments and returns a value (which will usually be assigned to an object).
+// UnaryOperation A function which takes one argument and returns a value (which will usually be assigned to second object).
+// BinaryOperation A function which takes two arguments and returns a value (which will usually be assigned to a third object).
+// InputIterator An input iterator (iterator you read from) which allows reading each element only once and only in a forward direction.
+// ForwardIterator An input iterator which is like InputIterator except it can be reset back to the beginning.
+// BidirectionalIterator An input iterator which is like ForwardIterator except it can be read in a backward direction as well.
+// RandomAccessIterator An input iterator which can be addressed like an array. It is a superset of all other input iterators.
+// OutputIterator An output iterator (iterator you write to) which allows writing each element only once in only in a forward direction.
+//
+// Note that with iterators that a function which takes an InputIterator will
+// also work with a ForwardIterator, BidirectionalIterator, or RandomAccessIterator.
+// The given iterator type is merely the -minimum- supported functionality the
+// iterator must support.
+///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Optimizations
+//
+// There are a number of opportunities for opptimizations that we take here
+// in this library. The most obvious kinds are those that subsitute memcpy
+// in the place of a conventional loop for data types with which this is
+// possible. The algorithms here are optimized to a higher level than currently
+// available C++ STL algorithms from vendors such as Microsoft. This is especially
+// so for game programming on console devices, as we do things such as reduce
+// branching relative to other STL algorithm implementations. However, the
+// proper implementation of these algorithm optimizations is a fairly tricky
+// thing.
+//
+// The various things we look to take advantage of in order to implement
+// optimizations include:
+// - Taking advantage of random access iterators.
+// - Taking advantage of POD (plain old data) data types.
+// - Taking advantage of type_traits in general.
+// - Reducing branching and taking advantage of likely branch predictions.
+// - Taking advantage of issues related to pointer and reference aliasing.
+// - Improving cache coherency during memory accesses.
+// - Making code more likely to be inlinable by the compiler.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Supported Algorithms
+//
+// Algorithms that we implement are listed here. Note that these items are not
+// all within this header file, as we split up the header files in order to
+// improve compilation performance. Items marked with '+' are items that are
+// extensions which don't exist in the C++ standard.
+//
+// -------------------------------------------------------------------------------
+// Algorithm Notes
+// -------------------------------------------------------------------------------
+// adjacent_find
+// adjacent_find
+// all_of C++11
+// any_of C++11
+// none_of C++11
+// binary_search
+// binary_search
+// +binary_search_i
+// +binary_search_i
+// +change_heap Found in heap.h
+// +change_heap Found in heap.h
+// copy
+// copy_if C++11
+// copy_n C++11
+// copy_backward
+// count
+// count_if
+// equal
+// equal
+// equal_range
+// equal_range
+// fill
+// fill_n
+// find
+// find_end
+// find_end
+// find_first_of
+// find_first_of
+// +find_first_not_of
+// +find_first_not_of
+// +find_last_of
+// +find_last_of
+// +find_last_not_of
+// +find_last_not_of
+// find_if
+// find_if_not
+// for_each
+// generate
+// generate_n
+// +identical
+// +identical
+// iter_swap
+// lexicographical_compare
+// lexicographical_compare
+// lower_bound
+// lower_bound
+// make_heap Found in heap.h
+// make_heap Found in heap.h
+// min
+// min
+// max
+// max
+// +min_alt Exists to work around the problem of conflicts with min/max #defines on some systems.
+// +min_alt
+// +max_alt
+// +max_alt
+// +median
+// +median
+// merge Found in sort.h
+// merge Found in sort.h
+// min_element
+// min_element
+// max_element
+// max_element
+// mismatch
+// mismatch
+// move
+// move_backward
+// nth_element Found in sort.h
+// nth_element Found in sort.h
+// partial_sort Found in sort.h
+// partial_sort Found in sort.h
+// push_heap Found in heap.h
+// push_heap Found in heap.h
+// pop_heap Found in heap.h
+// pop_heap Found in heap.h
+// random_shuffle
+// remove
+// remove_if
+// remove_copy
+// remove_copy_if
+// +remove_heap Found in heap.h
+// +remove_heap Found in heap.h
+// replace
+// replace_if
+// replace_copy
+// replace_copy_if
+// reverse_copy
+// reverse
+// rotate
+// rotate_copy
+// search
+// search
+// search_n
+// set_difference
+// set_difference
+// set_intersection
+// set_intersection
+// set_symmetric_difference
+// set_symmetric_difference
+// sort Found in sort.h
+// sort Found in sort.h
+// sort_heap Found in heap.h
+// sort_heap Found in heap.h
+// stable_sort Found in sort.h
+// stable_sort Found in sort.h
+// swap
+// swap_ranges
+// transform
+// transform
+// unique
+// unique
+// upper_bound
+// upper_bound
+// is_permutation
+// is_permutation
+// next_permutation
+// next_permutation
+//
+// Algorithms from the C++ standard that we don't implement are listed here.
+// Most of these items are absent because they aren't used very often.
+// They also happen to be the more complicated than other algorithms.
+// However, we can implement any of these functions for users that might
+// need them.
+// includes
+// includes
+// inplace_merge
+// inplace_merge
+// partial_sort_copy
+// partial_sort_copy
+// paritition
+// prev_permutation
+// prev_permutation
+// random_shuffle
+// search_n
+// set_union
+// set_union
+// stable_partition
+// unique_copy
+// unique_copy
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef EASTL_ALGORITHM_H
+#define EASTL_ALGORITHM_H
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef _MSC_VER
+ #pragma warning(push, 0)
+ #if defined(EA_COMPILER_MICROSOFT) && (defined(EA_PROCESSOR_X86) || defined(EA_PROCESSOR_X86_64))
+ #include
+ #endif
+#endif
+ #include
+ #include // memcpy, memcmp, memmove
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+ #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
+#endif
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// min/max workaround
+//
+// MSVC++ has #defines for min/max which collide with the min/max algorithm
+// declarations. The following may still not completely resolve some kinds of
+// problems with MSVC++ #defines, though it deals with most cases in production
+// game code.
+//
+#if EASTL_NOMINMAX
+ #ifdef min
+ #undef min
+ #endif
+ #ifdef max
+ #undef max
+ #endif
+#endif
+
+
+
+
+namespace eastl
+{
+ /// min_element
+ ///
+ /// min_element finds the smallest element in the range [first, last).
+ /// It returns the first iterator i in [first, last) such that no other
+ /// iterator in [first, last) points to a value smaller than *i.
+ /// The return value is last if and only if [first, last) is an empty range.
+ ///
+ /// Returns: The first iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, last) the following corresponding
+ /// condition holds: !(*j < *i).
+ ///
+ /// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the
+ /// corresponding comparisons.
+ ///
+ template
+ ForwardIterator min_element(ForwardIterator first, ForwardIterator last)
+ {
+ if(first != last)
+ {
+ ForwardIterator currentMin = first;
+
+ while(++first != last)
+ {
+ if(*first < *currentMin)
+ currentMin = first;
+ }
+ return currentMin;
+ }
+ return first;
+ }
+
+
+ /// min_element
+ ///
+ /// min_element finds the smallest element in the range [first, last).
+ /// It returns the first iterator i in [first, last) such that no other
+ /// iterator in [first, last) points to a value smaller than *i.
+ /// The return value is last if and only if [first, last) is an empty range.
+ ///
+ /// Returns: The first iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, last) the following corresponding
+ /// conditions hold: compare(*j, *i) == false.
+ ///
+ /// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the
+ /// corresponding comparisons.
+ ///
+ template
+ ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare compare)
+ {
+ if(first != last)
+ {
+ ForwardIterator currentMin = first;
+
+ while(++first != last)
+ {
+ if(compare(*first, *currentMin))
+ currentMin = first;
+ }
+ return currentMin;
+ }
+ return first;
+ }
+
+
+ /// max_element
+ ///
+ /// max_element finds the largest element in the range [first, last).
+ /// It returns the first iterator i in [first, last) such that no other
+ /// iterator in [first, last) points to a value greater than *i.
+ /// The return value is last if and only if [first, last) is an empty range.
+ ///
+ /// Returns: The first iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, last) the following corresponding
+ /// condition holds: !(*i < *j).
+ ///
+ /// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the
+ /// corresponding comparisons.
+ ///
+ template
+ ForwardIterator max_element(ForwardIterator first, ForwardIterator last)
+ {
+ if(first != last)
+ {
+ ForwardIterator currentMax = first;
+
+ while(++first != last)
+ {
+ if(*currentMax < *first)
+ currentMax = first;
+ }
+ return currentMax;
+ }
+ return first;
+ }
+
+
+ /// max_element
+ ///
+ /// max_element finds the largest element in the range [first, last).
+ /// It returns the first iterator i in [first, last) such that no other
+ /// iterator in [first, last) points to a value greater than *i.
+ /// The return value is last if and only if [first, last) is an empty range.
+ ///
+ /// Returns: The first iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, last) the following corresponding
+ /// condition holds: compare(*i, *j) == false.
+ ///
+ /// Complexity: Exactly 'max((last - first) - 1, 0)' applications of the
+ /// corresponding comparisons.
+ ///
+ template
+ ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare compare)
+ {
+ if(first != last)
+ {
+ ForwardIterator currentMax = first;
+
+ while(++first != last)
+ {
+ if(compare(*currentMax, *first))
+ currentMax = first;
+ }
+ return currentMax;
+ }
+ return first;
+ }
+
+
+ #if EASTL_MINMAX_ENABLED
+
+ /// min
+ ///
+ /// Min returns the lesser of its two arguments; it returns the first
+ /// argument if neither is less than the other. The two arguments are
+ /// compared with operator <.
+ ///
+ /// This min and our other min implementations are defined as returning:
+ /// b < a ? b : a
+ /// which for example may in practice result in something different than:
+ /// b <= a ? b : a
+ /// in the case where b is different from a (though they compare as equal).
+ /// We choose the specific ordering here because that's the ordering
+ /// done by other STL implementations.
+ ///
+ /// Some compilers (e.g. VS20003 - VS2013) generate poor code for the case of
+ /// scalars returned by reference, so we provide a specialization for those cases.
+ /// The specialization returns T by value instead of reference, which is
+ /// not that the Standard specifies. The Standard allows you to use
+ /// an expression like &max(x, y), which would be impossible in this case.
+ /// However, we have found no actual code that uses min or max like this and
+ /// this specialization causes no problems in practice. Microsoft has acknowledged
+ /// the problem and may fix it for a future VS version.
+ ///
+ template
+ inline EA_CONSTEXPR typename eastl::enable_if::value, T>::type
+ min(T a, T b)
+ {
+ return b < a ? b : a;
+ }
+
+ template
+ inline typename eastl::enable_if::value, const T&>::type
+ min(const T& a, const T& b)
+ {
+ return b < a ? b : a;
+ }
+
+ #if defined(_MSC_VER) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ min(float a, float b)
+ {
+ return (float)__fsel(a - b, b, a);
+ }
+
+ inline double
+ min(double a, double b)
+ {
+ return (double)__fsel(a - b, b, a);
+ }
+
+ #elif defined(_MSC_VER) && defined(EA_PROCESSOR_X86)
+
+ // We used to have x86 asm here, but it didn't improve performance.
+
+ #elif defined(__GNUC__) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ min(float a, float b)
+ {
+ float result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (b), "f" (a));
+ return result;
+ }
+
+ inline double
+ min(double a, double b)
+ {
+ double result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (b), "f" (a));
+ return result;
+ }
+ #else
+ inline EA_CONSTEXPR float min(float a, float b) { return b < a ? b : a; }
+ inline EA_CONSTEXPR double min(double a, double b) { return b < a ? b : a; }
+ inline EA_CONSTEXPR long double min(long double a, long double b) { return b < a ? b : a; }
+ #endif
+
+ #endif // EASTL_MINMAX_ENABLED
+
+
+ /// min_alt
+ ///
+ /// This is an alternative version of min that avoids any possible
+ /// collisions with Microsoft #defines of min and max.
+ ///
+ /// See min(a, b) for detailed specifications.
+ ///
+ template
+ inline EA_CONSTEXPR typename eastl::enable_if::value, T>::type
+ min_alt(T a, T b)
+ {
+ return b < a ? b : a;
+ }
+
+ template
+ inline typename eastl::enable_if::value, const T&>::type
+ min_alt(const T& a, const T& b)
+ {
+ return b < a ? b : a;
+ }
+
+
+ #if defined(_MSC_VER) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ min_alt(float a, float b)
+ {
+ return (float)__fsel(a - b, b, a);
+ }
+
+ inline double
+ min_alt(double a, double b)
+ {
+ return (double)__fsel(a - b, b, a);
+ }
+
+ #elif defined(_MSC_VER) && defined(EA_PROCESSOR_X86)
+
+ // We used to have x86 asm here, but it didn't improve performance.
+
+ #elif defined(__GNUC__) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ min_alt(float a, float b)
+ {
+ float result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (b), "f" (a));
+ return result;
+ }
+
+ inline double
+ min_alt(double a, double b)
+ {
+ double result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (b), "f" (a));
+ return result;
+ }
+ #else
+ inline EA_CONSTEXPR float min_alt(float a, float b) { return b < a ? b : a; }
+ inline EA_CONSTEXPR double min_alt(double a, double b) { return b < a ? b : a; }
+ inline EA_CONSTEXPR long double min_alt(long double a, long double b) { return b < a ? b : a; }
+ #endif
+
+
+ #if EASTL_MINMAX_ENABLED
+ /// min
+ ///
+ /// Min returns the lesser of its two arguments; it returns the first
+ /// argument if neither is less than the other. The two arguments are
+ /// compared with the Compare function (or function object), which
+ /// takes two arguments and returns true if the first is less than
+ /// the second.
+ ///
+ /// See min(a, b) for detailed specifications.
+ ///
+ /// Example usage:
+ /// struct A{ int a; };
+ /// struct Struct{ bool operator()(const A& a1, const A& a2){ return a1.a < a2.a; } };
+ ///
+ /// A a1, a2, a3;
+ /// a3 = min(a1, a2, Struct());
+ ///
+ /// Example usage:
+ /// struct B{ int b; };
+ /// inline bool Function(const B& b1, const B& b2){ return b1.b < b2.b; }
+ ///
+ /// B b1, b2, b3;
+ /// b3 = min(b1, b2, Function);
+ ///
+ template
+ inline const T&
+ min(const T& a, const T& b, Compare compare)
+ {
+ return compare(b, a) ? b : a;
+ }
+
+ #endif // EASTL_MINMAX_ENABLED
+
+
+ /// min_alt
+ ///
+ /// This is an alternative version of min that avoids any possible
+ /// collisions with Microsoft #defines of min and max.
+ ///
+ /// See min(a, b) for detailed specifications.
+ ///
+ template
+ inline const T&
+ min_alt(const T& a, const T& b, Compare compare)
+ {
+ return compare(b, a) ? b : a;
+ }
+
+
+ #if EASTL_MINMAX_ENABLED
+ /// max
+ ///
+ /// Max returns the greater of its two arguments; it returns the first
+ /// argument if neither is greater than the other. The two arguments are
+ /// compared with operator < (and not operator >).
+ ///
+ /// This min and our other min implementations are defined as returning:
+ /// a < b ? b : a
+ /// which for example may in practice result in something different than:
+ /// a <= b ? b : a
+ /// in the case where b is different from a (though they compare as equal).
+ /// We choose the specific ordering here because that's the ordering
+ /// done by other STL implementations.
+ ///
+ template
+ inline EA_CONSTEXPR typename eastl::enable_if::value, T>::type
+ max(T a, T b)
+ {
+ return a < b ? b : a;
+ }
+
+ template
+ inline typename eastl::enable_if::value, const T&>::type
+ max(const T& a, const T& b)
+ {
+ return a < b ? b : a;
+ }
+
+
+ #if defined(_MSC_VER) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ max(float a, float b)
+ {
+ return (float)__fsel(a - b, a, b);
+ }
+
+ inline double
+ max(double a, double b)
+ {
+ return (double)__fsel(a - b, a, b);
+ }
+
+ #elif defined(_MSC_VER) && defined(EA_PROCESSOR_X86)
+
+ // We used to have x86 asm here, but it didn't improve performance.
+
+ #elif defined(__GNUC__) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ max(float a, float b)
+ {
+ float result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (a), "f" (b));
+ return result;
+ }
+
+ inline double
+ max(double a, double b)
+ {
+ double result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (a), "f" (b));
+ return result;
+ }
+ #else
+ inline EA_CONSTEXPR float max(float a, float b) { return a < b ? b : a; }
+ inline EA_CONSTEXPR double max(double a, double b) { return a < b ? b : a; }
+ inline EA_CONSTEXPR long double max(long double a, long double b) { return a < b ? b : a; }
+ #endif
+
+ #endif // EASTL_MINMAX_ENABLED
+
+
+ /// max_alt
+ ///
+ /// This is an alternative version of max that avoids any possible
+ /// collisions with Microsoft #defines of min and max.
+ ///
+ template
+ inline EA_CONSTEXPR typename eastl::enable_if::value, T>::type
+ max_alt(T a, T b)
+ {
+ return a < b ? b : a;
+ }
+
+ template
+ inline typename eastl::enable_if::value, const T&>::type
+ max_alt(const T& a, const T& b)
+ {
+ return a < b ? b : a;
+ }
+
+ #if defined(_MSC_VER) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ max_alt(float a, float b)
+ {
+ return (float)__fsel(a - b, a, b);
+ }
+
+ inline double
+ max_alt(double a, double b)
+ {
+ return (double)__fsel(a - b, a, b);
+ }
+
+ #elif defined(_MSC_VER) && defined(EA_PROCESSOR_X86)
+
+ // We used to have x86 asm here, but it didn't improve performance.
+
+ #elif defined(__GNUC__) && defined(EA_PROCESSOR_POWERPC)
+ inline float
+ max_alt(float a, float b)
+ {
+ float result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (a), "f" (b));
+ return result;
+ }
+
+ inline double
+ max_alt(double a, double b)
+ {
+ double result, test(a - b);
+ __asm__ ("fsel %0, %1, %2, %3" : "=f" (result) : "f" (test), "f" (a), "f" (b));
+ return result;
+ }
+ #else
+ inline EA_CONSTEXPR float max_alt(float a, float b) { return a < b ? b : a; }
+ inline EA_CONSTEXPR double max_alt(double a, double b) { return a < b ? b : a; }
+ inline EA_CONSTEXPR long double max_alt(long double a, long double b) { return a < b ? b : a; }
+ #endif
+
+
+ #if EASTL_MINMAX_ENABLED
+ /// max
+ ///
+ /// Min returns the lesser of its two arguments; it returns the first
+ /// argument if neither is less than the other. The two arguments are
+ /// compared with the Compare function (or function object), which
+ /// takes two arguments and returns true if the first is less than
+ /// the second.
+ ///
+ template
+ inline const T&
+ max(const T& a, const T& b, Compare compare)
+ {
+ return compare(a, b) ? b : a;
+ }
+ #endif
+
+
+ /// max_alt
+ ///
+ /// This is an alternative version of max that avoids any possible
+ /// collisions with Microsoft #defines of min and max.
+ ///
+ template
+ inline const T&
+ max_alt(const T& a, const T& b, Compare compare)
+ {
+ return compare(a, b) ? b : a;
+ }
+
+
+ /// min(std::initializer_list)
+ ///
+ template
+ T min(std::initializer_list ilist)
+ {
+ return *eastl::min_element(ilist.begin(), ilist.end());
+ }
+
+ /// min(std::initializer_list, Compare)
+ ///
+ template
+ T min(std::initializer_list ilist, Compare compare)
+ {
+ return *eastl::min_element(ilist.begin(), ilist.end(), compare);
+ }
+
+
+ /// max(std::initializer_list)
+ ///
+ template
+ T max(std::initializer_list ilist)
+ {
+ return *eastl::max_element(ilist.begin(), ilist.end());
+ }
+
+ /// max(std::initializer_list, Compare)
+ ///
+ template
+ T max(std::initializer_list ilist, Compare compare)
+ {
+ return *eastl::max_element(ilist.begin(), ilist.end(), compare);
+ }
+
+
+ /// minmax_element
+ ///
+ /// Returns: make_pair(first, first) if [first, last) is empty, otherwise make_pair(m, M),
+ /// where m is the first iterator in [first,last) such that no iterator in the range
+ /// refers to a smaller element, and where M is the last iterator in [first,last) such
+ /// that no iterator in the range refers to a larger element.
+ ///
+ /// Complexity: At most max([(3/2)*(N - 1)], 0) applications of the corresponding predicate,
+ /// where N is distance(first, last).
+ ///
+ template
+ eastl::pair
+ minmax_element(ForwardIterator first, ForwardIterator last, Compare compare)
+ {
+ eastl::pair result(first, first);
+
+ if(!(first == last) && !(++first == last))
+ {
+ if(compare(*first, *result.first))
+ {
+ result.second = result.first;
+ result.first = first;
+ }
+ else
+ result.second = first;
+
+ while(++first != last)
+ {
+ ForwardIterator i = first;
+
+ if(++first == last)
+ {
+ if(compare(*i, *result.first))
+ result.first = i;
+ else if(!compare(*i, *result.second))
+ result.second = i;
+ break;
+ }
+ else
+ {
+ if(compare(*first, *i))
+ {
+ if(compare(*first, *result.first))
+ result.first = first;
+
+ if(!compare(*i, *result.second))
+ result.second = i;
+ }
+ else
+ {
+ if(compare(*i, *result.first))
+ result.first = i;
+
+ if(!compare(*first, *result.second))
+ result.second = first;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ template
+ eastl::pair
+ minmax_element(ForwardIterator first, ForwardIterator last)
+ {
+ typedef typename eastl::iterator_traits::value_type value_type;
+
+ return eastl::minmax_element(first, last, eastl::less());
+ }
+
+
+
+ /// minmax
+ ///
+ /// Requires: Type T shall be LessThanComparable.
+ /// Returns: pair(b, a) if b is smaller than a, and pair(a, b) otherwise.
+ /// Remarks: Returns pair(a, b) when the arguments are equivalent.
+ /// Complexity: Exactly one comparison.
+ ///
+
+ // The following optimization is a problem because it changes the return value in a way that would break
+ // users unless they used auto (e.g. auto result = minmax(17, 33); )
+ //
+ // template
+ // inline EA_CONSTEXPR typename eastl::enable_if::value, eastl::pair >::type
+ // minmax(T a, T b)
+ // {
+ // return (b < a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);
+ // }
+ //
+ // template
+ // inline typename eastl::enable_if::value, eastl::pair >::type
+ // minmax(const T& a, const T& b)
+ // {
+ // return (b < a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);
+ // }
+
+ // It turns out that the following conforming definition of minmax generates a warning when used with VC++ up
+ // to at least VS2012. The VS2012 version of minmax is a broken and non-conforming definition, and we don't
+ // want to do that. We could do it for scalars alone, though we'd have to decide if we are going to do that
+ // for all compilers, because it changes the return value from a pair of references to a pair of values.
+ template
+ inline eastl::pair
+ minmax(const T& a, const T& b)
+ {
+ return (b < a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);
+ }
+
+
+ template
+ eastl::pair
+ minmax(const T& a, const T& b, Compare compare)
+ {
+ return compare(b, a) ? eastl::make_pair(b, a) : eastl::make_pair(a, b);
+ }
+
+
+
+ template
+ eastl::pair
+ minmax(std::initializer_list ilist)
+ {
+ typedef typename std::initializer_list::iterator iterator_type;
+ eastl::pair iteratorPair = eastl::minmax_element(ilist.begin(), ilist.end());
+ return eastl::make_pair(*iteratorPair.first, *iteratorPair.second);
+ }
+
+ template
+ eastl::pair
+ minmax(std::initializer_list ilist, Compare compare)
+ {
+ typedef typename std::initializer_list::iterator iterator_type;
+ eastl::pair iteratorPair = eastl::minmax_element(ilist.begin(), ilist.end(), compare);
+ return eastl::make_pair(*iteratorPair.first, *iteratorPair.second);
+ }
+
+
+ /// median
+ ///
+ /// median finds which element of three (a, b, d) is in-between the other two.
+ /// If two or more elements are equal, the first (e.g. a before b) is chosen.
+ ///
+ /// Complexity: Either two or three comparisons will be required, depending
+ /// on the values.
+ ///
+ template
+ inline const T& median(const T& a, const T& b, const T& c)
+ {
+ if(a < b)
+ {
+ if(b < c)
+ return b;
+ else if(a < c)
+ return c;
+ else
+ return a;
+ }
+ else if(a < c)
+ return a;
+ else if(b < c)
+ return c;
+ return b;
+ }
+
+
+ /// median
+ ///
+ /// median finds which element of three (a, b, d) is in-between the other two.
+ /// If two or more elements are equal, the first (e.g. a before b) is chosen.
+ ///
+ /// Complexity: Either two or three comparisons will be required, depending
+ /// on the values.
+ ///
+ template
+ inline const T& median(const T& a, const T& b, const T& c, Compare compare)
+ {
+ if(compare(a, b))
+ {
+ if(compare(b, c))
+ return b;
+ else if(compare(a, c))
+ return c;
+ else
+ return a;
+ }
+ else if(compare(a, c))
+ return a;
+ else if(compare(b, c))
+ return c;
+ return b;
+ }
+
+
+
+
+ /// all_of
+ ///
+ /// Returns: true if the unary predicate p returns true for all elements in the range [first, last)
+ ///
+ template
+ inline bool all_of(InputIterator first, InputIterator last, Predicate p)
+ {
+ for(; first != last; ++first)
+ {
+ if(!p(*first))
+ return false;
+ }
+ return true;
+ }
+
+
+ /// any_of
+ ///
+ /// Returns: true if the unary predicate p returns true for any of the elements in the range [first, last)
+ ///
+ template
+ inline bool any_of(InputIterator first, InputIterator last, Predicate p)
+ {
+ for(; first != last; ++first)
+ {
+ if(p(*first))
+ return true;
+ }
+ return false;
+ }
+
+
+ /// none_of
+ ///
+ /// Returns: true if the unary predicate p returns true for none of the elements in the range [first, last)
+ ///
+ template
+ inline bool none_of(InputIterator first, InputIterator last, Predicate p)
+ {
+ for(; first != last; ++first)
+ {
+ if(p(*first))
+ return false;
+ }
+ return true;
+ }
+
+
+ /// adjacent_find
+ ///
+ /// Returns: The first iterator i such that both i and i + 1 are in the range
+ /// [first, last) for which the following corresponding conditions hold: *i == *(i + 1).
+ /// Returns last if no such iterator is found.
+ ///
+ /// Complexity: Exactly 'find(first, last, value) - first' applications of the corresponding predicate.
+ ///
+ template
+ inline ForwardIterator
+ adjacent_find(ForwardIterator first, ForwardIterator last)
+ {
+ if(first != last)
+ {
+ ForwardIterator i = first;
+
+ for(++i; i != last; ++i)
+ {
+ if(*first == *i)
+ return first;
+ first = i;
+ }
+ }
+ return last;
+ }
+
+
+
+ /// adjacent_find
+ ///
+ /// Returns: The first iterator i such that both i and i + 1 are in the range
+ /// [first, last) for which the following corresponding conditions hold: predicate(*i, *(i + 1)) != false.
+ /// Returns last if no such iterator is found.
+ ///
+ /// Complexity: Exactly 'find(first, last, value) - first' applications of the corresponding predicate.
+ ///
+ template
+ inline ForwardIterator
+ adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate predicate)
+ {
+ if(first != last)
+ {
+ ForwardIterator i = first;
+
+ for(++i; i != last; ++i)
+ {
+ if(predicate(*first, *i))
+ return first;
+ first = i;
+ }
+ }
+ return last;
+ }
+
+
+ /// shuffle
+ ///
+ /// New for C++11
+ /// Randomizes a sequence of values via a user-supplied UniformRandomNumberGenerator.
+ /// The difference between this and the original random_shuffle function is that this uses the more
+ /// advanced and flexible UniformRandomNumberGenerator interface as opposed to the more
+ /// limited RandomNumberGenerator interface of random_shuffle.
+ ///
+ /// Effects: Shuffles the elements in the range [first, last) with uniform distribution.
+ ///
+ /// Complexity: Exactly '(last - first) - 1' swaps.
+ ///
+ /// Example usage:
+ /// struct Rand{ eastl_size_t operator()(eastl_size_t n) { return (eastl_size_t)(rand() % n); } }; // Note: The C rand function is poor and slow.
+ /// Rand randInstance;
+ /// shuffle(pArrayBegin, pArrayEnd, randInstance);
+ ///
+ #if EASTL_MOVE_SEMANTICS_ENABLED
+ // See the C++11 Standard, 26.5.1.3, Uniform random number generator requirements.
+ // Also http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
+
+ template
+ void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomNumberGenerator&& urng)
+ {
+ if(first != last)
+ {
+ typedef typename eastl::iterator_traits::difference_type difference_type;
+ typedef typename eastl::make_unsigned::type unsigned_difference_type;
+ typedef typename eastl::uniform_int_distribution uniform_int_distribution;
+ typedef typename uniform_int_distribution::param_type uniform_int_distribution_param_type;
+
+ uniform_int_distribution uid;
+
+ for(RandomAccessIterator i = first + 1; i != last; ++i)
+ iter_swap(i, first + uid(urng, uniform_int_distribution_param_type(0, i - first)));
+ }
+ }
+ #endif
+
+
+ /// random_shuffle
+ ///
+ /// Randomizes a sequence of values.
+ ///
+ /// Effects: Shuffles the elements in the range [first, last) with uniform distribution.
+ ///
+ /// Complexity: Exactly '(last - first) - 1' swaps.
+ ///
+ /// Example usage:
+ /// eastl_size_t Rand(eastl_size_t n) { return (eastl_size_t)(rand() % n); } // Note: The C rand function is poor and slow.
+ /// pointer_to_unary_function randInstance(Rand);
+ /// random_shuffle(pArrayBegin, pArrayEnd, randInstance);
+ ///
+ /// Example usage:
+ /// struct Rand{ eastl_size_t operator()(eastl_size_t n) { return (eastl_size_t)(rand() % n); } }; // Note: The C rand function is poor and slow.
+ /// Rand randInstance;
+ /// random_shuffle(pArrayBegin, pArrayEnd, randInstance);
+ ///
+ #if EASTL_MOVE_SEMANTICS_ENABLED
+ template
+ inline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& rng)
+ #else
+ template
+ inline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rng)
+ #endif
+ {
+ typedef typename eastl::iterator_traits::difference_type difference_type;
+
+ // We must do 'rand((i - first) + 1)' here and cannot do 'rand(last - first)',
+ // as it turns out that the latter results in unequal distribution probabilities.
+ // http://www.cigital.com/papers/download/developer_gambling.php
+
+ for(RandomAccessIterator i = first + 1; i < last; ++i)
+ iter_swap(i, first + (difference_type)rng((eastl_size_t)((i - first) + 1)));
+ }
+
+
+ /// random_shuffle
+ ///
+ /// Randomizes a sequence of values.
+ ///
+ /// Effects: Shuffles the elements in the range [first, last) with uniform distribution.
+ ///
+ /// Complexity: Exactly '(last - first) - 1' swaps.
+ ///
+ /// Example usage:
+ /// random_shuffle(pArrayBegin, pArrayEnd);
+ ///
+ /// *** Disabled until we decide if we want to get into the business of writing random number generators. ***
+ ///
+ /// template
+ /// inline void random_shuffle(RandomAccessIterator first, RandomAccessIterator last)
+ /// {
+ /// for(RandomAccessIterator i = first + 1; i < last; ++i)
+ /// iter_swap(i, first + SomeRangedRandomNumberGenerator((i - first) + 1));
+ /// }
+
+
+
+
+
+
+ /// move_n
+ ///
+ /// Same as move(InputIterator, InputIterator, OutputIterator) except based on count instead of iterator range.
+ ///
+ template
+ inline OutputIterator
+ move_n_impl(InputIterator first, Size n, OutputIterator result, EASTL_ITC_NS::input_iterator_tag)
+ {
+ for(; n > 0; --n)
+ *result++ = eastl::move(*first++);
+ return result;
+ }
+
+ template
+ inline OutputIterator
+ move_n_impl(RandomAccessIterator first, Size n, OutputIterator result, EASTL_ITC_NS::random_access_iterator_tag)
+ {
+ return eastl::move(first, first + n, result); // Take advantage of the optimizations present in the move algorithm.
+ }
+
+
+ template
+ inline OutputIterator
+ move_n(InputIterator first, Size n, OutputIterator result)
+ {
+ typedef typename eastl::iterator_traits::iterator_category IC;
+ return eastl::move_n_impl(first, n, result, IC());
+ }
+
+
+
+ /// copy_n
+ ///
+ /// Same as copy(InputIterator, InputIterator, OutputIterator) except based on count instead of iterator range.
+ /// Effects: Copies exactly count values from the range beginning at first to the range beginning at result, if count > 0. Does nothing otherwise.
+ /// Returns: Iterator in the destination range, pointing past the last element copied if count>0 or first otherwise.
+ /// Complexity: Exactly count assignments, if count > 0.
+ ///
+ template
+ inline OutputIterator
+ copy_n_impl(InputIterator first, Size n, OutputIterator result, EASTL_ITC_NS::input_iterator_tag)
+ {
+ for(; n > 0; --n)
+ *result++ = *first++;
+ return result;
+ }
+
+ template
+ inline OutputIterator
+ copy_n_impl(RandomAccessIterator first, Size n, OutputIterator result, EASTL_ITC_NS::random_access_iterator_tag)
+ {
+ return eastl::copy(first, first + n, result); // Take advantage of the optimizations present in the copy algorithm.
+ }
+
+
+ template
+ inline OutputIterator
+ copy_n(InputIterator first, Size n, OutputIterator result)
+ {
+ typedef typename eastl::iterator_traits::iterator_category IC;
+ return eastl::copy_n_impl(first, n, result, IC());
+ }
+
+
+ /// copy_if
+ ///
+ /// Effects: Assigns to the result iterator only if the predicate is true.
+ ///
+ template
+ inline OutputIterator
+ copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate)
+ {
+ // This implementation's performance could be improved by taking a more complicated approach like with the copy algorithm.
+ for(; first != last; ++first)
+ {
+ if(predicate(*first))
+ *result++ = *first;
+ }
+
+ return result;
+ }
+
+
+
+
+ // Implementation moving copying both trivial and non-trivial data via a lesser iterator than random-access.
+ template
+ struct move_and_copy_backward_helper
+ {
+ template
+ static BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ while(first != last)
+ *--resultEnd = *--last;
+ return resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.
+ }
+ };
+
+ // Specialization for moving non-trivial data via a lesser iterator than random-access.
+ template
+ struct move_and_copy_backward_helper
+ {
+ template
+ static BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ while(first != last)
+ *--resultEnd = eastl::move(*--last);
+ return resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.
+ }
+ };
+
+ // Specialization for moving non-trivial data via a random-access iterator. It's theoretically faster because the compiler can see the count when its a compile-time const.
+ template<>
+ struct move_and_copy_backward_helper
+ {
+ template
+ static BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ typedef typename eastl::iterator_traits::difference_type difference_type;
+
+ for(difference_type n = (last - first); n > 0; --n)
+ *--resultEnd = eastl::move(*--last);
+ return resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.
+ }
+ };
+
+ // Specialization for copying non-trivial data via a random-access iterator. It's theoretically faster because the compiler can see the count when its a compile-time const.
+ // This specialization converts the random access BidirectionalIterator1 last-first to an integral type. There's simple way for us to take advantage of a random access output iterator,
+ // as the range is specified by the input instead of the output, and distance(first, last) for a non-random-access iterator is potentially slow.
+ template <>
+ struct move_and_copy_backward_helper
+ {
+ template
+ static BidirectionalIterator2 move_or_copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ typedef typename eastl::iterator_traits::difference_type difference_type;
+
+ for(difference_type n = (last - first); n > 0; --n)
+ *--resultEnd = *--last;
+ return resultEnd; // resultEnd now points to the beginning of the destination sequence instead of the end.
+ }
+ };
+
+ // Specialization for when we can use memmove/memcpy. See the notes above for what conditions allow this.
+ template
+ struct move_and_copy_backward_helper
+ {
+ template
+ static T* move_or_copy_backward(const T* first, const T* last, T* resultEnd)
+ {
+ return (T*)memmove(resultEnd - (last - first), first, (size_t)((uintptr_t)last - (uintptr_t)first));
+ // We could use memcpy here if there's no range overlap, but memcpy is rarely much faster than memmove.
+ }
+ };
+
+ template
+ inline BidirectionalIterator2 move_and_copy_backward_chooser(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ typedef typename eastl::iterator_traits::iterator_category IIC;
+ typedef typename eastl::iterator_traits::iterator_category OIC;
+ typedef typename eastl::iterator_traits::value_type value_type_input;
+ typedef typename eastl::iterator_traits::value_type value_type_output;
+
+ const bool canBeMemmoved = eastl::is_trivially_copyable::value &&
+ eastl::is_same::value &&
+ (eastl::is_pointer::value || eastl::is_same::value) &&
+ (eastl::is_pointer::value || eastl::is_same::value);
+
+ return eastl::move_and_copy_backward_helper::move_or_copy_backward(first, last, resultEnd); // Need to chose based on the input iterator tag and not the output iterator tag, because containers accept input ranges of iterator types different than self.
+ }
+
+
+ // We have a second layer of unwrap_iterator calls because the original iterator might be something like move_iterator > (i.e. doubly-wrapped).
+ template
+ inline BidirectionalIterator2 move_and_copy_backward_unwrapper(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ return BidirectionalIterator2(eastl::move_and_copy_backward_chooser(eastl::unwrap_iterator(first), eastl::unwrap_iterator(last), eastl::unwrap_iterator(resultEnd))); // Have to convert to BidirectionalIterator2 because result.base() could be a T*
+ }
+
+
+ /// move_backward
+ ///
+ /// The elements are moved in reverse order (the last element is moved first), but their relative order is preserved.
+ /// After this operation the elements in the moved-from range will still contain valid values of the
+ /// appropriate type, but not necessarily the same values as before the move.
+ /// Returns the beginning of the result range.
+ /// Note: When moving between containers, the dest range must be valid; this function doesn't resize containers.
+ /// Note: If result is within [first, last), move must be used instead of move_backward.
+ ///
+ /// Example usage:
+ /// eastl::move_backward(myArray.begin(), myArray.end(), myDestArray.end());
+ ///
+ /// Reference implementation:
+ /// template
+ /// BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ /// {
+ /// while(last != first)
+ /// *--resultEnd = eastl::move(*--last);
+ /// return resultEnd;
+ /// }
+ ///
+ template
+ inline BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ return eastl::move_and_copy_backward_unwrapper(eastl::unwrap_iterator(first), eastl::unwrap_iterator(last), resultEnd);
+ }
+
+
+ /// copy_backward
+ ///
+ /// copies memory in the range of [first, last) to the range *ending* with result.
+ ///
+ /// Effects: Copies elements in the range [first, last) into the range
+ /// [result - (last - first), result) starting from last 1 and proceeding to first.
+ /// For each positive integer n <= (last - first), performs *(result n) = *(last - n).
+ ///
+ /// Requires: result shall not be in the range [first, last).
+ ///
+ /// Returns: result - (last - first). That is, returns the beginning of the result range.
+ ///
+ /// Complexity: Exactly 'last - first' assignments.
+ ///
+ template
+ inline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 resultEnd)
+ {
+ const bool isMove = eastl::is_move_iterator::value; EA_UNUSED(isMove);
+
+ return eastl::move_and_copy_backward_unwrapper(eastl::unwrap_iterator(first), eastl::unwrap_iterator(last), resultEnd);
+ }
+
+
+ /// count
+ ///
+ /// Counts the number of items in the range of [first, last) which equal the input value.
+ ///
+ /// Effects: Returns the number of iterators i in the range [first, last) for which the
+ /// following corresponding conditions hold: *i == value.
+ ///
+ /// Complexity: At most 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of count is count_if and not another variation of count.
+ /// This is because both versions would have three parameters and there could be ambiguity.
+ ///
+ template
+ inline typename eastl::iterator_traits::difference_type
+ count(InputIterator first, InputIterator last, const T& value)
+ {
+ typename eastl::iterator_traits::difference_type result = 0;
+
+ for(; first != last; ++first)
+ {
+ if(*first == value)
+ ++result;
+ }
+ return result;
+ }
+
+
+ // C++ doesn't define a count with predicate, as it can effectively be synthesized via count_if
+ // with an appropriate predicate. However, it's often simpler to just have count with a predicate.
+ template
+ inline typename eastl::iterator_traits::difference_type
+ count(InputIterator first, InputIterator last, const T& value, Predicate predicate)
+ {
+ typename eastl::iterator_traits::difference_type result = 0;
+
+ for(; first != last; ++first)
+ {
+ if(predicate(*first, value))
+ ++result;
+ }
+ return result;
+ }
+
+
+ /// count_if
+ ///
+ /// Counts the number of items in the range of [first, last) which match
+ /// the input value as defined by the input predicate function.
+ ///
+ /// Effects: Returns the number of iterators i in the range [first, last) for which the
+ /// following corresponding conditions hold: predicate(*i) != false.
+ ///
+ /// Complexity: At most 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The non-predicate version of count_if is count and not another variation of count_if.
+ /// This is because both versions would have three parameters and there could be ambiguity.
+ ///
+ template
+ inline typename eastl::iterator_traits::difference_type
+ count_if(InputIterator first, InputIterator last, Predicate predicate)
+ {
+ typename eastl::iterator_traits::difference_type result = 0;
+
+ for(; first != last; ++first)
+ {
+ if(predicate(*first))
+ ++result;
+ }
+ return result;
+ }
+
+
+ /// find
+ ///
+ /// finds the value within the unsorted range of [first, last).
+ ///
+ /// Returns: The first iterator i in the range [first, last) for which
+ /// the following corresponding conditions hold: *i == value.
+ /// Returns last if no such iterator is found.
+ ///
+ /// Complexity: At most 'last - first' applications of the corresponding predicate.
+ /// This is a linear search and not a binary one.
+ ///
+ /// Note: The predicate version of find is find_if and not another variation of find.
+ /// This is because both versions would have three parameters and there could be ambiguity.
+ ///
+ template
+ inline InputIterator
+ find(InputIterator first, InputIterator last, const T& value)
+ {
+ while((first != last) && !(*first == value)) // Note that we always express value comparisons in terms of < or ==.
+ ++first;
+ return first;
+ }
+
+
+ // C++ doesn't define a find with predicate, as it can effectively be synthesized via find_if
+ // with an appropriate predicate. However, it's often simpler to just have find with a predicate.
+ template
+ inline InputIterator
+ find(InputIterator first, InputIterator last, const T& value, Predicate predicate)
+ {
+ while((first != last) && !predicate(*first, value))
+ ++first;
+ return first;
+ }
+
+
+
+ /// find_if
+ ///
+ /// finds the value within the unsorted range of [first, last).
+ ///
+ /// Returns: The first iterator i in the range [first, last) for which
+ /// the following corresponding conditions hold: pred(*i) != false.
+ /// Returns last if no such iterator is found.
+ /// If the sequence of elements to search for (i.e. first2 - last2) is empty,
+ /// the find always fails and last1 will be returned.
+ ///
+ /// Complexity: At most 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The non-predicate version of find_if is find and not another variation of find_if.
+ /// This is because both versions would have three parameters and there could be ambiguity.
+ ///
+ template
+ inline InputIterator
+ find_if(InputIterator first, InputIterator last, Predicate predicate)
+ {
+ while((first != last) && !predicate(*first))
+ ++first;
+ return first;
+ }
+
+
+
+ /// find_if_not
+ ///
+ /// find_if_not works the same as find_if except it tests for if the predicate
+ /// returns false for the elements instead of true.
+ ///
+ template
+ inline InputIterator
+ find_if_not(InputIterator first, InputIterator last, Predicate predicate)
+ {
+ for(; first != last; ++first)
+ {
+ if(!predicate(*first))
+ return first;
+ }
+ return last;
+ }
+
+
+
+
+ /// find_first_of
+ ///
+ /// find_first_of is similar to find in that it performs linear search through
+ /// a range of ForwardIterators. The difference is that while find searches
+ /// for one particular value, find_first_of searches for any of several values.
+ /// Specifically, find_first_of searches for the first occurrance in the
+ /// range [first1, last1) of any of the elements in [first2, last2).
+ /// This function is thus similar to the strpbrk standard C string function.
+ /// If the sequence of elements to search for (i.e. first2-last2) is empty,
+ /// the find always fails and last1 will be returned.
+ ///
+ /// Effects: Finds an element that matches one of a set of values.
+ ///
+ /// Returns: The first iterator i in the range [first1, last1) such that for some
+ /// integer j in the range [first2, last2) the following conditions hold: *i == *j.
+ /// Returns last1 if no such iterator is found.
+ ///
+ /// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the
+ /// corresponding predicate.
+ ///
+ template
+ ForwardIterator1
+ find_first_of(ForwardIterator1 first1, ForwardIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2)
+ {
+ for(; first1 != last1; ++first1)
+ {
+ for(ForwardIterator2 i = first2; i != last2; ++i)
+ {
+ if(*first1 == *i)
+ return first1;
+ }
+ }
+ return last1;
+ }
+
+
+ /// find_first_of
+ ///
+ /// find_first_of is similar to find in that it performs linear search through
+ /// a range of ForwardIterators. The difference is that while find searches
+ /// for one particular value, find_first_of searches for any of several values.
+ /// Specifically, find_first_of searches for the first occurrance in the
+ /// range [first1, last1) of any of the elements in [first2, last2).
+ /// This function is thus similar to the strpbrk standard C string function.
+ ///
+ /// Effects: Finds an element that matches one of a set of values.
+ ///
+ /// Returns: The first iterator i in the range [first1, last1) such that for some
+ /// integer j in the range [first2, last2) the following conditions hold: pred(*i, *j) != false.
+ /// Returns last1 if no such iterator is found.
+ ///
+ /// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the
+ /// corresponding predicate.
+ ///
+ template
+ ForwardIterator1
+ find_first_of(ForwardIterator1 first1, ForwardIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2,
+ BinaryPredicate predicate)
+ {
+ for(; first1 != last1; ++first1)
+ {
+ for(ForwardIterator2 i = first2; i != last2; ++i)
+ {
+ if(predicate(*first1, *i))
+ return first1;
+ }
+ }
+ return last1;
+ }
+
+
+ /// find_first_not_of
+ ///
+ /// Searches through first range for the first element that does not belong the second input range.
+ /// This is very much like the C++ string find_first_not_of function.
+ ///
+ /// Returns: The first iterator i in the range [first1, last1) such that for some
+ /// integer j in the range [first2, last2) the following conditions hold: !(*i == *j).
+ /// Returns last1 if no such iterator is found.
+ ///
+ /// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the
+ /// corresponding predicate.
+ ///
+ template
+ ForwardIterator1
+ find_first_not_of(ForwardIterator1 first1, ForwardIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2)
+ {
+ for(; first1 != last1; ++first1)
+ {
+ if(eastl::find(first2, last2, *first1) == last2)
+ break;
+ }
+
+ return first1;
+ }
+
+
+
+ /// find_first_not_of
+ ///
+ /// Searches through first range for the first element that does not belong the second input range.
+ /// This is very much like the C++ string find_first_not_of function.
+ ///
+ /// Returns: The first iterator i in the range [first1, last1) such that for some
+ /// integer j in the range [first2, last2) the following conditions hold: pred(*i, *j) == false.
+ /// Returns last1 if no such iterator is found.
+ ///
+ /// Complexity: At most '(last1 - first1) * (last2 - first2)' applications of the
+ /// corresponding predicate.
+ ///
+ template
+ inline ForwardIterator1
+ find_first_not_of(ForwardIterator1 first1, ForwardIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2,
+ BinaryPredicate predicate)
+ {
+ typedef typename eastl::iterator_traits::value_type value_type;
+
+ for(; first1 != last1; ++first1)
+ {
+ if(eastl::find_if(first2, last2, eastl::bind1st(predicate, *first1)) == last2)
+ break;
+ }
+
+ return first1;
+ }
+
+
+ template
+ inline BidirectionalIterator1
+ find_last_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2)
+ {
+ if((first1 != last1) && (first2 != last2))
+ {
+ BidirectionalIterator1 it1(last1);
+
+ while((--it1 != first1) && (eastl::find(first2, last2, *it1) == last2))
+ ; // Do nothing
+
+ if((it1 != first1) || (eastl::find(first2, last2, *it1) != last2))
+ return it1;
+ }
+
+ return last1;
+ }
+
+
+ template
+ BidirectionalIterator1
+ find_last_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2,
+ BinaryPredicate predicate)
+ {
+ typedef typename eastl::iterator_traits::value_type value_type;
+
+ if((first1 != last1) && (first2 != last2))
+ {
+ BidirectionalIterator1 it1(last1);
+
+ while((--it1 != first1) && (eastl::find_if(first2, last2, eastl::bind1st(predicate, *it1)) == last2))
+ ; // Do nothing
+
+ if((it1 != first1) || (eastl::find_if(first2, last2, eastl::bind1st(predicate, *it1)) != last2))
+ return it1;
+ }
+
+ return last1;
+ }
+
+
+ template
+ inline BidirectionalIterator1
+ find_last_not_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2)
+ {
+ if((first1 != last1) && (first2 != last2))
+ {
+ BidirectionalIterator1 it1(last1);
+
+ while((--it1 != first1) && (eastl::find(first2, last2, *it1) != last2))
+ ; // Do nothing
+
+ if((it1 != first1) || (eastl::find( first2, last2, *it1) == last2))
+ return it1;
+ }
+
+ return last1;
+ }
+
+
+ template
+ inline BidirectionalIterator1
+ find_last_not_of(BidirectionalIterator1 first1, BidirectionalIterator1 last1,
+ ForwardIterator2 first2, ForwardIterator2 last2,
+ BinaryPredicate predicate)
+ {
+ typedef typename eastl::iterator_traits::value_type value_type;
+
+ if((first1 != last1) && (first2 != last2))
+ {
+ BidirectionalIterator1 it1(last1);
+
+ while((--it1 != first1) && (eastl::find_if(first2, last2, eastl::bind1st(predicate, *it1)) != last2))
+ ; // Do nothing
+
+ if((it1 != first1) || (eastl::find_if(first2, last2, eastl::bind1st(predicate, *it1))) != last2)
+ return it1;
+ }
+
+ return last1;
+ }
+
+
+
+
+ /// for_each
+ ///
+ /// Calls the Function function for each value in the range [first, last).
+ /// Function takes a single parameter: the current value.
+ ///
+ /// Effects: Applies function to the result of dereferencing every iterator in
+ /// the range [first, last), starting from first and proceeding to last 1.
+ ///
+ /// Returns: function.
+ ///
+ /// Complexity: Applies function exactly 'last - first' times.
+ ///
+ /// Note: If function returns a result, the result is ignored.
+ ///
+ template
+ inline Function
+ for_each(InputIterator first, InputIterator last, Function function)
+ {
+ for(; first != last; ++first)
+ function(*first);
+ return function;
+ }
+
+
+ /// generate
+ ///
+ /// Iterates the range of [first, last) and assigns to each element the
+ /// result of the function generator. Generator is a function which takes
+ /// no arguments.
+ ///
+ /// Complexity: Exactly 'last - first' invocations of generator and assignments.
+ ///
+ template
+ inline void
+ generate(ForwardIterator first, ForwardIterator last, Generator generator)
+ {
+ for(; first != last; ++first) // We cannot call generate_n(first, last-first, generator)
+ *first = generator(); // because the 'last-first' might not be supported by the
+ } // given iterator.
+
+
+ /// generate_n
+ ///
+ /// Iterates an interator n times and assigns the result of generator
+ /// to each succeeding element. Generator is a function which takes
+ /// no arguments.
+ ///
+ /// Complexity: Exactly n invocations of generator and assignments.
+ ///
+ template
+ inline OutputIterator
+ generate_n(OutputIterator first, Size n, Generator generator)
+ {
+ for(; n > 0; --n, ++first)
+ *first = generator();
+ return first;
+ }
+
+
+ /// transform
+ ///
+ /// Iterates the input range of [first, last) and the output iterator result
+ /// and assigns the result of unaryOperation(input) to result.
+ ///
+ /// Effects: Assigns through every iterator i in the range [result, result + (last1 - first1))
+ /// a new corresponding value equal to unaryOperation(*(first1 + (i - result)).
+ ///
+ /// Requires: op shall not have any side effects.
+ ///
+ /// Returns: result + (last1 - first1). That is, returns the end of the output range.
+ ///
+ /// Complexity: Exactly 'last1 - first1' applications of unaryOperation.
+ ///
+ /// Note: result may be equal to first.
+ ///
+ template
+ inline OutputIterator
+ transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation unaryOperation)
+ {
+ for(; first != last; ++first, ++result)
+ *result = unaryOperation(*first);
+ return result;
+ }
+
+
+ /// transform
+ ///
+ /// Iterates the input range of [first, last) and the output iterator result
+ /// and assigns the result of binaryOperation(input1, input2) to result.
+ ///
+ /// Effects: Assigns through every iterator i in the range [result, result + (last1 - first1))
+ /// a new corresponding value equal to binaryOperation(*(first1 + (i - result), *(first2 + (i - result))).
+ ///
+ /// Requires: binaryOperation shall not have any side effects.
+ ///
+ /// Returns: result + (last1 - first1). That is, returns the end of the output range.
+ ///
+ /// Complexity: Exactly 'last1 - first1' applications of binaryOperation.
+ ///
+ /// Note: result may be equal to first1 or first2.
+ ///
+ template
+ inline OutputIterator
+ transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binaryOperation)
+ {
+ for(; first1 != last1; ++first1, ++first2, ++result)
+ *result = binaryOperation(*first1, *first2);
+ return result;
+ }
+
+
+ /// equal
+ ///
+ /// Returns: true if for every iterator i in the range [first1, last1) the
+ /// following corresponding conditions hold: predicate(*i, *(first2 + (i - first1))) != false.
+ /// Otherwise, returns false.
+ ///
+ /// Complexity: At most last1 first1 applications of the corresponding predicate.
+ ///
+ /// To consider: Make specializations of this for scalar types and random access
+ /// iterators that uses memcmp or some trick memory comparison function.
+ /// We should verify that such a thing results in an improvement.
+ ///
+ template
+ inline bool
+ equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
+ {
+ for(; first1 != last1; ++first1, ++first2)
+ {
+ if(!(*first1 == *first2)) // Note that we always express value comparisons in terms of < or ==.
+ return false;
+ }
+ return true;
+ }
+
+ /* Enable the following if there was shown to be some benefit. A glance and Microsoft VC++ memcmp
+ shows that it is not optimized in any way, much less one that would benefit us here.
+
+ inline bool equal(const bool* first1, const bool* last1, const bool* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const char* first1, const char* last1, const char* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const unsigned char* first1, const unsigned char* last1, const unsigned char* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const signed char* first1, const signed char* last1, const signed char* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ #ifndef EA_WCHAR_T_NON_NATIVE // EABase defines this. If you are getting a compiler error here, then somebody has taken away EABase or broken it.
+ inline bool equal(const wchar_t* first1, const wchar_t* last1, const wchar_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+ #endif
+
+ inline bool equal(const int16_t* first1, const int16_t* last1, const int16_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const uint16_t* first1, const uint16_t* last1, const uint16_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const int32_t* first1, const int32_t* last1, const int32_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const uint32_t* first1, const uint32_t* last1, const uint32_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const int64_t* first1, const int64_t* last1, const int64_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const uint64_t* first1, const uint64_t* last1, const uint64_t* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const float* first1, const float* last1, const float* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const double* first1, const double* last1, const double* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+
+ inline bool equal(const long double* first1, const long double* last1, const long double* first2)
+ { return (memcmp(first1, first2, (size_t)((uintptr_t)last1 - (uintptr_t)first1)) == 0); }
+ */
+
+
+
+ /// equal
+ ///
+ /// Returns: true if for every iterator i in the range [first1, last1) the
+ /// following corresponding conditions hold: pred(*i, *(first2 + (i first1))) != false.
+ /// Otherwise, returns false.
+ ///
+ /// Complexity: At most last1 first1 applications of the corresponding predicate.
+ ///
+ template
+ inline bool
+ equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate predicate)
+ {
+ for(; first1 != last1; ++first1, ++first2)
+ {
+ if(!predicate(*first1, *first2))
+ return false;
+ }
+ return true;
+ }
+
+
+
+ /// identical
+ ///
+ /// Returns true if the two input ranges are equivalent.
+ /// There is a subtle difference between this algorithm and
+ /// the 'equal' algorithm. The equal algorithm assumes the
+ /// two ranges are of equal length. This algorithm efficiently
+ /// compares two ranges for both length equality and for
+ /// element equality. There is no other standard algorithm
+ /// that can do this.
+ ///
+ /// Returns: true if the sequence of elements defined by the range
+ /// [first1, last1) is of the same length as the sequence of
+ /// elements defined by the range of [first2, last2) and if
+ /// the elements in these ranges are equal as per the
+ /// equal algorithm.
+ ///
+ /// Complexity: At most 'min((last1 - first1), (last2 - first2))' applications
+ /// of the corresponding comparison.
+ ///
+ template
+ bool identical(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, InputIterator2 last2)
+ {
+ while((first1 != last1) && (first2 != last2) && (*first1 == *first2))
+ {
+ ++first1;
+ ++first2;
+ }
+ return (first1 == last1) && (first2 == last2);
+ }
+
+
+ /// identical
+ ///
+ template
+ bool identical(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, InputIterator2 last2, BinaryPredicate predicate)
+ {
+ while((first1 != last1) && (first2 != last2) && predicate(*first1, *first2))
+ {
+ ++first1;
+ ++first2;
+ }
+ return (first1 == last1) && (first2 == last2);
+ }
+
+
+
+ /// lexicographical_compare
+ ///
+ /// Returns: true if the sequence of elements defined by the range
+ /// [first1, last1) is lexicographically less than the sequence of
+ /// elements defined by the range [first2, last2). Returns false otherwise.
+ ///
+ /// Complexity: At most 'min((last1 - first1), (last2 - first2))' applications
+ /// of the corresponding comparison.
+ ///
+ /// Note: If two sequences have the same number of elements and their
+ /// corresponding elements are equivalent, then neither sequence is
+ /// lexicographically less than the other. If one sequence is a prefix
+ /// of the other, then the shorter sequence is lexicographically less
+ /// than the longer sequence. Otherwise, the lexicographical comparison
+ /// of the sequences yields the same result as the comparison of the first
+ /// corresponding pair of elements that are not equivalent.
+ ///
+ template
+ inline bool
+ lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
+ {
+ for(; (first1 != last1) && (first2 != last2); ++first1, ++first2)
+ {
+ if(*first1 < *first2)
+ return true;
+ if(*first2 < *first1)
+ return false;
+ }
+ return (first1 == last1) && (first2 != last2);
+ }
+
+ inline bool // Specialization for const char*.
+ lexicographical_compare(const char* first1, const char* last1, const char* first2, const char* last2)
+ {
+ const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ return result ? (result < 0) : (n1 < n2);
+ }
+
+ inline bool // Specialization for char*.
+ lexicographical_compare(char* first1, char* last1, char* first2, char* last2)
+ {
+ const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ return result ? (result < 0) : (n1 < n2);
+ }
+
+ inline bool // Specialization for const unsigned char*.
+ lexicographical_compare(const unsigned char* first1, const unsigned char* last1, const unsigned char* first2, const unsigned char* last2)
+ {
+ const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ return result ? (result < 0) : (n1 < n2);
+ }
+
+ inline bool // Specialization for unsigned char*.
+ lexicographical_compare(unsigned char* first1, unsigned char* last1, unsigned char* first2, unsigned char* last2)
+ {
+ const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ return result ? (result < 0) : (n1 < n2);
+ }
+
+ inline bool // Specialization for const signed char*.
+ lexicographical_compare(const signed char* first1, const signed char* last1, const signed char* first2, const signed char* last2)
+ {
+ const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ return result ? (result < 0) : (n1 < n2);
+ }
+
+ inline bool // Specialization for signed char*.
+ lexicographical_compare(signed char* first1, signed char* last1, signed char* first2, signed char* last2)
+ {
+ const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ return result ? (result < 0) : (n1 < n2);
+ }
+
+ #if defined(_MSC_VER) // If using the VC++ compiler (and thus bool is known to be a single byte)...
+ //Not sure if this is a good idea.
+ //inline bool // Specialization for const bool*.
+ //lexicographical_compare(const bool* first1, const bool* last1, const bool* first2, const bool* last2)
+ //{
+ // const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ // const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ // return result ? (result < 0) : (n1 < n2);
+ //}
+ //
+ //inline bool // Specialization for bool*.
+ //lexicographical_compare(bool* first1, bool* last1, bool* first2, bool* last2)
+ //{
+ // const ptrdiff_t n1(last1 - first1), n2(last2 - first2);
+ // const int result = memcmp(first1, first2, (size_t)eastl::min_alt(n1, n2));
+ // return result ? (result < 0) : (n1 < n2);
+ //}
+ #endif
+
+
+
+ /// lexicographical_compare
+ ///
+ /// Returns: true if the sequence of elements defined by the range
+ /// [first1, last1) is lexicographically less than the sequence of
+ /// elements defined by the range [first2, last2). Returns false otherwise.
+ ///
+ /// Complexity: At most 'min((last1 -first1), (last2 - first2))' applications
+ /// of the corresponding comparison.
+ ///
+ /// Note: If two sequences have the same number of elements and their
+ /// corresponding elements are equivalent, then neither sequence is
+ /// lexicographically less than the other. If one sequence is a prefix
+ /// of the other, then the shorter sequence is lexicographically less
+ /// than the longer sequence. Otherwise, the lexicographical comparison
+ /// of the sequences yields the same result as the comparison of the first
+ /// corresponding pair of elements that are not equivalent.
+ ///
+ /// Note: False is always returned if range 1 is exhausted before range 2.
+ /// The result of this is that you can't do a successful reverse compare
+ /// (e.g. use greater<> as the comparison instead of less<>) unless the
+ /// two sequences are of identical length. What you want to do is reverse
+ /// the order of the arguments in order to get the desired effect.
+ ///
+ template
+ inline bool
+ lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, InputIterator2 last2, Compare compare)
+ {
+ for(; (first1 != last1) && (first2 != last2); ++first1, ++first2)
+ {
+ if(compare(*first1, *first2))
+ return true;
+ if(compare(*first2, *first1))
+ return false;
+ }
+ return (first1 == last1) && (first2 != last2);
+ }
+
+
+ /// mismatch
+ ///
+ /// Finds the first position where the two ranges [first1, last1) and
+ /// [first2, first2 + (last1 - first1)) differ. The two versions of
+ /// mismatch use different tests for whether elements differ.
+ ///
+ /// Returns: A pair of iterators i and j such that j == first2 + (i - first1)
+ /// and i is the first iterator in the range [first1, last1) for which the
+ /// following corresponding condition holds: !(*i == *(first2 + (i - first1))).
+ /// Returns the pair last1 and first2 + (last1 - first1) if such an iterator
+ /// i is not found.
+ ///
+ /// Complexity: At most last1 first1 applications of the corresponding predicate.
+ ///
+ template
+ inline eastl::pair
+ mismatch(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2) // , InputIterator2 last2)
+ {
+ while((first1 != last1) && (*first1 == *first2)) // && (first2 != last2) <- C++ standard mismatch function doesn't check first2/last2.
+ {
+ ++first1;
+ ++first2;
+ }
+
+ return eastl::pair(first1, first2);
+ }
+
+
+ /// mismatch
+ ///
+ /// Finds the first position where the two ranges [first1, last1) and
+ /// [first2, first2 + (last1 - first1)) differ. The two versions of
+ /// mismatch use different tests for whether elements differ.
+ ///
+ /// Returns: A pair of iterators i and j such that j == first2 + (i - first1)
+ /// and i is the first iterator in the range [first1, last1) for which the
+ /// following corresponding condition holds: pred(*i, *(first2 + (i - first1))) == false.
+ /// Returns the pair last1 and first2 + (last1 - first1) if such an iterator
+ /// i is not found.
+ ///
+ /// Complexity: At most last1 first1 applications of the corresponding predicate.
+ ///
+ template
+ inline eastl::pair
+ mismatch(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, // InputIterator2 last2,
+ BinaryPredicate predicate)
+ {
+ while((first1 != last1) && predicate(*first1, *first2)) // && (first2 != last2) <- C++ standard mismatch function doesn't check first2/last2.
+ {
+ ++first1;
+ ++first2;
+ }
+
+ return eastl::pair(first1, first2);
+ }
+
+
+ /// lower_bound
+ ///
+ /// Finds the position of the first element in a sorted range that has a value
+ /// greater than or equivalent to a specified value.
+ ///
+ /// Effects: Finds the first position into which value can be inserted without
+ /// violating the ordering.
+ ///
+ /// Returns: The furthermost iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, i) the following corresponding
+ /// condition holds: *j < value.
+ ///
+ /// Complexity: At most 'log(last - first) + 1' comparisons.
+ ///
+ /// Optimizations: We have no need to specialize this implementation for random
+ /// access iterators (e.g. contiguous array), as the code below will already
+ /// take advantage of them.
+ ///
+ template
+ ForwardIterator
+ lower_bound(ForwardIterator first, ForwardIterator last, const T& value)
+ {
+ typedef typename eastl::iterator_traits::difference_type DifferenceType;
+
+ DifferenceType d = eastl::distance(first, last); // This will be efficient for a random access iterator such as an array.
+
+ while(d > 0)
+ {
+ ForwardIterator i = first;
+ DifferenceType d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.
+
+ eastl::advance(i, d2); // This will be efficient for a random access iterator such as an array.
+
+ if(*i < value)
+ {
+ // Disabled because std::lower_bound doesn't specify (23.3.3.3, p3) this can be done: EASTL_VALIDATE_COMPARE(!(value < *i)); // Validate that the compare function is sane.
+ first = ++i;
+ d -= d2 + 1;
+ }
+ else
+ d = d2;
+ }
+ return first;
+ }
+
+
+ /// lower_bound
+ ///
+ /// Finds the position of the first element in a sorted range that has a value
+ /// greater than or equivalent to a specified value. The input Compare function
+ /// takes two arguments and returns true if the first argument is less than
+ /// the second argument.
+ ///
+ /// Effects: Finds the first position into which value can be inserted without
+ /// violating the ordering.
+ ///
+ /// Returns: The furthermost iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, i) the following corresponding
+ /// condition holds: compare(*j, value) != false.
+ ///
+ /// Complexity: At most 'log(last - first) + 1' comparisons.
+ ///
+ /// Optimizations: We have no need to specialize this implementation for random
+ /// access iterators (e.g. contiguous array), as the code below will already
+ /// take advantage of them.
+ ///
+ template
+ ForwardIterator
+ lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)
+ {
+ typedef typename eastl::iterator_traits::difference_type DifferenceType;
+
+ DifferenceType d = eastl::distance(first, last); // This will be efficient for a random access iterator such as an array.
+
+ while(d > 0)
+ {
+ ForwardIterator i = first;
+ DifferenceType d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.
+
+ eastl::advance(i, d2); // This will be efficient for a random access iterator such as an array.
+
+ if(compare(*i, value))
+ {
+ // Disabled because std::lower_bound doesn't specify (23.3.3.1, p3) this can be done: EASTL_VALIDATE_COMPARE(!compare(value, *i)); // Validate that the compare function is sane.
+ first = ++i;
+ d -= d2 + 1;
+ }
+ else
+ d = d2;
+ }
+ return first;
+ }
+
+
+
+ /// upper_bound
+ ///
+ /// Finds the position of the first element in a sorted range that has a
+ /// value that is greater than a specified value.
+ ///
+ /// Effects: Finds the furthermost position into which value can be inserted
+ /// without violating the ordering.
+ ///
+ /// Returns: The furthermost iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, i) the following corresponding
+ /// condition holds: !(value < *j).
+ ///
+ /// Complexity: At most 'log(last - first) + 1' comparisons.
+ ///
+ template
+ ForwardIterator
+ upper_bound(ForwardIterator first, ForwardIterator last, const T& value)
+ {
+ typedef typename eastl::iterator_traits::difference_type DifferenceType;
+
+ DifferenceType len = eastl::distance(first, last);
+
+ while(len > 0)
+ {
+ ForwardIterator i = first;
+ DifferenceType len2 = len >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.
+
+ eastl::advance(i, len2);
+
+ if(!(value < *i)) // Note that we always express value comparisons in terms of < or ==.
+ {
+ first = ++i;
+ len -= len2 + 1;
+ }
+ else
+ {
+ // Disabled because std::upper_bound doesn't specify (23.3.3.2, p3) this can be done: EASTL_VALIDATE_COMPARE(!(*i < value)); // Validate that the compare function is sane.
+ len = len2;
+ }
+ }
+ return first;
+ }
+
+
+ /// upper_bound
+ ///
+ /// Finds the position of the first element in a sorted range that has a
+ /// value that is greater than a specified value. The input Compare function
+ /// takes two arguments and returns true if the first argument is less than
+ /// the second argument.
+ ///
+ /// Effects: Finds the furthermost position into which value can be inserted
+ /// without violating the ordering.
+ ///
+ /// Returns: The furthermost iterator i in the range [first, last) such that
+ /// for any iterator j in the range [first, i) the following corresponding
+ /// condition holds: compare(value, *j) == false.
+ ///
+ /// Complexity: At most 'log(last - first) + 1' comparisons.
+ ///
+ template
+ ForwardIterator
+ upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)
+ {
+ typedef typename eastl::iterator_traits::difference_type DifferenceType;
+
+ DifferenceType len = eastl::distance(first, last);
+
+ while(len > 0)
+ {
+ ForwardIterator i = first;
+ DifferenceType len2 = len >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.
+
+ eastl::advance(i, len2);
+
+ if(!compare(value, *i))
+ {
+ first = ++i;
+ len -= len2 + 1;
+ }
+ else
+ {
+ // Disabled because std::upper_bound doesn't specify (23.3.3.2, p3) this can be done: EASTL_VALIDATE_COMPARE(!compare(*i, value)); // Validate that the compare function is sane.
+ len = len2;
+ }
+ }
+ return first;
+ }
+
+
+ /// equal_range
+ ///
+ /// Effects: Finds the largest subrange [i, j) such that the value can be inserted
+ /// at any iterator k in it without violating the ordering. k satisfies the
+ /// corresponding conditions: !(*k < value) && !(value < *k).
+ ///
+ /// Complexity: At most '2 * log(last - first) + 1' comparisons.
+ ///
+ template
+ pair
+ equal_range(ForwardIterator first, ForwardIterator last, const T& value)
+ {
+ typedef pair ResultType;
+ typedef typename eastl::iterator_traits::difference_type DifferenceType;
+
+ DifferenceType d = eastl::distance(first, last);
+
+ while(d > 0)
+ {
+ ForwardIterator i(first);
+ DifferenceType d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.
+
+ eastl::advance(i, d2);
+
+ if(*i < value)
+ {
+ EASTL_VALIDATE_COMPARE(!(value < *i)); // Validate that the compare function is sane.
+ first = ++i;
+ d -= d2 + 1;
+ }
+ else if(value < *i)
+ {
+ EASTL_VALIDATE_COMPARE(!(*i < value)); // Validate that the compare function is sane.
+ d = d2;
+ last = i;
+ }
+ else
+ {
+ ForwardIterator j(i);
+
+ return ResultType(eastl::lower_bound(first, i, value),
+ eastl::upper_bound(++j, last, value));
+ }
+ }
+ return ResultType(first, first);
+ }
+
+
+ /// equal_range
+ ///
+ /// Effects: Finds the largest subrange [i, j) such that the value can be inserted
+ /// at any iterator k in it without violating the ordering. k satisfies the
+ /// corresponding conditions: compare(*k, value) == false && compare(value, *k) == false.
+ ///
+ /// Complexity: At most '2 * log(last - first) + 1' comparisons.
+ ///
+ template
+ pair
+ equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare compare)
+ {
+ typedef pair ResultType;
+ typedef typename eastl::iterator_traits::difference_type DifferenceType;
+
+ DifferenceType d = eastl::distance(first, last);
+
+ while(d > 0)
+ {
+ ForwardIterator i(first);
+ DifferenceType d2 = d >> 1; // We use '>>1' here instead of '/2' because MSVC++ for some reason generates significantly worse code for '/2'. Go figure.
+
+ eastl::advance(i, d2);
+
+ if(compare(*i, value))
+ {
+ EASTL_VALIDATE_COMPARE(!compare(value, *i)); // Validate that the compare function is sane.
+ first = ++i;
+ d -= d2 + 1;
+ }
+ else if(compare(value, *i))
+ {
+ EASTL_VALIDATE_COMPARE(!compare(*i, value)); // Validate that the compare function is sane.
+ d = d2;
+ last = i;
+ }
+ else
+ {
+ ForwardIterator j(i);
+
+ return ResultType(eastl::lower_bound(first, i, value, compare),
+ eastl::upper_bound(++j, last, value, compare));
+ }
+ }
+ return ResultType(first, first);
+ }
+
+
+ /// replace
+ ///
+ /// Effects: Substitutes elements referred by the iterator i in the range [first, last)
+ /// with new_value, when the following corresponding conditions hold: *i == old_value.
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of replace is replace_if and not another variation of replace.
+ /// This is because both versions would have the same parameter count and there could be ambiguity.
+ ///
+ template
+ inline void
+ replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value)
+ {
+ for(; first != last; ++first)
+ {
+ if(*first == old_value)
+ *first = new_value;
+ }
+ }
+
+
+ /// replace_if
+ ///
+ /// Effects: Substitutes elements referred by the iterator i in the range [first, last)
+ /// with new_value, when the following corresponding conditions hold: predicate(*i) != false.
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of replace_if is replace and not another variation of replace_if.
+ /// This is because both versions would have the same parameter count and there could be ambiguity.
+ ///
+ template
+ inline void
+ replace_if(ForwardIterator first, ForwardIterator last, Predicate predicate, const T& new_value)
+ {
+ for(; first != last; ++first)
+ {
+ if(predicate(*first))
+ *first = new_value;
+ }
+ }
+
+
+ /// remove_copy
+ ///
+ /// Effects: Copies all the elements referred to by the iterator i in the range
+ /// [first, last) for which the following corresponding condition does not hold:
+ /// *i == value.
+ ///
+ /// Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap.
+ ///
+ /// Returns: The end of the resulting range.
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ template
+ inline OutputIterator
+ remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)
+ {
+ for(; first != last; ++first)
+ {
+ if(!(*first == value)) // Note that we always express value comparisons in terms of < or ==.
+ {
+ *result = *first;
+ ++result;
+ }
+ }
+ return result;
+ }
+
+
+ /// remove_copy_if
+ ///
+ /// Effects: Copies all the elements referred to by the iterator i in the range
+ /// [first, last) for which the following corresponding condition does not hold:
+ /// predicate(*i) != false.
+ ///
+ /// Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap.
+ ///
+ /// Returns: The end of the resulting range.
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ template
+ inline OutputIterator
+ remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate)
+ {
+ for(; first != last; ++first)
+ {
+ if(!predicate(*first))
+ {
+ *result = *first;
+ ++result;
+ }
+ }
+ return result;
+ }
+
+
+ /// remove
+ ///
+ /// Effects: Eliminates all the elements referred to by iterator i in the
+ /// range [first, last) for which the following corresponding condition
+ /// holds: *i == value.
+ ///
+ /// Returns: The end of the resulting range.
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of remove is remove_if and not another variation of remove.
+ /// This is because both versions would have the same parameter count and there could be ambiguity.
+ ///
+ /// Note: Since this function moves the element to the back of the heap and
+ /// doesn't actually remove it from the given container, the user must call
+ /// the container erase function if the user wants to erase the element
+ /// from the container.
+ ///
+ /// Example usage:
+ /// vector intArray;
+ /// ...
+ /// intArray.erase(remove(intArray.begin(), intArray.end(), 4), intArray.end()); // Erase all elements of value 4.
+ ///
+ template
+ inline ForwardIterator
+ remove(ForwardIterator first, ForwardIterator last, const T& value)
+ {
+ first = eastl::find(first, last, value);
+ if(first != last)
+ {
+ ForwardIterator i(first);
+ return eastl::remove_copy(++i, last, first, value);
+ }
+ return first;
+ }
+
+
+ /// remove_if
+ ///
+ /// Effects: Eliminates all the elements referred to by iterator i in the
+ /// range [first, last) for which the following corresponding condition
+ /// holds: predicate(*i) != false.
+ ///
+ /// Returns: The end of the resulting range.
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of remove_if is remove and not another variation of remove_if.
+ /// This is because both versions would have the same parameter count and there could be ambiguity.
+ ///
+ /// Note: Since this function moves the element to the back of the heap and
+ /// doesn't actually remove it from the given container, the user must call
+ /// the container erase function if the user wants to erase the element
+ /// from the container.
+ ///
+ /// Example usage:
+ /// vector intArray;
+ /// ...
+ /// intArray.erase(remove(intArray.begin(), intArray.end(), bind2nd(less(), (int)3)), intArray.end()); // Erase all elements less than 3.
+ ///
+ template
+ inline ForwardIterator
+ remove_if(ForwardIterator first, ForwardIterator last, Predicate predicate)
+ {
+ first = eastl::find_if(first, last, predicate);
+ if(first != last)
+ {
+ ForwardIterator i(first);
+ return eastl::remove_copy_if(++i, last, first, predicate);
+ }
+ return first;
+ }
+
+
+ /// replace_copy
+ ///
+ /// Effects: Assigns to every iterator i in the range [result, result + (last - first))
+ /// either new_value or *(first + (i - result)) depending on whether the following
+ /// corresponding conditions hold: *(first + (i - result)) == old_value.
+ ///
+ /// Requires: The ranges [first, last) and [result, result + (last - first)) shall not overlap.
+ ///
+ /// Returns: result + (last - first).
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of replace_copy is replace_copy_if and not another variation of replace_copy.
+ /// This is because both versions would have the same parameter count and there could be ambiguity.
+ ///
+ template
+ inline OutputIterator
+ replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)
+ {
+ for(; first != last; ++first, ++result)
+ *result = (*first == old_value) ? new_value : *first;
+ return result;
+ }
+
+
+ /// replace_copy_if
+ ///
+ /// Effects: Assigns to every iterator i in the range [result, result + (last - first))
+ /// either new_value or *(first + (i - result)) depending on whether the following
+ /// corresponding conditions hold: predicate(*(first + (i - result))) != false.
+ ///
+ /// Requires: The ranges [first, last) and [result, result+(lastfirst)) shall not overlap.
+ ///
+ /// Returns: result + (last - first).
+ ///
+ /// Complexity: Exactly 'last - first' applications of the corresponding predicate.
+ ///
+ /// Note: The predicate version of replace_copy_if is replace_copy and not another variation of replace_copy_if.
+ /// This is because both versions would have the same parameter count and there could be ambiguity.
+ ///
+ template
+ inline OutputIterator
+ replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate, const T& new_value)
+ {
+ for(; first != last; ++first, ++result)
+ *result = predicate(*first) ? new_value : *first;
+ return result;
+ }
+
+
+
+
+ // reverse
+ //
+ // We provide helper functions which allow reverse to be implemented more
+ // efficiently for some types of iterators and types.
+ //
+ template