flatten 20260225
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.DS_Store
|
||||
*.pyc
|
||||
xcuserdata
|
||||
.bin
|
||||
transfer-to-*
|
||||
temp
|
||||
2221
Core_Zero.xcodeproj/project.pbxproj
Normal file
2221
Core_Zero.xcodeproj/project.pbxproj
Normal file
File diff suppressed because it is too large
Load Diff
7
Core_Zero.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
Core_Zero.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1330"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F6E97D10281EF664004C92E9"
|
||||
BuildableName = "Core_Zero_Tests"
|
||||
BlueprintName = "Core_Zero_Tests"
|
||||
ReferencedContainer = "container:Core_Zero.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F6E97D10281EF664004C92E9"
|
||||
BuildableName = "Core_Zero_Tests"
|
||||
BlueprintName = "Core_Zero_Tests"
|
||||
ReferencedContainer = "container:Core_Zero.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "-s"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "-b"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::math::Float16""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::algorithm::on_destruct""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::string::split_once""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::algorithm::container_get_if""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::algorithm::small_copy""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::enumerate""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::no_last""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::no_first""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::zip""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::is_first""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::range""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::range_with""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::safe_next""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::iterators::transform_with""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::log::LogOf""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::ptr""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::const_hash""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::const_hash::expected""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::rtti::type_name""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::rtti""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::string::join""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::string::cmp_case""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::string::replace""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::string::trim""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::timer::Timer""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::string::str""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: vectorpool""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: safe iteration of lists""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::containers::InPlace""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: MultiContainer""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: allocator_pool::Stack""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: SizeAllocatorPool""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: core::allocator_pool::prune::Pruning""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = ""Scenario: stackarray_v2""
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "F6E97D10281EF664004C92E9"
|
||||
BuildableName = "Core_Zero_Tests"
|
||||
BlueprintName = "Core_Zero_Tests"
|
||||
ReferencedContainer = "container:Core_Zero.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
188
Examples.cpp
Normal file
188
Examples.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
#include <tjp/core/containers/Vector.hpp>
|
||||
#include <tjp/core/containers/Map.hpp>
|
||||
#include <tjp/core/algorithm/map_value.hpp>
|
||||
#include <tjp/core/algorithm/map_value_erase.hpp>
|
||||
#include <tjp/core/iterators/range.hpp>
|
||||
#include <tjp/core/threads/Lock.hpp>
|
||||
#include <tjp/core/time/Time+chrono.hpp>
|
||||
|
||||
namespace my_base_namespace {
|
||||
namespace ext = tjp::core;
|
||||
using namespace ext;
|
||||
}
|
||||
|
||||
// or
|
||||
|
||||
namespace my_base_namespace {
|
||||
namespace ext = tjp::core;
|
||||
|
||||
using ext::Mutex;
|
||||
}
|
||||
|
||||
namespace my_base_namespace::sub_name_space {
|
||||
|
||||
void do_something() {}
|
||||
|
||||
template<typename T>
|
||||
void do_something_with(T &&) {}
|
||||
|
||||
// ----------------------------------------
|
||||
// example for locks
|
||||
// ----------------------------------------
|
||||
void example_lock_tjp()
|
||||
{
|
||||
Mutex mutex;
|
||||
|
||||
auto lock = lock_of(mutex);
|
||||
do_something();
|
||||
|
||||
auto should_send_signal = true;
|
||||
if (should_send_signal)
|
||||
{
|
||||
auto unlock = unlock_of(mutex);
|
||||
do_something();
|
||||
}
|
||||
}
|
||||
|
||||
// using std
|
||||
void example_lock_cpp()
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
do_something();
|
||||
|
||||
auto should_send_signal = true;
|
||||
if (should_send_signal)
|
||||
{
|
||||
try
|
||||
{
|
||||
mutex.unlock();
|
||||
do_something();
|
||||
mutex.lock();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------
|
||||
// example for maps
|
||||
// ----------------------------------------
|
||||
void example_map_tjp()
|
||||
{
|
||||
Map<int, int> map;
|
||||
if (auto value = map_value(map, 42))
|
||||
do_something_with(*value);
|
||||
|
||||
if (auto value = map_value_erase(map, 42))
|
||||
do_something_with(*value);
|
||||
}
|
||||
|
||||
|
||||
// using std
|
||||
void example_map_cpp()
|
||||
{
|
||||
std::map<int, int> map;
|
||||
auto i = map.find(42);
|
||||
if (i != map.end())
|
||||
{
|
||||
do_something_with(*i);
|
||||
}
|
||||
|
||||
auto j = map.find(42);
|
||||
if (j != map.end())
|
||||
{
|
||||
auto v = std::move(j->second);
|
||||
map.erase(j);
|
||||
|
||||
do_something_with(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------
|
||||
// example for range
|
||||
// ----------------------------------------
|
||||
|
||||
void example_range_cpp()
|
||||
{
|
||||
for (auto k=0; k<42; ++k)
|
||||
do_something_with(k);
|
||||
}
|
||||
|
||||
void example_range_tjp()
|
||||
{
|
||||
for (auto i: range(42))
|
||||
do_something_with(i);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
// time
|
||||
// ----------------------------------------
|
||||
|
||||
void example_time_duration_cpp()
|
||||
{
|
||||
auto t1 = std::chrono::system_clock::now();
|
||||
do_something();
|
||||
auto t2 = std::chrono::system_clock::now();
|
||||
|
||||
auto duration = t2 - t1;
|
||||
auto duration_serializable_number = std::chrono::duration_cast<std::chrono::microseconds>(duration).count();
|
||||
do_something_with(duration_serializable_number);
|
||||
|
||||
auto duration_in_seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
|
||||
do_something_with(duration_in_seconds);
|
||||
|
||||
auto two_second_after_t1 = t1 + std::chrono::seconds(2);
|
||||
do_something_with(two_second_after_t1);
|
||||
|
||||
auto meters = 32.;
|
||||
auto seconds = std::chrono::seconds(2);
|
||||
auto meters_per_second = meters / std::chrono::duration<float>(seconds).count();
|
||||
do_something_with(meters_per_second);
|
||||
|
||||
meters = std::chrono::duration<float>(seconds).count() * meters_per_second;
|
||||
do_something_with(meters);
|
||||
}
|
||||
|
||||
void example_time_duration_tjp()
|
||||
{
|
||||
auto t1 = time::now();
|
||||
do_something();
|
||||
auto t2 = time::now();
|
||||
|
||||
auto duration = t2 - t1;
|
||||
auto duration_serializable_number = duration.v;
|
||||
do_something_with(duration_serializable_number);
|
||||
|
||||
auto duration_in_seconds = duration / time::Seconds;
|
||||
do_something_with(duration_in_seconds);
|
||||
|
||||
auto two_second_after_t1 = t1 + time::Seconds(2);
|
||||
auto two_second_after_t1_another = t1 + 2 * time::Seconds;
|
||||
do_something_with(two_second_after_t1);
|
||||
do_something_with(two_second_after_t1_another);
|
||||
|
||||
auto meters = 32.;
|
||||
auto seconds = 2 * time::Seconds;
|
||||
auto meters_per_second = meters / seconds;
|
||||
do_something_with(meters_per_second);
|
||||
|
||||
meters = seconds * meters_per_second;
|
||||
do_something_with(meters);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
26
LICENSE
Executable file
26
LICENSE
Executable file
@@ -0,0 +1,26 @@
|
||||
MIT NON-AI License
|
||||
|
||||
Copyright (c) 2025, Timothy Prepscius
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of the 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.
|
||||
|
||||
In addition, the following restrictions apply:
|
||||
|
||||
1. The Software and any modifications made to it may not be used for the purpose of training or improving machine learning algorithms,
|
||||
including but not limited to artificial intelligence, natural language processing, or data mining. This condition applies to any derivatives,
|
||||
modifications, or updates based on the Software code. Any usage of the Software in an AI-training dataset is considered a breach of this License.
|
||||
|
||||
2. The Software may not be included in any dataset used for training or improving machine learning algorithms,
|
||||
including but not limited to artificial intelligence, natural language processing, or data mining.
|
||||
|
||||
3. Any person or organization found to be in violation of these restrictions will be subject to legal action and may be held liable
|
||||
for any damages resulting from such use.
|
||||
|
||||
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.
|
||||
8
Makefile
Normal file
8
Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
###################################
|
||||
# License: Modified MIT (NON-AI)
|
||||
# Copyright 2025 Timothy Prepscius
|
||||
# See the LICENSE file in the root directory for license information.
|
||||
###################################
|
||||
|
||||
ROOTDIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))..)
|
||||
include $(ROOTDIR)/Core_Make/tjp/Make/Makefile
|
||||
11
Makefile.def
Executable file
11
Makefile.def
Executable file
@@ -0,0 +1,11 @@
|
||||
###################################
|
||||
# License: Modified MIT (NON-AI)
|
||||
# Copyright 2025 Timothy Prepscius
|
||||
# See the LICENSE file in the root directory for license information.
|
||||
###################################
|
||||
|
||||
timprepscius.core_zero.include := -I $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
timprepscius.core_zero.link := -L $(dir $(realpath $(lastword $(MAKEFILE_LIST))))/.bin/$(OBJDIR)
|
||||
|
||||
timprepscius.core.include := $(timprepscius.core.include) $(timprepscius.core_zero.include)
|
||||
timprepscius.core.link := $(timprepscius.core.link) $(timprepscius.core_zero.link)
|
||||
51
Makefile.project
Executable file
51
Makefile.project
Executable file
@@ -0,0 +1,51 @@
|
||||
###################################
|
||||
# License: Modified MIT (NON-AI)
|
||||
# Copyright 2025 Timothy Prepscius
|
||||
# See the LICENSE file in the root directory for license information.
|
||||
###################################
|
||||
|
||||
include $(MAKEDIR)/Makefile.base
|
||||
|
||||
PROJECTS := \
|
||||
tjp/core/algorithm \
|
||||
tjp/core/assert \
|
||||
tjp/core/containers \
|
||||
tjp/core/const_hash \
|
||||
tjp/core/debug \
|
||||
tjp/core/exception \
|
||||
tjp/core/io \
|
||||
tjp/core/iterators \
|
||||
tjp/core/log \
|
||||
tjp/core/ptr \
|
||||
tjp/core/ptr/std \
|
||||
tjp/core/ptr/using_maps \
|
||||
tjp/core/ptr/using_info \
|
||||
tjp/core/sfinae \
|
||||
tjp/core/string \
|
||||
tjp/core/system \
|
||||
tjp/core/testing \
|
||||
tjp/core/threads \
|
||||
tjp/core/threads/std \
|
||||
tjp/core/time \
|
||||
tjp/core/timer \
|
||||
tjp/core/type_traits \
|
||||
tjp/core/types \
|
||||
|
||||
ifeq (Android,$(SYS_NAME))
|
||||
|
||||
PROJECTS += \
|
||||
tjp/core/debug/android \
|
||||
|
||||
else
|
||||
PROJECTS += \
|
||||
tjp/core/debug/glib \
|
||||
|
||||
endif
|
||||
|
||||
SRC_PCH := tjp/core/Precompile.pch
|
||||
INCPATH := $(timprepscius.libraries.cpp.include)
|
||||
LIBFILE := libCore_Zero.a
|
||||
|
||||
COPYTO := $(LIBRARIES_PROJECT)
|
||||
|
||||
include $(MAKEDIR)/Makefile.lib
|
||||
141
ReadMe.md
Executable file
141
ReadMe.md
Executable file
@@ -0,0 +1,141 @@
|
||||
# Core_Zero
|
||||
|
||||
Basic foundational classes
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
Most of Core_Zero is header-only.
|
||||
To enable header-only use:
|
||||
`#define TJP_CORE_HEADER_ONLY`
|
||||
|
||||
The entire Core_Zero project will be converted to header only compatible soon.
|
||||
|
||||
To build all of the project use these steps.
|
||||
|
||||
```
|
||||
mkdir my_project
|
||||
cd my_project
|
||||
|
||||
git clone http://github.com/timprepscius/Core_Libraries
|
||||
git clone http://github.com/timprepscius/Core_Zero
|
||||
git clone http://github.com/timprepscius/Core_Make
|
||||
cd Core_Zero
|
||||
make
|
||||
|
||||
cd tests
|
||||
make
|
||||
.bin/Core_Zero_Tests.exe
|
||||
|
||||
```
|
||||
|
||||
|
||||
## How to use
|
||||
|
||||
### Locks
|
||||
|
||||
```
|
||||
// ----------------------------------------
|
||||
// example for locks
|
||||
// ----------------------------------------
|
||||
void example_lock_tjp()
|
||||
{
|
||||
Mutex mutex;
|
||||
|
||||
auto lock = lock_of(mutex);
|
||||
do_something();
|
||||
|
||||
auto should_send_signal = true;
|
||||
if (should_send_signal)
|
||||
{
|
||||
auto unlock = unlock_of(mutex);
|
||||
do_something();
|
||||
}
|
||||
}
|
||||
|
||||
// using std
|
||||
void example_lock_cpp()
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
do_something();
|
||||
|
||||
auto should_send_signal = true;
|
||||
if (should_send_signal)
|
||||
{
|
||||
try
|
||||
{
|
||||
mutex.unlock();
|
||||
do_something();
|
||||
mutex.lock();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Maps
|
||||
|
||||
```
|
||||
// ----------------------------------------
|
||||
// example for maps
|
||||
// ----------------------------------------
|
||||
void example_map_tjp()
|
||||
{
|
||||
Map<int, int> map;
|
||||
if (auto value = map_value(map, 42))
|
||||
do_something_with(*value);
|
||||
|
||||
if (auto value = map_value_erase(map, 42))
|
||||
do_something_with(*value);
|
||||
}
|
||||
|
||||
|
||||
// using std
|
||||
void example_map_cpp()
|
||||
{
|
||||
std::map<int, int> map;
|
||||
auto i = map.find(42);
|
||||
if (i != map.end())
|
||||
{
|
||||
do_something_with(*i);
|
||||
}
|
||||
|
||||
auto j = map.find(42);
|
||||
if (j != map.end())
|
||||
{
|
||||
auto v = std::move(j->second);
|
||||
map.erase(j);
|
||||
|
||||
do_something_with(v);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Range iteration
|
||||
```
|
||||
// ----------------------------------------
|
||||
// example for range
|
||||
// ----------------------------------------
|
||||
void example_range_tjp()
|
||||
{
|
||||
for (auto i: range(42))
|
||||
do_something_with(i);
|
||||
}
|
||||
|
||||
// using std
|
||||
void example_range_cpp()
|
||||
{
|
||||
for (auto k=0; k<42; ++k)
|
||||
do_something_with(k);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Other examples
|
||||
|
||||
Look at `Core_Zero/Examples.cpp` for more examples on how to use this library.
|
||||
1
tests/Makefile
Symbolic link
1
tests/Makefile
Symbolic link
@@ -0,0 +1 @@
|
||||
../../Make/Makefile
|
||||
36
tests/Makefile.project
Executable file
36
tests/Makefile.project
Executable file
@@ -0,0 +1,36 @@
|
||||
include $(MAKEDIR)/Makefile.base
|
||||
|
||||
PROJECTS := \
|
||||
. \
|
||||
../core/algorithm/_tests \
|
||||
../core/const_hash/_tests \
|
||||
../core/const_expr/_tests \
|
||||
../core/containers/_tests \
|
||||
../core/iterators/_tests \
|
||||
../core/log/_tests \
|
||||
../core/ptr/_tests \
|
||||
../core/ptr/using_info/_tests \
|
||||
../core/ptr/using_maps/_tests \
|
||||
../core/rtti/_tests \
|
||||
../core/testing/_tests \
|
||||
|
||||
INCPATH := \
|
||||
$(timprepscius.libraries.cpp.include) \
|
||||
$(timprepscius.core.include)
|
||||
|
||||
LDPATH := \
|
||||
$(timprepscius.libraries.cpp.link)
|
||||
|
||||
LIBS := \
|
||||
-lCore_Zero
|
||||
|
||||
EXEFILE := Core_Zero_Tests.exe
|
||||
|
||||
#COPYTO := $(ROOTDIR)/.bin
|
||||
|
||||
ifeq (Darwin,$(SYS_NAME))
|
||||
LIBS += -lc++
|
||||
endif
|
||||
|
||||
|
||||
include $(MAKEDIR)/Makefile.bin
|
||||
21
tests/Run.cpp
Normal file
21
tests/Run.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
|
||||
#include <tjp/core/log/Log.h>
|
||||
|
||||
using namespace tjp;
|
||||
using namespace core;
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
xLogInitialize();
|
||||
xLogActivateStory("testing");
|
||||
xLogActivateStory("debug");
|
||||
|
||||
int result = Catch::Session().run( argc, argv );
|
||||
return result;
|
||||
}
|
||||
29
tjp/core/Precompile.pch
Normal file
29
tjp/core/Precompile.pch
Normal file
@@ -0,0 +1,29 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#define USE_PRECOMPILED_HEADERS
|
||||
#ifdef USE_PRECOMPILED_HEADERS
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#endif
|
||||
|
||||
12
tjp/core/algorithm/ExecuteOnDestruct.h
Executable file
12
tjp/core/algorithm/ExecuteOnDestruct.h
Executable file
@@ -0,0 +1,12 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
struct ExecuteOnDestruct;
|
||||
using OnDestruct = ExecuteOnDestruct;
|
||||
|
||||
} // namespace
|
||||
73
tjp/core/algorithm/ExecuteOnDestruct.hpp
Executable file
73
tjp/core/algorithm/ExecuteOnDestruct.hpp
Executable file
@@ -0,0 +1,73 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ExecuteOnDestruct.h"
|
||||
#include <functional>
|
||||
#include "../threads/TestMutex.hpp"
|
||||
#include "no_throw.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
struct ExecuteOnDestruct
|
||||
{
|
||||
typedef std::function<void()> F;
|
||||
|
||||
[[no_unique_address]]
|
||||
TestMutex m;
|
||||
|
||||
F f;
|
||||
|
||||
struct Throws_{};
|
||||
static constexpr Throws_ Throws = Throws_{};
|
||||
|
||||
ExecuteOnDestruct(const ExecuteOnDestruct &) = delete;
|
||||
|
||||
ExecuteOnDestruct() {}
|
||||
|
||||
ExecuteOnDestruct(ExecuteOnDestruct &&rhs):
|
||||
f(rhs.move())
|
||||
{}
|
||||
|
||||
template<typename FU>
|
||||
ExecuteOnDestruct(FU &&f_) : f(no_throw(std::forward<FU>(f_)))
|
||||
{}
|
||||
|
||||
|
||||
// note: throwing on destruction, *can* cause termination, weird but true as of 2026
|
||||
template<typename FU>
|
||||
ExecuteOnDestruct(FU &&f_, Throws_) : f(std::forward<FU>(f_))
|
||||
{}
|
||||
|
||||
F move()
|
||||
{
|
||||
auto l = lock_of(m);
|
||||
F f_;
|
||||
std::swap(f_, f);
|
||||
return f_;
|
||||
}
|
||||
|
||||
~ExecuteOnDestruct() noexcept(false)
|
||||
{
|
||||
execute();
|
||||
}
|
||||
|
||||
void execute()
|
||||
{
|
||||
auto f = move();
|
||||
if (f)
|
||||
f();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
move();
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace
|
||||
43
tjp/core/algorithm/_tests/all_are.cpp
Executable file
43
tjp/core/algorithm/_tests/all_are.cpp
Executable file
@@ -0,0 +1,43 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/all_are.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::all_are")
|
||||
{
|
||||
GIVEN("a vector of values")
|
||||
{
|
||||
Vector<int> v;
|
||||
for (auto i=0; i<50; ++i)
|
||||
v.push_back(42);
|
||||
|
||||
auto all_are_42 = all_are(v, [](auto &v) { return v == 42; });
|
||||
REQUIRE(all_are_42);
|
||||
|
||||
WHEN("one is not 42")
|
||||
{
|
||||
v[5] = 43;
|
||||
auto all_are_42 = all_are(v, [](auto &v) { return v == 42; });
|
||||
REQUIRE(!all_are_42);
|
||||
}
|
||||
|
||||
WHEN("multiple are not 42")
|
||||
{
|
||||
v[2] = 40;
|
||||
v[13] = 39;
|
||||
auto all_are_42 = all_are(v, [](auto &v) { return v == 42; });
|
||||
REQUIRE(!all_are_42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/container_erase_if.cpp
Executable file
54
tjp/core/algorithm/_tests/container_erase_if.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_erase_if.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_erase_if")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = container_erase_if(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(erased == 4);
|
||||
REQUIRE(v.size() == 96);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = container_erase_if(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 96);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = container_erase_if(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
53
tjp/core/algorithm/_tests/container_erase_if_one.cpp
Executable file
53
tjp/core/algorithm/_tests/container_erase_if_one.cpp
Executable file
@@ -0,0 +1,53 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_erase_if_one.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_erase_if_one")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is erased")
|
||||
{
|
||||
auto erased = container_erase_if_one(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
|
||||
WHEN("42 is erased again")
|
||||
{
|
||||
auto erased = container_erase_if_one(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = container_erase_if_one(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
47
tjp/core/algorithm/_tests/container_erase_value_all.cpp
Executable file
47
tjp/core/algorithm/_tests/container_erase_value_all.cpp
Executable file
@@ -0,0 +1,47 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_erase_value_all.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_erase_value_all")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = container_erase_value_all(v, 10);
|
||||
REQUIRE(erased==4);
|
||||
REQUIRE(v.size() == 96);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = container_erase_value_all(v, 10);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 96);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = container_erase_value_all(v, 1000);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
47
tjp/core/algorithm/_tests/container_erase_value_one.cpp
Executable file
47
tjp/core/algorithm/_tests/container_erase_value_one.cpp
Executable file
@@ -0,0 +1,47 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_erase_value_one.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_erase_value_one")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = container_erase_value_one(v, 10);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = container_erase_value_one(v, 10);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(v.size() == 98);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = container_erase_value_one(v, 1000);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
40
tjp/core/algorithm/_tests/container_find_if.cpp
Executable file
40
tjp/core/algorithm/_tests/container_find_if.cpp
Executable file
@@ -0,0 +1,40 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_find_if.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_find_if")
|
||||
{
|
||||
GIVEN("a vector of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is found")
|
||||
{
|
||||
auto found = container_find_if(v, [](auto &v) { return v == 10; });
|
||||
|
||||
REQUIRE(found != v.end());
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_find_if(v, [](auto &v) { return v == 1000; });
|
||||
|
||||
REQUIRE(found == v.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
85
tjp/core/algorithm/_tests/container_get_if.cpp
Executable file
85
tjp/core/algorithm/_tests/container_get_if.cpp
Executable file
@@ -0,0 +1,85 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_get_if.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_get_if")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
auto found = container_get_if(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(found);
|
||||
REQUIRE(*found == 42);
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_get_if(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_get_if(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!found);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
#ifdef CHECK_COMPILATION_FAILURE
|
||||
WHEN("called with a temporary list")
|
||||
{
|
||||
int destructed = 0;
|
||||
auto make_values = [&]() {
|
||||
struct S {
|
||||
int *destructed;
|
||||
int value;
|
||||
S(int *destructed_, int value_) :
|
||||
destructed(destructed_),
|
||||
value(value_)
|
||||
{}
|
||||
~S() { (*destructed)++; }
|
||||
};
|
||||
|
||||
|
||||
List<S> temp;
|
||||
temp.emplace_back(&destructed, 5);
|
||||
temp.emplace_back(&destructed, 42);
|
||||
return temp;
|
||||
};
|
||||
|
||||
auto found = container_get_if(
|
||||
make_values(), [&](auto &s) {
|
||||
REQUIRE(destructed == 0);
|
||||
return s.value == 42;
|
||||
}
|
||||
);
|
||||
|
||||
REQUIRE(destructed == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
45
tjp/core/algorithm/_tests/container_get_if_optional.cpp
Executable file
45
tjp/core/algorithm/_tests/container_get_if_optional.cpp
Executable file
@@ -0,0 +1,45 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_get_if_optional.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_get_if_optional")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
auto found = container_get_if_optional(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(found);
|
||||
REQUIRE(*found == 42);
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_get_if_optional(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!found);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/container_get_if_optional_erase.cpp
Executable file
54
tjp/core/algorithm/_tests/container_get_if_optional_erase.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_get_if_optional_erase.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_get_if_optional_erase")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is erased")
|
||||
{
|
||||
auto erased = container_get_if_optional_erase(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(*erased == 42);
|
||||
REQUIRE(v.size() == 99);
|
||||
|
||||
WHEN("42 is erased again")
|
||||
{
|
||||
auto erased = container_get_if_optional_erase(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = container_get_if_optional_erase(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
48
tjp/core/algorithm/_tests/container_get_optional_erase.cpp
Executable file
48
tjp/core/algorithm/_tests/container_get_optional_erase.cpp
Executable file
@@ -0,0 +1,48 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_get_optional_erase.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_get_optional_erase")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is erased")
|
||||
{
|
||||
auto erased = container_get_optional_erase(v, 42);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(*erased == 42);
|
||||
REQUIRE(v.size() == 99);
|
||||
|
||||
WHEN("42 is erased again")
|
||||
{
|
||||
auto erased = container_get_optional_erase(v, 42);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_get_optional_erase(v, 1000);
|
||||
REQUIRE(!found);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
44
tjp/core/algorithm/_tests/container_has.cpp
Executable file
44
tjp/core/algorithm/_tests/container_has.cpp
Executable file
@@ -0,0 +1,44 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_has.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_has")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
auto found = container_has(v, 42);
|
||||
REQUIRE(found);
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_has(v, 1000);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_has(v, 1000);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
50
tjp/core/algorithm/_tests/container_has_if.cpp
Executable file
50
tjp/core/algorithm/_tests/container_has_if.cpp
Executable file
@@ -0,0 +1,50 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/container_has_if.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::container_has_if")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
auto found = container_has_if(
|
||||
v, [](auto &v) { return v == 42; }
|
||||
);
|
||||
REQUIRE(found);
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_has_if(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = container_has_if(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
38
tjp/core/algorithm/_tests/copy_clear.cpp
Executable file
38
tjp/core/algorithm/_tests/copy_clear.cpp
Executable file
@@ -0,0 +1,38 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/copy_clear.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::copy_clear")
|
||||
{
|
||||
WHEN("simple value")
|
||||
{
|
||||
int i = 42;
|
||||
auto v = copy_clear(i);
|
||||
REQUIRE(i == 0);
|
||||
REQUIRE(v == 42);
|
||||
}
|
||||
|
||||
WHEN("complex value")
|
||||
{
|
||||
String i = "hello";
|
||||
auto v = copy_clear(i);
|
||||
REQUIRE(i == "");
|
||||
REQUIRE(v == "hello");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
38
tjp/core/algorithm/_tests/copy_of.cpp
Executable file
38
tjp/core/algorithm/_tests/copy_of.cpp
Executable file
@@ -0,0 +1,38 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/copy_of.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::copy_of")
|
||||
{
|
||||
WHEN("simple value")
|
||||
{
|
||||
int i = 42;
|
||||
auto v = copy_of(i);
|
||||
REQUIRE(i == 42);
|
||||
REQUIRE(v == 42);
|
||||
}
|
||||
|
||||
WHEN("complex value")
|
||||
{
|
||||
String i = "hello";
|
||||
auto v = copy_of(i);
|
||||
REQUIRE(i == "hello");
|
||||
REQUIRE(v == "hello");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
42
tjp/core/algorithm/_tests/emplace.cpp
Executable file
42
tjp/core/algorithm/_tests/emplace.cpp
Executable file
@@ -0,0 +1,42 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/emplace.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::emplace")
|
||||
{
|
||||
WHEN("Vector value")
|
||||
{
|
||||
Vector<int> v;
|
||||
|
||||
WHEN("initializer list")
|
||||
{
|
||||
Vector<int> expected = { 1, 2, 3, 4, 5};
|
||||
emplace(v, { 1, 2, 3, 4, 5});
|
||||
REQUIRE(v == expected);
|
||||
}
|
||||
|
||||
WHEN("init")
|
||||
{
|
||||
Vector<int> expected = { 1, 1 };
|
||||
emplace(v, 2, 1);
|
||||
REQUIRE(v == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
38
tjp/core/algorithm/_tests/empty_of.cpp
Executable file
38
tjp/core/algorithm/_tests/empty_of.cpp
Executable file
@@ -0,0 +1,38 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/empty_of.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::empty_of")
|
||||
{
|
||||
WHEN("simple value")
|
||||
{
|
||||
using T = Vector<int>;
|
||||
auto &v = empty_of<T>();
|
||||
REQUIRE(v.empty());
|
||||
}
|
||||
|
||||
WHEN("complex value")
|
||||
{
|
||||
struct X { int y = 42; };
|
||||
|
||||
using T = X;
|
||||
auto &v = empty_of<T>();
|
||||
REQUIRE(v.y == 42);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
33
tjp/core/algorithm/_tests/ends_with.cpp
Executable file
33
tjp/core/algorithm/_tests/ends_with.cpp
Executable file
@@ -0,0 +1,33 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/ends_with.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::ends_with")
|
||||
{
|
||||
WHEN("Vector value")
|
||||
{
|
||||
Vector<int> v = { 1, 2, 3, 4, 5 };
|
||||
auto ends_with_345 = ends_with(v, Vector<int> {3, 4, 5});
|
||||
REQUIRE(ends_with_345);
|
||||
|
||||
auto ends_with_456 = ends_with(v, Vector<int> {4,5,6});
|
||||
REQUIRE(!ends_with_456);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
33
tjp/core/algorithm/_tests/has_last.cpp
Executable file
33
tjp/core/algorithm/_tests/has_last.cpp
Executable file
@@ -0,0 +1,33 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/has_last.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::has_last")
|
||||
{
|
||||
WHEN("Vector value")
|
||||
{
|
||||
Vector<int> v = { 1, 2, 3, 4, 5 };
|
||||
auto ends_with_5 = has_last(v, [](auto &v) { return v == 5; });
|
||||
REQUIRE(ends_with_5);
|
||||
|
||||
auto ends_with_6 = has_last(v, [](auto &v) { return v == 6; });
|
||||
REQUIRE(!ends_with_6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
31
tjp/core/algorithm/_tests/in_range_segment.cpp
Executable file
31
tjp/core/algorithm/_tests/in_range_segment.cpp
Executable file
@@ -0,0 +1,31 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/in_range_segment.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::in_range_segment")
|
||||
{
|
||||
WHEN("ranges")
|
||||
{
|
||||
static_assert(in_range_segment(1, 0, 10));
|
||||
static_assert(!in_range_segment(0, 1, 10));
|
||||
static_assert(!in_range_segment(11, 1, 10));
|
||||
static_assert(in_range_segment(10, 1, 10));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
30
tjp/core/algorithm/_tests/is_in.cpp
Executable file
30
tjp/core/algorithm/_tests/is_in.cpp
Executable file
@@ -0,0 +1,30 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/is_in.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::is_in")
|
||||
{
|
||||
WHEN("ranges")
|
||||
{
|
||||
static_assert(is_in(0, 0, 1, 2, 3));
|
||||
static_assert(is_in(1, 0, 1, 2, 3));
|
||||
static_assert(!is_in(4, 0, 1, 2, 3));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
34
tjp/core/algorithm/_tests/is_zero.cpp
Executable file
34
tjp/core/algorithm/_tests/is_zero.cpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/is_zero.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::is_zero")
|
||||
{
|
||||
WHEN("ranges")
|
||||
{
|
||||
auto minus_one = [](auto &&v) { return v - 1; };
|
||||
auto test_minus_one = is_zero(minus_one);
|
||||
|
||||
REQUIRE(test_minus_one(1));
|
||||
REQUIRE(!test_minus_one(0));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
29
tjp/core/algorithm/_tests/last_of_parameter_pack.cpp
Executable file
29
tjp/core/algorithm/_tests/last_of_parameter_pack.cpp
Executable file
@@ -0,0 +1,29 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/last_of_parameter_pack.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::last_of_parameter_pack")
|
||||
{
|
||||
WHEN("ranges")
|
||||
{
|
||||
static_assert(last_of_parameter_pack(1,2,3,4) == 4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/list_erase_if.cpp
Executable file
54
tjp/core/algorithm/_tests/list_erase_if.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/list_erase_if.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::list_erase_if")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = list_erase_if(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(erased == 4);
|
||||
REQUIRE(v.size() == 96);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = list_erase_if(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 96);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = list_erase_if(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/list_erase_if_value.cpp
Executable file
54
tjp/core/algorithm/_tests/list_erase_if_value.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/list_erase_if_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/List.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::list_erase_if_value")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
List<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = list_erase_if_value(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(erased == 4);
|
||||
REQUIRE(v.size() == 96);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = list_erase_if_value(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 96);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = list_erase_if_value(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/map_erase.cpp
Executable file
54
tjp/core/algorithm/_tests/map_erase.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_erase.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_erase")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = map_erase(
|
||||
v, 10
|
||||
);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
|
||||
WHEN("evens are erased again")
|
||||
{
|
||||
auto erased = map_erase(
|
||||
v, 10
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = map_erase(
|
||||
v, 1000
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/map_erase_if.cpp
Executable file
54
tjp/core/algorithm/_tests/map_erase_if.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_erase_if.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_erase_if")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("evens are erased")
|
||||
{
|
||||
auto erased = map_erase_if(
|
||||
v, [](auto &v) { return v.first % 2 == 0; }
|
||||
);
|
||||
REQUIRE(erased == 50);
|
||||
REQUIRE(v.size() == 50);
|
||||
|
||||
WHEN("evens are erased again")
|
||||
{
|
||||
auto erased = map_erase_if(
|
||||
v, [](auto &v) { return v.first % 2 == 0; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 50);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = map_erase_if(
|
||||
v, [](auto &v) { return v.first == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/map_erase_if_key.cpp
Executable file
54
tjp/core/algorithm/_tests/map_erase_if_key.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_erase_if_key.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_erase_if_key")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("evens are erased")
|
||||
{
|
||||
auto erased = map_erase_if_key(
|
||||
v, [](auto &v) { return v % 2 == 0; }
|
||||
);
|
||||
REQUIRE(erased == 50);
|
||||
REQUIRE(v.size() == 50);
|
||||
|
||||
WHEN("evens are erased again")
|
||||
{
|
||||
auto erased = map_erase_if_key(
|
||||
v, [](auto &v) { return v % 2 == 0; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 50);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = map_erase_if_key(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/map_erase_if_value.cpp
Executable file
54
tjp/core/algorithm/_tests/map_erase_if_value.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_erase_if_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_erase_if_value")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("evens are erased")
|
||||
{
|
||||
auto erased = map_erase_if_value(
|
||||
v, [](auto &v) { return v % 2 == 0; }
|
||||
);
|
||||
REQUIRE(erased == 50);
|
||||
REQUIRE(v.size() == 50);
|
||||
|
||||
WHEN("evens are erased again")
|
||||
{
|
||||
auto erased = map_erase_if_value(
|
||||
v, [](auto &v) { return v % 2 == 0; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 50);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = map_erase_if_value(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
33
tjp/core/algorithm/_tests/map_for_each_value.cpp
Executable file
33
tjp/core/algorithm/_tests/map_for_each_value.cpp
Executable file
@@ -0,0 +1,33 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_for_each_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_for_each_value")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = 1;
|
||||
|
||||
auto x = 0;
|
||||
map_for_each_value(
|
||||
v,
|
||||
[&](auto &v) { x += v; }
|
||||
);
|
||||
|
||||
REQUIRE(x == 100);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
44
tjp/core/algorithm/_tests/map_has.cpp
Executable file
44
tjp/core/algorithm/_tests/map_has.cpp
Executable file
@@ -0,0 +1,44 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_has.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_has")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
auto found = map_has(v, 42);
|
||||
REQUIRE(found);
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = map_has(v, 1000);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = map_has(v, 1000);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
44
tjp/core/algorithm/_tests/map_has_key.cpp
Executable file
44
tjp/core/algorithm/_tests/map_has_key.cpp
Executable file
@@ -0,0 +1,44 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_has_key.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_has_key")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
auto found = map_has_key(v, 42);
|
||||
REQUIRE(found);
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = map_has_key(v, 1000);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
auto found = map_has_key(v, 1000);
|
||||
REQUIRE(!found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
34
tjp/core/algorithm/_tests/map_iterator_or_insert.cpp
Executable file
34
tjp/core/algorithm/_tests/map_iterator_or_insert.cpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_iterator_or_insert.hpp>
|
||||
#include <tjp/core/algorithm/map_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_iterator_or_insert")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
map_iterator_insert(v, 0)->second = 42;
|
||||
map_iterator_insert(v, 1000)->second = 42;
|
||||
|
||||
REQUIRE(*map_value(v, 0) == 42);
|
||||
REQUIRE(*map_value(v, 1000) == 42);
|
||||
REQUIRE(*map_value(v, 1) == 1);
|
||||
REQUIRE(map_value(v, 1001) == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
37
tjp/core/algorithm/_tests/map_value.cpp
Executable file
37
tjp/core/algorithm/_tests/map_value.cpp
Executable file
@@ -0,0 +1,37 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_value")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
REQUIRE(map_value(v, 42) != nullptr);
|
||||
REQUIRE(*map_value(v, 42) == 42);
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
REQUIRE(map_value(v, 1000) == nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
37
tjp/core/algorithm/_tests/map_value_require.cpp
Executable file
37
tjp/core/algorithm/_tests/map_value_require.cpp
Executable file
@@ -0,0 +1,37 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/map_value_require.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Map.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::map_value_require")
|
||||
{
|
||||
GIVEN("a map of values")
|
||||
{
|
||||
Map<int, int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v[i] = i;
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("42 is found")
|
||||
{
|
||||
REQUIRE_NOTHROW(map_value_require(v, 42));
|
||||
REQUIRE(map_value_require(v, 42) == 42);
|
||||
}
|
||||
|
||||
WHEN("1000 is not found")
|
||||
{
|
||||
REQUIRE_THROWS(map_value_require(v, 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
34
tjp/core/algorithm/_tests/no_throw.cpp
Executable file
34
tjp/core/algorithm/_tests/no_throw.cpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/no_throw.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::no_throw")
|
||||
{
|
||||
GIVEN("throws")
|
||||
{
|
||||
auto throws = []() {
|
||||
throw std::runtime_error("exception");
|
||||
};
|
||||
|
||||
auto nthrows = no_throw(throws);
|
||||
|
||||
REQUIRE_NOTHROW(nthrows());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
34
tjp/core/algorithm/_tests/not_zero.cpp
Executable file
34
tjp/core/algorithm/_tests/not_zero.cpp
Executable file
@@ -0,0 +1,34 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/not_zero.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::not_zero")
|
||||
{
|
||||
WHEN("ranges")
|
||||
{
|
||||
auto minus_one = [](auto &&v) { return v - 1; };
|
||||
auto test_minus_one = not_zero(minus_one);
|
||||
|
||||
REQUIRE(test_minus_one(2));
|
||||
REQUIRE(!test_minus_one(1));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
77
tjp/core/algorithm/_tests/on_destruct.cpp
Executable file
77
tjp/core/algorithm/_tests/on_destruct.cpp
Executable file
@@ -0,0 +1,77 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/on_destruct.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::on_destruct")
|
||||
{
|
||||
GIVEN("a throw during destruct")
|
||||
{
|
||||
auto f = []() {
|
||||
auto throws = []() {
|
||||
throw std::runtime_error("exception");
|
||||
};
|
||||
|
||||
ExecuteOnDestruct x(throws, ExecuteOnDestruct::Throws);
|
||||
};
|
||||
|
||||
REQUIRE_THROWS(f());
|
||||
}
|
||||
|
||||
GIVEN("no throw during destruct")
|
||||
{
|
||||
auto f = []() {
|
||||
auto throws = []() {
|
||||
throw std::runtime_error("exception");
|
||||
};
|
||||
|
||||
ExecuteOnDestruct x(throws);
|
||||
};
|
||||
|
||||
REQUIRE_NOTHROW(f());
|
||||
}
|
||||
|
||||
GIVEN("a sequence of destructions")
|
||||
{
|
||||
Vector<int> destructs;
|
||||
{
|
||||
auto one = on_destruct([&](){destructs.push_back(1);});
|
||||
auto two = on_destruct([&](){destructs.push_back(2);});
|
||||
auto three = on_destruct([&](){destructs.push_back(3);});
|
||||
auto four = on_destruct([&](){destructs.push_back(4);});
|
||||
}
|
||||
|
||||
Vector<int> expected = { 4, 3, 2, 1 };
|
||||
REQUIRE(destructs == expected);
|
||||
}
|
||||
|
||||
GIVEN("a destruct on destructs once")
|
||||
{
|
||||
int i = 0;
|
||||
REQUIRE(i==0);
|
||||
|
||||
{
|
||||
auto destruct = on_destruct([&](){i++;});
|
||||
|
||||
destruct.execute();
|
||||
REQUIRE(i==1);
|
||||
|
||||
destruct.execute();
|
||||
REQUIRE(i==1);
|
||||
}
|
||||
|
||||
REQUIRE(i==1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
38
tjp/core/algorithm/_tests/one_is.cpp
Executable file
38
tjp/core/algorithm/_tests/one_is.cpp
Executable file
@@ -0,0 +1,38 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/one_is.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::one_is")
|
||||
{
|
||||
GIVEN("a vector of values")
|
||||
{
|
||||
Vector<int> v;
|
||||
for (auto i=0; i<50; ++i)
|
||||
v.push_back(41);
|
||||
|
||||
WHEN("none are 42")
|
||||
{
|
||||
auto one_is_42 = one_is(v, [](auto &v) { return v == 42; });
|
||||
REQUIRE(!one_is_42);
|
||||
}
|
||||
|
||||
WHEN("one is 42")
|
||||
{
|
||||
v[13] = 42;
|
||||
auto one_is_42 = one_is(v, [](auto &v) { return v == 42; });
|
||||
REQUIRE(one_is_42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
28
tjp/core/algorithm/_tests/optional_value.cpp
Executable file
28
tjp/core/algorithm/_tests/optional_value.cpp
Executable file
@@ -0,0 +1,28 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/optional_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Optional.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::optional_value")
|
||||
{
|
||||
GIVEN("optional value")
|
||||
{
|
||||
Optional<int> five = 5;
|
||||
REQUIRE(optional_value(five) != nullptr);
|
||||
REQUIRE(*optional_value(five) == 5);
|
||||
|
||||
Optional<int> empty;
|
||||
REQUIRE(optional_value(empty) == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
27
tjp/core/algorithm/_tests/optional_value_or_default.cpp
Executable file
27
tjp/core/algorithm/_tests/optional_value_or_default.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/optional_value_or_default.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Optional.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::optional_value_or_default")
|
||||
{
|
||||
GIVEN("optional value")
|
||||
{
|
||||
Optional<int> five = 5;
|
||||
REQUIRE(optional_value_or_default(five, 42) == 5);
|
||||
|
||||
Optional<int> empty;
|
||||
REQUIRE(optional_value_or_default(empty, 42) == 42);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
27
tjp/core/algorithm/_tests/set_empty.cpp
Executable file
27
tjp/core/algorithm/_tests/set_empty.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/set_empty.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Set.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::set_empty")
|
||||
{
|
||||
GIVEN("optional value")
|
||||
{
|
||||
Set<int> not_empty = { 1, 2, 3 };
|
||||
Set<int> empty = {};
|
||||
|
||||
REQUIRE(set_empty(empty));
|
||||
REQUIRE(!set_empty(not_empty));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
192
tjp/core/algorithm/_tests/small_cmp.cpp
Executable file
192
tjp/core/algorithm/_tests/small_cmp.cpp
Executable file
@@ -0,0 +1,192 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/small_cmp.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
#include <tjp/core/timer/Timer.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::small_cmp")
|
||||
{
|
||||
WHEN("cmp_small_a_lot")
|
||||
{
|
||||
Vector<Vector<size_t>> profiles;
|
||||
profiles.push_back({ 1, 4, 3, 7, 9, 14, 16, 8, 23, 4, 2, 3 });
|
||||
profiles.push_back({ 4, 4, 4, 4, 2, 2, 4, 4, 4, 8, 8, 8 });
|
||||
profiles.push_back({ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 });
|
||||
profiles.push_back({ 16, 16, 8, 8, 8, 3, 2, 1, 1, 1, 4, 8 });
|
||||
profiles.push_back({ 4, 4, 8, 4, 8, 8, 4, 4, 2, 2, 2, 2 });
|
||||
|
||||
constexpr auto max = 2048;
|
||||
char d_[max + 128];
|
||||
char s_[max + 128];
|
||||
|
||||
auto sum = 0;
|
||||
|
||||
for (auto i=0; i<max+128; ++i)
|
||||
{
|
||||
d_[i] = 'a' + std::rand() % 3;
|
||||
s_[i] = 'a' + std::rand() % 3;
|
||||
}
|
||||
|
||||
auto numCycles = 32768;
|
||||
|
||||
for (auto &chunks : profiles)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
Timer timer(false);
|
||||
|
||||
auto *reads = chunks.data();
|
||||
auto numReads = chunks.size();
|
||||
|
||||
// ------
|
||||
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
auto r0 = mem_cmp(d, readSize, s, readSize);
|
||||
auto r1 = small_cmp(d, readSize, s, readSize);
|
||||
|
||||
auto r0v = r0 < 0 ? -1 : (r0 > 0 ? 1 : 0);
|
||||
auto r1v = r1 < 0 ? -1 : (r1 > 0 ? 1 : 0);
|
||||
if (r0v != r1v)
|
||||
{
|
||||
auto rx = small_cmp(d, readSize, s, readSize);
|
||||
unused(rx);
|
||||
REQUIRE(false);
|
||||
}
|
||||
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
|
||||
// -------
|
||||
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
sum += small_cmp_v1(d, readSize, s, readSize);
|
||||
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV1Elapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
sum += small_cmp_v1a(d, readSize, s, readSize);
|
||||
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV1AElapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
sum += small_cmp_v2(d, readSize, s, readSize);
|
||||
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV2Elapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
sum += small_cmp_v3(d, readSize, s, readSize);
|
||||
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV3Elapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
sum += mem_cmp(d, readSize, s, readSize);
|
||||
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
|
||||
auto memcpyElapsed = timer.stop();
|
||||
|
||||
std::cout << "small_cmp_v1 " << std::setprecision(16) << readSmallV1Elapsed << std::endl;
|
||||
std::cout << "small_cmp_v1a " << std::setprecision(16) << readSmallV1AElapsed << std::endl;
|
||||
std::cout << "small_cmp_v2 " << std::setprecision(16) << readSmallV2Elapsed << std::endl;
|
||||
std::cout << "small_cmp_v3 " << std::setprecision(16) << readSmallV3Elapsed << std::endl;
|
||||
std::cout << "memcmp " << memcpyElapsed << std::endl;
|
||||
std::cout << "sum " << sum << std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
127
tjp/core/algorithm/_tests/small_copy.cpp
Executable file
127
tjp/core/algorithm/_tests/small_copy.cpp
Executable file
@@ -0,0 +1,127 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/small_copy.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/timer/Timer.hpp>
|
||||
|
||||
#include "../../log/LogOf.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::small_copy")
|
||||
{
|
||||
WHEN("read_small_a_lot")
|
||||
{
|
||||
Vector<Vector<size_t>> profiles;
|
||||
profiles.push_back({ 1, 4, 3, 7, 9, 14, 16, 8, 23, 4, 2, 3 });
|
||||
profiles.push_back({ 4, 4, 4, 4, 2, 2, 4, 4, 4, 8, 8, 8 });
|
||||
profiles.push_back({ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 });
|
||||
profiles.push_back({ 16, 16, 8, 8, 8, 3, 2, 1, 1, 1, 4, 8 });
|
||||
profiles.push_back({ 4, 4, 8, 4, 8, 8, 4, 4, 2, 2, 2, 2 });
|
||||
|
||||
constexpr auto max = 2048;
|
||||
char d_[max + 128];
|
||||
char s_[max + 128];
|
||||
auto numCycles = 32768;
|
||||
|
||||
for (auto &chunks : profiles)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
Timer timer(false);
|
||||
|
||||
auto *reads = chunks.data();
|
||||
auto numReads = chunks.size();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
small_copy_v3(d, s, readSize);
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV3Elapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
small_copy_v4a(d, s, readSize);
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV4aElapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
small_copy_v4b(d, s, readSize);
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
auto readSmallV4bElapsed = timer.stop();
|
||||
|
||||
timer.start();
|
||||
for (auto i=0; i<numCycles; ++i)
|
||||
{
|
||||
char *d = d_;
|
||||
char *s = s_;
|
||||
auto size = 0;
|
||||
|
||||
while (size < max)
|
||||
{
|
||||
auto readSize = reads[i % numReads];
|
||||
memcpy(d, s, readSize);
|
||||
d += readSize;
|
||||
s += readSize;
|
||||
size += readSize;
|
||||
}
|
||||
}
|
||||
|
||||
auto memcpyElapsed = timer.stop();
|
||||
|
||||
|
||||
std::cout << logVar(chunks) << std::endl;
|
||||
std::cout << "small_copy_v3 " << readSmallV3Elapsed << std::endl;
|
||||
std::cout << "small_copy_v4a " << readSmallV4aElapsed << std::endl;
|
||||
std::cout << "small_copy_v4b " << readSmallV4bElapsed << std::endl;
|
||||
std::cout << "memcpy " << memcpyElapsed << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
33
tjp/core/algorithm/_tests/starts_with.cpp
Executable file
33
tjp/core/algorithm/_tests/starts_with.cpp
Executable file
@@ -0,0 +1,33 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/starts_with.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/string/String.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::starts_with")
|
||||
{
|
||||
WHEN("Vector value")
|
||||
{
|
||||
Vector<int> v = { 1, 2, 3, 4, 5 };
|
||||
auto starts_with_123 = starts_with(v, Vector<int> {1,2,3});
|
||||
REQUIRE(starts_with_123);
|
||||
|
||||
auto starts_with_456 = starts_with(v, Vector<int> {4,5,6});
|
||||
REQUIRE(!starts_with_456);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
41
tjp/core/algorithm/_tests/vector_append.cpp
Executable file
41
tjp/core/algorithm/_tests/vector_append.cpp
Executable file
@@ -0,0 +1,41 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/vector_append.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::vector_append")
|
||||
{
|
||||
GIVEN("vector")
|
||||
{
|
||||
WHEN("using an empty vector")
|
||||
{
|
||||
Vector<int> empty = {};
|
||||
Vector<int> append = { 4, 5, 6 };
|
||||
|
||||
vector_append(empty, append);
|
||||
auto expected = append;
|
||||
REQUIRE(empty == expected);
|
||||
}
|
||||
|
||||
WHEN("using a non empty vector")
|
||||
{
|
||||
Vector<int> not_empty = { 1, 2, 3 };
|
||||
Vector<int> append = { 4, 5, 6 };
|
||||
|
||||
vector_append(not_empty, append);
|
||||
Vector<int> expected = { 1, 2, 3, 4, 5, 6 };
|
||||
REQUIRE(not_empty == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
54
tjp/core/algorithm/_tests/vector_erase_if_value.cpp
Executable file
54
tjp/core/algorithm/_tests/vector_erase_if_value.cpp
Executable file
@@ -0,0 +1,54 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/vector_erase_if_value.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::vector_erase_if_value")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
Vector<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = vector_erase_if_value(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(erased == 4);
|
||||
REQUIRE(v.size() == 96);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = vector_erase_if_value(
|
||||
v, [](auto &v) { return v == 10; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 96);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = vector_erase_if_value(
|
||||
v, [](auto &v) { return v == 1000; }
|
||||
);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
47
tjp/core/algorithm/_tests/vector_erase_value_all.cpp
Executable file
47
tjp/core/algorithm/_tests/vector_erase_value_all.cpp
Executable file
@@ -0,0 +1,47 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/vector_erase_value_all.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::vector_erase_value_all")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
Vector<int> v;
|
||||
for (auto i=0; i<100; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = vector_erase_value_all(v, 10);
|
||||
REQUIRE(erased==4);
|
||||
REQUIRE(v.size() == 96);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = vector_erase_value_all(v, 10);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 96);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = vector_erase_value_all(v, 1000);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
52
tjp/core/algorithm/_tests/vector_erase_value_one.cpp
Executable file
52
tjp/core/algorithm/_tests/vector_erase_value_one.cpp
Executable file
@@ -0,0 +1,52 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#include <tjp/core/algorithm/vector_erase_value_one.hpp>
|
||||
|
||||
#include <tjp/core/testing/catch.hpp>
|
||||
#include <tjp/core/containers/Vector.h>
|
||||
#include <tjp/core/algorithm/unused.hpp>
|
||||
|
||||
namespace tjp::core::algorithm {
|
||||
namespace {
|
||||
|
||||
SCENARIO("core::algorithm::vector_erase_value_one")
|
||||
{
|
||||
GIVEN("a list of values")
|
||||
{
|
||||
Vector<int> v;
|
||||
for (auto i=0; i<98; ++i)
|
||||
v.push_back(i / 4);
|
||||
|
||||
v.push_back(9999);
|
||||
v.push_back(999);
|
||||
|
||||
REQUIRE(v.size() == 100);
|
||||
WHEN("10 is erased")
|
||||
{
|
||||
auto erased = vector_erase_value_one(v, 10);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(v.size() == 99);
|
||||
REQUIRE(v[10 * 4] == 999);
|
||||
|
||||
WHEN("10 is erased again")
|
||||
{
|
||||
auto erased = vector_erase_value_one(v, 10);
|
||||
REQUIRE(erased);
|
||||
REQUIRE(v.size() == 98);
|
||||
REQUIRE(v[10 * 4 + 1] == 9999);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("1000 is not erased")
|
||||
{
|
||||
auto erased = vector_erase_value_one(v, 1000);
|
||||
REQUIRE(!erased);
|
||||
REQUIRE(v.size() == 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
19
tjp/core/algorithm/all_are.hpp
Executable file
19
tjp/core/algorithm/all_are.hpp
Executable file
@@ -0,0 +1,19 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
bool all_are(const T &l, F &&f)
|
||||
{
|
||||
for (auto &v: l)
|
||||
if (!f(v))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
18
tjp/core/algorithm/cmp.hpp
Executable file
18
tjp/core/algorithm/cmp.hpp
Executable file
@@ -0,0 +1,18 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
int cmp(const T &l, const T &r)
|
||||
{
|
||||
if (l == r)
|
||||
return 0;
|
||||
|
||||
return l < r ? -1 : 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
22
tjp/core/algorithm/container_count_if.hpp
Executable file
22
tjp/core/algorithm/container_count_if.hpp
Executable file
@@ -0,0 +1,22 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
size_t container_count_if (const T &c, F &&f)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (auto &v: c)
|
||||
if (f(v))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
27
tjp/core/algorithm/container_erase_if.hpp
Executable file
27
tjp/core/algorithm/container_erase_if.hpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../iterators/safe_next.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_erase_if (T &c, F &&f)
|
||||
{
|
||||
size_t erased = 0;
|
||||
for (auto i: safe_next(c))
|
||||
{
|
||||
if (f(*i))
|
||||
{
|
||||
c.erase(i);
|
||||
++erased;
|
||||
}
|
||||
}
|
||||
|
||||
return erased;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
31
tjp/core/algorithm/container_erase_if_imp_use_iterator.hpp
Executable file
31
tjp/core/algorithm/container_erase_if_imp_use_iterator.hpp
Executable file
@@ -0,0 +1,31 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_erase_if_imp_use_iterator(T &v, F &&f)
|
||||
{
|
||||
size_t erased = 0;
|
||||
|
||||
auto i = v.begin();
|
||||
while (i != v.end())
|
||||
{
|
||||
if (f(*i))
|
||||
{
|
||||
i = v.erase(i);
|
||||
++erased;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return erased;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
25
tjp/core/algorithm/container_erase_if_one.hpp
Executable file
25
tjp/core/algorithm/container_erase_if_one.hpp
Executable file
@@ -0,0 +1,25 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_erase_if_one (T &c, F &&f)
|
||||
{
|
||||
auto i = std::find_if(c.begin(), c.end(), std::forward<F>(f));
|
||||
|
||||
if (i != c.end())
|
||||
{
|
||||
c.erase(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
31
tjp/core/algorithm/container_erase_value_all.hpp
Executable file
31
tjp/core/algorithm/container_erase_value_all.hpp
Executable file
@@ -0,0 +1,31 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename U>
|
||||
auto container_erase_value_all (T &v, U &&u)
|
||||
{
|
||||
size_t erased = 0;
|
||||
|
||||
auto i = v.begin();
|
||||
while (i != v.end())
|
||||
{
|
||||
if ((*i) == std::forward<U>(u))
|
||||
{
|
||||
i = v.erase(i);
|
||||
++erased;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return erased;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
25
tjp/core/algorithm/container_erase_value_one.hpp
Executable file
25
tjp/core/algorithm/container_erase_value_one.hpp
Executable file
@@ -0,0 +1,25 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename U>
|
||||
auto container_erase_value_one (T &c, U &&u)
|
||||
{
|
||||
auto i = std::find(c.begin(), c.end(), std::forward<U>(u));
|
||||
|
||||
if (i != c.end())
|
||||
{
|
||||
c.erase(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
18
tjp/core/algorithm/container_find_if.hpp
Executable file
18
tjp/core/algorithm/container_find_if.hpp
Executable file
@@ -0,0 +1,18 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_find_if (T &c, F &&f)
|
||||
{
|
||||
return std::find_if(c.begin(), c.end(), std::forward<F>(f));
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
26
tjp/core/algorithm/container_get_if.hpp
Executable file
26
tjp/core/algorithm/container_get_if.hpp
Executable file
@@ -0,0 +1,26 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_get_if (T &&c, F &&u)
|
||||
{
|
||||
static_assert(std::is_lvalue_reference_v<T&&>, "requires an lvalue");
|
||||
auto i = std::find_if(c.begin(), c.end(), std::forward<F>(u));
|
||||
|
||||
if (i != c.end())
|
||||
{
|
||||
return &*i;
|
||||
}
|
||||
|
||||
typedef decltype(&*i) R;
|
||||
return (R)nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
25
tjp/core/algorithm/container_get_if_optional.hpp
Executable file
25
tjp/core/algorithm/container_get_if_optional.hpp
Executable file
@@ -0,0 +1,25 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_get_if_optional (const T &c, F &&u)
|
||||
{
|
||||
auto i = std::find_if(c.begin(), c.end(), std::forward<F>(u));
|
||||
|
||||
if (i != c.end())
|
||||
{
|
||||
return std::make_optional(*i);
|
||||
}
|
||||
|
||||
return std::optional<typename T::value_type>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
27
tjp/core/algorithm/container_get_if_optional_erase.hpp
Executable file
27
tjp/core/algorithm/container_get_if_optional_erase.hpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto container_get_if_optional_erase (T &c, F &&u)
|
||||
{
|
||||
auto i = std::find_if(c.begin(), c.end(), std::forward<F>(u));
|
||||
|
||||
if (i != c.end())
|
||||
{
|
||||
auto result = std::make_optional(std::move(*i));
|
||||
c.erase(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
return std::optional<typename T::value_type>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
27
tjp/core/algorithm/container_get_optional_erase.hpp
Executable file
27
tjp/core/algorithm/container_get_optional_erase.hpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename U>
|
||||
auto container_get_optional_erase (T &c, U &&u)
|
||||
{
|
||||
auto i = std::find(c.begin(), c.end(), std::forward<U>(u));
|
||||
|
||||
if (i != c.end())
|
||||
{
|
||||
auto result = std::make_optional(*i);
|
||||
c.erase(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
return std::optional<typename T::value_type>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/container_has.hpp
Executable file
17
tjp/core/algorithm/container_has.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename U>
|
||||
bool container_has (const T &c, const U &v)
|
||||
{
|
||||
return std::find(c.begin(), c.end(), v) != c.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/container_has_if.hpp
Executable file
17
tjp/core/algorithm/container_has_if.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
bool container_has_if (const T &c, F &&f)
|
||||
{
|
||||
return std::find_if(c.begin(), c.end(), std::forward<F>(f)) != c.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
26
tjp/core/algorithm/copy_clear.hpp
Executable file
26
tjp/core/algorithm/copy_clear.hpp
Executable file
@@ -0,0 +1,26 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename std::enable_if<(std::is_fundamental<T>::value || std::is_pointer<T>::value), T>::type* = nullptr>
|
||||
T copy_clear(T &t)
|
||||
{
|
||||
T t_{0};
|
||||
std::swap(t, t_);
|
||||
return t_;
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<!(std::is_fundamental<T>::value || std::is_pointer<T>::value), T>::type* = nullptr>
|
||||
T copy_clear(T &t, T &&t_=T())
|
||||
{
|
||||
std::swap(t, t_);
|
||||
return t_;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
20
tjp/core/algorithm/copy_clear_delete.hpp
Executable file
20
tjp/core/algorithm/copy_clear_delete.hpp
Executable file
@@ -0,0 +1,20 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
auto copy_clear_delete(T *&t)
|
||||
{
|
||||
T *t_{0};
|
||||
std::swap(t, t_);
|
||||
return unique_ptr<T>(t_);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
15
tjp/core/algorithm/copy_of.hpp
Executable file
15
tjp/core/algorithm/copy_of.hpp
Executable file
@@ -0,0 +1,15 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T>
|
||||
T copy_of(const T &t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
23
tjp/core/algorithm/emplace.hpp
Executable file
23
tjp/core/algorithm/emplace.hpp
Executable file
@@ -0,0 +1,23 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename ... Args>
|
||||
void emplace(T &t, Args && ...args)
|
||||
{
|
||||
t = T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto emplace(T &t, T &&rhs)
|
||||
{
|
||||
t = std::move(rhs);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
16
tjp/core/algorithm/empty_of.hpp
Executable file
16
tjp/core/algorithm/empty_of.hpp
Executable file
@@ -0,0 +1,16 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M>
|
||||
const M &empty_of()
|
||||
{
|
||||
static M m;
|
||||
return m;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
40
tjp/core/algorithm/ends_with.hpp
Executable file
40
tjp/core/algorithm/ends_with.hpp
Executable file
@@ -0,0 +1,40 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../string/StringView.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename U>
|
||||
bool ends_with (const T &c1, const U &c2)
|
||||
{
|
||||
if (c2.size() > c1.size())
|
||||
return false;
|
||||
|
||||
auto offset = c1.size() - c2.size();
|
||||
|
||||
auto c1i = c1.begin() + offset;
|
||||
auto c2i = c2.begin();
|
||||
while (c2i != c2.end())
|
||||
{
|
||||
if (*c1i != *c2i)
|
||||
return false;
|
||||
|
||||
++c1i;
|
||||
++c2i;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ends_with (const T &c1, const char *c2)
|
||||
{
|
||||
return ends_with(c1, StringView(c2));
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
15
tjp/core/algorithm/has_last.hpp
Executable file
15
tjp/core/algorithm/has_last.hpp
Executable file
@@ -0,0 +1,15 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
bool has_last(T &t, F &&f)
|
||||
{
|
||||
return !t.empty() && f(t.back());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
38
tjp/core/algorithm/has_sequence.hpp
Executable file
38
tjp/core/algorithm/has_sequence.hpp
Executable file
@@ -0,0 +1,38 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename U>
|
||||
bool has_sequence (const T &c1, const U &c2)
|
||||
{
|
||||
if (c2.size() > c1.size())
|
||||
return false;
|
||||
|
||||
auto end = c1.size() - c2.size();
|
||||
|
||||
for (auto offset = 0; offset <= end; ++offset)
|
||||
{
|
||||
auto c1i = c1.begin() + offset;
|
||||
auto c2i = c2.begin();
|
||||
while (c2i != c2.end())
|
||||
{
|
||||
if (*c1i != *c2i)
|
||||
break;
|
||||
|
||||
++c1i;
|
||||
++c2i;
|
||||
}
|
||||
|
||||
if (c2i == c2.end())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
16
tjp/core/algorithm/in_range_segment.hpp
Executable file
16
tjp/core/algorithm/in_range_segment.hpp
Executable file
@@ -0,0 +1,16 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename V, typename L, typename R>
|
||||
constexpr
|
||||
bool in_range_segment(const V &v, const L &offset, const R &size)
|
||||
{
|
||||
return (v >= offset) && (v < (offset + size));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/is_in.hpp
Executable file
17
tjp/core/algorithm/is_in.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
// https://stackoverflow.com/questions/15181579/c-most-efficient-way-to-compare-a-variable-to-multiple-values
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename First, typename ... T>
|
||||
constexpr bool is_in(First &&first, const T & ... t)
|
||||
{
|
||||
return ((first == t) || ...);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
14
tjp/core/algorithm/is_zero.hpp
Executable file
14
tjp/core/algorithm/is_zero.hpp
Executable file
@@ -0,0 +1,14 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename F>
|
||||
constexpr auto is_zero(F &&f) {
|
||||
return [f](auto &&v) { return f(v) == 0; };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/last_of_parameter_pack.hpp
Executable file
17
tjp/core/algorithm/last_of_parameter_pack.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename... Args>
|
||||
constexpr
|
||||
decltype(auto) last_of_parameter_pack(Args&&... args){
|
||||
return (std::forward<Args>(args), ...);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/list_erase_if.hpp
Executable file
17
tjp/core/algorithm/list_erase_if.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "container_erase_if_imp_use_iterator.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto list_erase_if(T &v, F &&f)
|
||||
{
|
||||
return container_erase_if_imp_use_iterator(v, std::forward<F>(f));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/list_erase_if_value.hpp
Executable file
17
tjp/core/algorithm/list_erase_if_value.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "list_erase_if.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto list_erase_if_value(T &v, F &&f)
|
||||
{
|
||||
return list_erase_if(v, std::forward<F>(f));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/list_erase_value_all.hpp
Executable file
17
tjp/core/algorithm/list_erase_value_all.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "container_erase_value_all.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
bool list_erase_value_all(M &m, K &&k)
|
||||
{
|
||||
return container_erase_value_all(m, std::forward<K>(k));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/list_erase_value_one.hpp
Executable file
17
tjp/core/algorithm/list_erase_value_one.hpp
Executable file
@@ -0,0 +1,17 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "container_erase_value_one.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
bool list_erase_value_one(M &m, K &&k)
|
||||
{
|
||||
return container_erase_value_one(m, std::forward<K>(k));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
24
tjp/core/algorithm/map_erase.hpp
Executable file
24
tjp/core/algorithm/map_erase.hpp
Executable file
@@ -0,0 +1,24 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename K>
|
||||
auto map_erase(T &map, K &&k)
|
||||
{
|
||||
auto i = map.find(std::forward<K>(k));
|
||||
if (i != map.end())
|
||||
{
|
||||
map.erase(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
26
tjp/core/algorithm/map_erase_get_optional.hpp
Executable file
26
tjp/core/algorithm/map_erase_get_optional.hpp
Executable file
@@ -0,0 +1,26 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename K>
|
||||
auto map_erase_get_optional(T &map, K &&k)
|
||||
{
|
||||
auto i = map.find(std::forward<K>(k));
|
||||
if (i != map.end())
|
||||
{
|
||||
auto v = std::make_optional(i->second);
|
||||
map.erase(i);
|
||||
return v;
|
||||
}
|
||||
|
||||
return std::optional<typename T::mapped_type>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
29
tjp/core/algorithm/map_erase_if.hpp
Executable file
29
tjp/core/algorithm/map_erase_if.hpp
Executable file
@@ -0,0 +1,29 @@
|
||||
// License: Modified MIT (NON-AI)
|
||||
// See the LICENSE file in the root directory for license information.
|
||||
// Copyright 2025 Timothy Prepscius
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename T, typename F>
|
||||
auto map_erase_if(T &map, F &&f)
|
||||
{
|
||||
int erased = 0;
|
||||
|
||||
auto i = map.begin();
|
||||
while (i != map.end())
|
||||
{
|
||||
if (f(*i))
|
||||
{
|
||||
++erased;
|
||||
i = map.erase(i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return erased;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user