flatten 20260225
This commit is contained in:
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
|
||||
29
tjp/core/algorithm/map_erase_if_key.hpp
Executable file
29
tjp/core/algorithm/map_erase_if_key.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_key(T &map, F &&f)
|
||||
{
|
||||
int erased = 0;
|
||||
|
||||
auto i = map.begin();
|
||||
while (i != map.end())
|
||||
{
|
||||
if (f(i->first))
|
||||
{
|
||||
++erased;
|
||||
i = map.erase(i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return erased;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
29
tjp/core/algorithm/map_erase_if_value.hpp
Executable file
29
tjp/core/algorithm/map_erase_if_value.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_value(T &map, F &&f)
|
||||
{
|
||||
int erased = 0;
|
||||
|
||||
auto i = map.begin();
|
||||
while (i != map.end())
|
||||
{
|
||||
if (f(i->second))
|
||||
{
|
||||
++erased;
|
||||
i = map.erase(i);
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return erased;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
16
tjp/core/algorithm/map_for_each_value.hpp
Executable file
16
tjp/core/algorithm/map_for_each_value.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 T, typename F>
|
||||
auto map_for_each_value(T &map, F &&f)
|
||||
{
|
||||
for (auto i=map.begin(); i!=map.end(); ++i)
|
||||
f(i->second);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/map_has.hpp
Executable file
17
tjp/core/algorithm/map_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 M, typename K>
|
||||
auto map_has(const M &m, K &&k)
|
||||
{
|
||||
return m.find(std::forward<K>(k)) != m.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
17
tjp/core/algorithm/map_has_key.hpp
Executable file
17
tjp/core/algorithm/map_has_key.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 "map_has.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
bool map_has_key (const M &m, K &&k)
|
||||
{
|
||||
return map_has(m, std::forward<K>(k));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
19
tjp/core/algorithm/map_insert.hpp
Executable file
19
tjp/core/algorithm/map_insert.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
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K, typename V>
|
||||
auto map_insert(M &&m, K &&k, V &&v)
|
||||
{
|
||||
auto [i, inserted] = m.emplace(std::forward<K>(k), std::forward<V>(v));
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
35
tjp/core/algorithm/map_iterator_or_insert.hpp
Executable file
35
tjp/core/algorithm/map_iterator_or_insert.hpp
Executable file
@@ -0,0 +1,35 @@
|
||||
// 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, typename K>
|
||||
auto map_iterator_insert(M &m, const K &k)
|
||||
{
|
||||
typedef typename M::mapped_type R;
|
||||
|
||||
auto i = m.find(k);
|
||||
if (i != m.end())
|
||||
return i;
|
||||
|
||||
auto [j, inserted] = m.emplace(k, R());
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
template<typename M, typename K, typename F>
|
||||
auto map_iterator_insert(M &m, const K &k, F &&f)
|
||||
{
|
||||
auto i = m.find(k);
|
||||
if (i != m.end())
|
||||
return i;
|
||||
|
||||
auto [j, inserted] = m.emplace(k, f());
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
32
tjp/core/algorithm/map_pair.hpp
Executable file
32
tjp/core/algorithm/map_pair.hpp
Executable file
@@ -0,0 +1,32 @@
|
||||
// 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, typename K>
|
||||
auto map_pair(const M &m, K &&k)
|
||||
{
|
||||
typedef typename M::value_type *R;
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
if (i != m.end())
|
||||
return &*i;
|
||||
|
||||
return (R)nullptr;
|
||||
}
|
||||
|
||||
template<typename M, typename K>
|
||||
auto map_pair(M &m, K &&k)
|
||||
{
|
||||
typedef typename M::value_type const *R;
|
||||
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
if (i != m.end())
|
||||
return &*i;
|
||||
|
||||
return (R)nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
20
tjp/core/algorithm/map_set_or_erase_optional.hpp
Executable file
20
tjp/core/algorithm/map_set_or_erase_optional.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 "map_erase.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K, typename V>
|
||||
auto map_set_or_erase_optional(M &m, K &&k, V &&v)
|
||||
{
|
||||
if (v)
|
||||
m[k] = *v;
|
||||
else
|
||||
map_erase(m, k);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
25
tjp/core/algorithm/map_value.hpp
Executable file
25
tjp/core/algorithm/map_value.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 <utility>
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
auto map_value(M &&m, K &&k)
|
||||
{
|
||||
static_assert(std::is_lvalue_reference_v<M&&>, "requires an lvalue");
|
||||
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
|
||||
return
|
||||
(i != m.end()) ?
|
||||
&i->second :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
28
tjp/core/algorithm/map_value_erase.hpp
Executable file
28
tjp/core/algorithm/map_value_erase.hpp
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
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../containers/Optional.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
auto map_value_erase(M &m, K &&k)
|
||||
{
|
||||
typedef typename M::mapped_type R;
|
||||
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
if (i != m.end())
|
||||
{
|
||||
auto result = Optional<R>(std::move(i->second));
|
||||
m.erase(i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return Optional<R>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
25
tjp/core/algorithm/map_value_optional.hpp
Executable file
25
tjp/core/algorithm/map_value_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 "../containers/Optional.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
auto map_value_optional(M &m, K &&k)
|
||||
{
|
||||
typedef typename M::mapped_type R;
|
||||
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
if (i != m.end())
|
||||
{
|
||||
return Optional<R>(std::move(i->second));
|
||||
}
|
||||
|
||||
return Optional<R>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
19
tjp/core/algorithm/map_value_or_default.hpp
Executable file
19
tjp/core/algorithm/map_value_or_default.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 M, typename K, typename V, typename R = typename M::mapped_type>
|
||||
R map_value_or_default(const M &m, K &&k, V &&v)
|
||||
{
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
if (i != m.end())
|
||||
return i->second;
|
||||
|
||||
return R(v);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
21
tjp/core/algorithm/map_value_or_insert.hpp
Executable file
21
tjp/core/algorithm/map_value_or_insert.hpp
Executable 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
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K, typename F>
|
||||
auto &map_value_or_insert(M &m, const K &k, const F &f)
|
||||
{
|
||||
auto i = m.find(k);
|
||||
if (i != m.end())
|
||||
return i->second;
|
||||
|
||||
auto [j, inserted] = m.emplace(k, f());
|
||||
|
||||
return j->second;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
16
tjp/core/algorithm/map_value_or_insert_value.hpp
Executable file
16
tjp/core/algorithm/map_value_or_insert_value.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, typename K, typename V>
|
||||
auto map_value_or_insert_value(M &m, K &&k, V &&v)
|
||||
{
|
||||
auto [i, inserted] = m.emplace(std::forward<K>(k), std::forward<V>(v));
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
21
tjp/core/algorithm/map_value_require.hpp
Executable file
21
tjp/core/algorithm/map_value_require.hpp
Executable 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../exception/Exception.hpp"
|
||||
|
||||
namespace tjp::core {
|
||||
|
||||
template<typename M, typename K>
|
||||
auto &map_value_require(M &m, K &&k)
|
||||
{
|
||||
auto i = m.find(std::forward<K>(k));
|
||||
if (i == m.end())
|
||||
throw Exception { "Map missing key" };
|
||||
|
||||
return i->second;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user