run v2
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,5 @@
|
|||||||
build
|
build
|
||||||
.cache
|
.cache
|
||||||
subprojects/*
|
subprojects/*
|
||||||
!subprojects/nlohmann_json.wrap
|
!subprojects/catch2.wrap
|
||||||
|
|
||||||
|
|||||||
@@ -10,3 +10,4 @@
|
|||||||
Тесты пишутся по необходимости и при наличии нужного настроения!!!
|
Тесты пишутся по необходимости и при наличии нужного настроения!!!
|
||||||
|
|
||||||
Но вы всегда можете это исправить. :)
|
Но вы всегда можете это исправить. :)
|
||||||
|
|
||||||
|
|||||||
10
bin/main.cpp
Normal file
10
bin/main.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "hack/patterns/ring_buffer.hpp"
|
||||||
|
|
||||||
|
auto main(int argc, char *argv[]) -> int
|
||||||
|
{
|
||||||
|
hack::patterns::ring_buffer<int, 10> rb;
|
||||||
|
for (int i = 1; i < 12; ++i) rb.put(i);
|
||||||
|
while(!rb.empty()) std::cout << rb.get().value() << std::endl;
|
||||||
|
}
|
||||||
7
bin/meson.build
Executable file
7
bin/meson.build
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
executable(
|
||||||
|
meson.project_name(),
|
||||||
|
'main.cpp',
|
||||||
|
dependencies : deps,
|
||||||
|
cpp_args: args,
|
||||||
|
include_directories : inc
|
||||||
|
)
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#include <vector>
|
|
||||||
#include <forward_list>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/algorithms/sort.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
{// ex: sort
|
|
||||||
std::vector<int> v { 4, 4, 6, 1, 4, 3, 2 };
|
|
||||||
std::forward_list<int> l { 8, 7, 5, 9, 0, 1, 3, 2, 6, 4 };
|
|
||||||
|
|
||||||
hack::algorithms::sort(v);
|
|
||||||
hack::algorithms::sort(l);
|
|
||||||
|
|
||||||
hack::log log;
|
|
||||||
log(v);
|
|
||||||
log(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#include <set>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/concepts/concepts.hpp"
|
|
||||||
|
|
||||||
template<hack::concepts::is_map T>
|
|
||||||
void test_map(const T& m)
|
|
||||||
{
|
|
||||||
hack::log()("is map", m);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<hack::concepts::is_associative_container T>
|
|
||||||
void test_associative(const T& m)
|
|
||||||
{
|
|
||||||
hack::log()("is associative", m);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<hack::concepts::is_unordered_set T>
|
|
||||||
void test_unordered_set(const T& m)
|
|
||||||
{
|
|
||||||
hack::log()("is unordered set", m);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
std::map<std::string, int> m { { "a", 1 }, { "b", 2 } };
|
|
||||||
test_map(m);
|
|
||||||
test_associative(m);
|
|
||||||
|
|
||||||
auto t = std::make_tuple("a", 1, "b", 2);
|
|
||||||
test_associative(t);
|
|
||||||
|
|
||||||
std::vector<int> v { 1, 2, 3 };
|
|
||||||
// test_associative(v); error !!!
|
|
||||||
|
|
||||||
std::unordered_set<int> us { 1, 2, 3 };
|
|
||||||
test_unordered_set(us);
|
|
||||||
test_associative(us);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#include <set>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/containers/containers.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
hack::log()("============================================================");
|
|
||||||
hack::log()("container::vector_multiset");
|
|
||||||
|
|
||||||
{// ex: containers::vector
|
|
||||||
std::vector<std::string> v;
|
|
||||||
hack::containers::vector::multiset(v, "asdf", "qwer", "zcv");
|
|
||||||
hack::log()(v);
|
|
||||||
|
|
||||||
hack::containers::vector::remove_at(v, 1);
|
|
||||||
hack::log()(v);
|
|
||||||
|
|
||||||
hack::containers::vector::multiset(v, "aa", "bb", "cc");
|
|
||||||
hack::log()(v);
|
|
||||||
|
|
||||||
auto it = std::find(v.begin(), v.end(), "aa");
|
|
||||||
hack::log()(*it);
|
|
||||||
hack::containers::vector::remove_at(v, it);
|
|
||||||
hack::log()(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: containers::utils::count
|
|
||||||
std::vector<std::string> v { "aa", "bb", "cc" };
|
|
||||||
auto r = hack::containers::utils::count(v, "aa", "bb");
|
|
||||||
hack::log()(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: containers::set
|
|
||||||
std::set<int> s;
|
|
||||||
hack::containers::set::multiset(s, 1, 2, 3);
|
|
||||||
hack::warn()("TODO: реализовать в log вывод set контейнера!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#include <set>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/iterators/associative_ostream_iterator.hpp"
|
|
||||||
#include "hack/concepts/concepts.hpp"
|
|
||||||
|
|
||||||
template<hack::concepts::is_map T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << "{";
|
|
||||||
std::copy(data.cbegin(), data.cend(), hack::iterators::associative_ostream_iterator<typename T::value_type>(data.size(), std::cout));
|
|
||||||
std::cout << "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
std::map<std::string, int> m { { "a", 1 }, { "b", 2 } };
|
|
||||||
|
|
||||||
for (auto& [key, value] : m)
|
|
||||||
hack::log()(key, value);
|
|
||||||
|
|
||||||
print_t(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#include <set>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
std::set<int> s { 1, 2, 3 };
|
|
||||||
hack::log()(s);
|
|
||||||
|
|
||||||
std::vector<int> v { 1, 2, 3 };
|
|
||||||
hack::log()(v, s);
|
|
||||||
|
|
||||||
std::unordered_set<int> us { 1, 2, 3 };
|
|
||||||
|
|
||||||
hack::log()(v, s, us);
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#include <set>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/macros/macros.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
std::string s { MAKE_STR(test) };
|
|
||||||
hack::log()(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/memory/make_ptr.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
auto a = hack::memory::make_unique<int>(5);
|
|
||||||
hack::log()(*a);
|
|
||||||
|
|
||||||
auto arr = hack::memory::make_unique<int[]>(5);
|
|
||||||
arr[0] = 1;
|
|
||||||
hack::log()(arr[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/security/uuid.hpp"
|
|
||||||
#include "hack/security/is_link.hpp"
|
|
||||||
#include "hack/security/is_string.hpp"
|
|
||||||
#include "hack/security/validate_email.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
auto uuid = hack::security::generate_uuid();
|
|
||||||
hack::log()(uuid);
|
|
||||||
|
|
||||||
hack::log()(hack::security::validate_uuid(uuid));
|
|
||||||
|
|
||||||
std::string url = "https://google.com";
|
|
||||||
hack::log()(hack::security::is_link(url));
|
|
||||||
|
|
||||||
hack::log()(hack::security::is_string<decltype (url)>::value);
|
|
||||||
|
|
||||||
std::string email = "asdf@asdf.com";
|
|
||||||
hack::log()(hack::security::validate_email(email));;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/string/string.hpp"
|
|
||||||
#include "hack/string/string_concat_helper.hpp"
|
|
||||||
#include "hack/string/utf8_len.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
{// ex: split string
|
|
||||||
std::string str { "asdf,qwer,zxcv" };
|
|
||||||
std::string str_int { "1 2 3" };
|
|
||||||
hack::string::v_str v = hack::string::split_str(str, ',');
|
|
||||||
auto v_int = hack::string::split_stoi(str_int, ' ');
|
|
||||||
hack::log log;
|
|
||||||
for (const auto& c : v) log(c);
|
|
||||||
for (const auto& c : v_int) log(c);
|
|
||||||
|
|
||||||
std::string str_2 { "qqq,aaa:eee,ggg" };
|
|
||||||
hack::string::v_str v_2 = hack::string::split_str(str_2, ",:");
|
|
||||||
for (const auto& c : v_2) log(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: string::str_concat
|
|
||||||
std::string name = "tro";
|
|
||||||
std::string surname = "lolo";
|
|
||||||
const auto full_name = hack::string::str_concat + name + ", " + surname;
|
|
||||||
hack::log()(full_name);
|
|
||||||
hack::log()(hack::string::str_concat + "super", + "string");
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: utf8_size
|
|
||||||
std::string str = "hi hi";
|
|
||||||
auto s = hack::string::utf8_len(str);
|
|
||||||
hack::log()(s);
|
|
||||||
|
|
||||||
s = hack::string::utf8_len("asdf");
|
|
||||||
hack::log()(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/utils/utils.hpp"
|
|
||||||
#include "hack/utils/singleton.hpp"
|
|
||||||
|
|
||||||
int f(int a)
|
|
||||||
{
|
|
||||||
hack::log()("f implementatioln");
|
|
||||||
return ++a;
|
|
||||||
}
|
|
||||||
|
|
||||||
int plus(int a)
|
|
||||||
{
|
|
||||||
return ++a;
|
|
||||||
}
|
|
||||||
|
|
||||||
int minus(int a)
|
|
||||||
{
|
|
||||||
return --a;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct counter_test
|
|
||||||
{
|
|
||||||
counter_test() : id { ++hack::utils::counter<int>::id } { }
|
|
||||||
int id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct counter_test_2
|
|
||||||
{
|
|
||||||
counter_test_2() : id { ++hack::utils::counter<int>::id } { }
|
|
||||||
int id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct test_singleton : public hack::utils::singleton<test_singleton>
|
|
||||||
{
|
|
||||||
void print()
|
|
||||||
{
|
|
||||||
hack::log()("Print singleton");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
{// ex: utils::func_memory
|
|
||||||
int a = 12;
|
|
||||||
auto cach_f = hack::utils::func_memory(f);
|
|
||||||
hack::log()("result 1", cach_f(a));
|
|
||||||
hack::log()("result 2", cach_f(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: utils::func_concat
|
|
||||||
int a = 1;
|
|
||||||
auto combine ( hack::utils::func_concat(plus, minus, plus, f) );
|
|
||||||
hack::log("")("func_concat result: ", combine(a), a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// {// ex: utils::exec
|
|
||||||
// hack::log()(hack::utils::unix_cmd("ls"));
|
|
||||||
// hack::log()(hack::utils::unix_cmd("pwd"));
|
|
||||||
// auto t = hack::utils::unix_cmd("pwd");
|
|
||||||
// hack::log::type_trace(t);
|
|
||||||
// }
|
|
||||||
|
|
||||||
{// ex: counter
|
|
||||||
counter_test a, b, c;
|
|
||||||
counter_test_2 a1, b1, c1;
|
|
||||||
hack::log()(c.id);
|
|
||||||
hack::log()(c1.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: case as string
|
|
||||||
switch(hack::utils::case_int("test"))
|
|
||||||
{
|
|
||||||
case hack::utils::case_int("test"): hack::log()("wow"); break;
|
|
||||||
case hack::utils::case_int("no_test"): hack::log()("ups"); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{// ex: singleton
|
|
||||||
test_singleton::instance().print();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ args = []
|
|||||||
inc = []
|
inc = []
|
||||||
deps = [
|
deps = [
|
||||||
dependency('uuid'),
|
dependency('uuid'),
|
||||||
subproject('nlohmann_json').get_variable('nlohmann_json_dep'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
|
subdir('bin')
|
||||||
subdir('tests')
|
subdir('tests')
|
||||||
|
|||||||
24
run.sh
24
run.sh
@@ -4,16 +4,24 @@ PROJECT_NAME=$(basename $PWD)
|
|||||||
|
|
||||||
run() {
|
run() {
|
||||||
command meson compile -C build
|
command meson compile -C build
|
||||||
if [[ -z "$1" ]]; then
|
cd build
|
||||||
cd build
|
./bin/$PROJECT_NAME
|
||||||
./tests/$PROJECT_NAME
|
cd ..
|
||||||
cd ..
|
|
||||||
else
|
|
||||||
meson test $1 -C build
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -d "build" ]; then
|
# run test [name_test]
|
||||||
|
# example: run test pattrens
|
||||||
|
if [ $1 = "test" ]; then
|
||||||
|
echo ""
|
||||||
|
meson test $2 -C build
|
||||||
|
echo ""
|
||||||
|
awk '/^-------------------------------------------------------------------------------/{flag=1} /===============================================================================/{flag=0} flag' ./build/meson-logs/testlog.txt
|
||||||
|
elif [ $1 = "tests" ]; then
|
||||||
|
echo ""
|
||||||
|
meson test -C build
|
||||||
|
echo ""
|
||||||
|
# awk '/^-------------------------------------------------------------------------------/{flag=1} /===============================================================================/{flag=0} flag' ./build/meson-logs/testlog.txt
|
||||||
|
elif [ -d "build" ]; then
|
||||||
run
|
run
|
||||||
else
|
else
|
||||||
command meson setup build
|
command meson setup build
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace hack::algorithms
|
|
||||||
{
|
|
||||||
// общая сортировка диапозонов, у кого-то есть своя локалная сортировка, а у кого-то
|
|
||||||
// нет. А тут чтоб не реализовывать, есть общая.
|
|
||||||
template<typename Range>
|
|
||||||
void sort_imp(Range& r, long)
|
|
||||||
{
|
|
||||||
std::sort(std::begin(r), std::end(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Range, typename = decltype(std::declval<Range&>().sort())>
|
|
||||||
auto sort_imp(Range& r, int) -> void
|
|
||||||
{
|
|
||||||
r.sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Range>
|
|
||||||
void sort(Range& r)
|
|
||||||
{
|
|
||||||
sort_imp(r, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <forward_list>
|
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
|
|
||||||
namespace hack::concepts
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
concept is_map = std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
|
|
||||||
std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept is_tuple = requires (T t) { std::tuple_cat(t, std::make_tuple(1, "tuple")); };
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept is_set = std::same_as<T, std::set<typename T::key_type, typename T::key_compare, typename T::allocator_type>>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept is_unordered_set = std::same_as<T, std::unordered_set<typename T::key_type>>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept is_forward_list = std::same_as<T, std::forward_list<typename T::value_type>>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept is_string = std::is_convertible_v<T, std::string_view>;
|
|
||||||
|
|
||||||
template<typename T, std::size_t N = 0>
|
|
||||||
concept is_sequence_container = std::same_as<T, std::vector<typename T::value_type>> || std::same_as<T, std::list<typename T::value_type>> || (std::is_array_v<T> && N > 0);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept is_associative_container = is_map<T> || is_tuple<T> || is_set<T> || is_unordered_set<T>;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
concept not_defined = !std::enable_if_t<!(std::integral<T> ||
|
|
||||||
is_sequence_container<T> ||
|
|
||||||
is_map<T> ||
|
|
||||||
is_tuple<T> ||
|
|
||||||
is_set<T> ||
|
|
||||||
is_unordered_set<T> ||
|
|
||||||
is_forward_list<T> ||
|
|
||||||
std::is_array<T>() ||
|
|
||||||
is_string<T>), bool>() == true;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "vector.hpp"
|
|
||||||
#include "utils.hpp"
|
|
||||||
#include "set.hpp"
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace hack::containers::set
|
|
||||||
{
|
|
||||||
// множественная вставка элементов
|
|
||||||
template<typename Range, typename... Args>
|
|
||||||
void multiset(Range& r, Args... args)
|
|
||||||
{
|
|
||||||
(r.insert(args), ...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace hack::containers::utils
|
|
||||||
{
|
|
||||||
// подсчитывает кол-во присутствующих элементов в диапозоне
|
|
||||||
template<typename Range, typename... Args>
|
|
||||||
int count(Range r, Args... args)
|
|
||||||
{
|
|
||||||
return (std::count(std::cbegin(r), std::cend(r), args) + ...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace hack::containers::vector
|
|
||||||
{
|
|
||||||
// множественная вставка элементов
|
|
||||||
template<typename Range, typename... Args>
|
|
||||||
void multiset(Range& r, Args... args)
|
|
||||||
{
|
|
||||||
constexpr std::size_t t = sizeof... (args);
|
|
||||||
r.reserve(t);
|
|
||||||
(r.emplace_back(std::forward<Args>(args)), ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
// удаление элемента вектора по его индексу, если не важна сортировка
|
|
||||||
template<typename T>
|
|
||||||
void remove_at(std::vector<T>& v, std::size_t idx)
|
|
||||||
{
|
|
||||||
if (idx < v.size())
|
|
||||||
{
|
|
||||||
v[idx] = std::move(v.back());
|
|
||||||
v.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// удаление элемента вектора по его итератору, если не важна сортировка
|
|
||||||
template<typename T>
|
|
||||||
void remove_at(std::vector<T>& v, typename std::vector<T>::iterator it)
|
|
||||||
{
|
|
||||||
if (it != v.end())
|
|
||||||
{
|
|
||||||
*it = std::move(v.back());
|
|
||||||
v.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <experimental/source_location>
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
#include "nlohmann/json.hpp"
|
|
||||||
|
|
||||||
#define DEF_LINE() std::experimental::source_location::current().line()
|
|
||||||
#define DEF_LOCATION() std::experimental::source_location::current()
|
|
||||||
|
|
||||||
#include "hack/view/color.hpp"
|
|
||||||
#include "hack/logger/logger.hpp"
|
|
||||||
#include "hack/utils/json_converter.hpp"
|
|
||||||
|
|
||||||
namespace hack
|
|
||||||
{
|
|
||||||
using JSON = nlohmann::json;
|
|
||||||
|
|
||||||
class exception : public utils::json_converter<JSON>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
exception(const std::experimental::source_location loc = DEF_LOCATION()) : m_location { loc } {}
|
|
||||||
~exception() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void message(const std::string v) noexcept { m_message = v; }
|
|
||||||
void description(const std::string v) noexcept { m_description = v; }
|
|
||||||
void system_error(const std::exception& e) noexcept { m_system_error = e.what(); }
|
|
||||||
void service(const std::string v) noexcept { m_service = v; }
|
|
||||||
|
|
||||||
template<typename Param>
|
|
||||||
void params(std::string key, Param value) { m_params[key] = value; }
|
|
||||||
|
|
||||||
// если что-то не значительное, но в больших обемах, то можно использовать этот метод
|
|
||||||
// на выходе будет что-то типа { "arg_1" : 123, "arg_2" : "value" }
|
|
||||||
template<typename... Args>
|
|
||||||
void variadic_params(Args... args)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
([&] { m_params["arg_" + std::to_string(++i)] = args; }(), ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Transaction>
|
|
||||||
void transaction(Transaction& tr)
|
|
||||||
{
|
|
||||||
m_params["transaction"] = tr.convert_to_json();
|
|
||||||
tr.m_data.m_result["status"] = "error";
|
|
||||||
tr.m_data.m_result["result"] = m_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
void log()
|
|
||||||
{
|
|
||||||
std::cout << view::color::bold << view::color::red <<"["+m_service+"] " << view::color::reset
|
|
||||||
<< m_location.file_name() << ":"
|
|
||||||
<< view::color::italic << view::color::yellow << m_location.function_name() << "()" << view::color::reset
|
|
||||||
<< view::color::bold << view::color::blue << "[" << m_location.line() << "]" << view::color::reset << ": "
|
|
||||||
<< m_message << std::endl;
|
|
||||||
|
|
||||||
if (!m_description.empty())
|
|
||||||
std::cout << view::color::bold << view::color::red <<"["+m_service+"] " << view::color::reset
|
|
||||||
<< m_location.file_name() << ":"
|
|
||||||
<< view::color::italic << view::color::yellow << m_location.function_name() << "()" << view::color::reset
|
|
||||||
<< view::color::bold << view::color::blue << "[" << m_location.line() << "]" << view::color::reset << ": "
|
|
||||||
<< m_description << std::endl;
|
|
||||||
|
|
||||||
if (!m_system_error.empty())
|
|
||||||
std::cout << view::color::bold << view::color::red <<"["+m_service+"] " << view::color::reset
|
|
||||||
<< m_location.file_name() << ":"
|
|
||||||
<< view::color::italic << view::color::yellow << m_location.function_name() << "()" << view::color::reset
|
|
||||||
<< view::color::bold << view::color::blue << "[" << m_location.line() << "]" << view::color::reset << ": "
|
|
||||||
<< m_system_error << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON convert_to_json() override
|
|
||||||
{
|
|
||||||
JSON j;
|
|
||||||
j["description"] = m_description;
|
|
||||||
j["system_error"] = m_system_error;
|
|
||||||
j["location"] = m_location.file_name();
|
|
||||||
j["function_name"] = m_location.function_name();
|
|
||||||
j["message"] = m_message;
|
|
||||||
j["service"] = m_service;
|
|
||||||
j["params"] = m_params;
|
|
||||||
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_message { "no valid data" };
|
|
||||||
std::string m_description;
|
|
||||||
std::string m_system_error;
|
|
||||||
std::string m_service;
|
|
||||||
std::experimental::source_location m_location;
|
|
||||||
JSON m_params;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace hack::iterators
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
class associative_ostream_iterator
|
|
||||||
{
|
|
||||||
using iterator_category = std::output_iterator_tag;
|
|
||||||
using traits = std::char_traits<char>;
|
|
||||||
using ostream_type = std::basic_ostream<char, traits>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::basic_ostream<char, traits>* os_;
|
|
||||||
const std::string devider_ = ", ";
|
|
||||||
std::size_t size_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
associative_ostream_iterator(std::size_t size, ostream_type& os) : os_ { &os }, size_ { size } { }
|
|
||||||
|
|
||||||
auto& operator=(const T& item)
|
|
||||||
{
|
|
||||||
--size_;
|
|
||||||
const auto& [key, value] = item;
|
|
||||||
*os_ << "{ " << key << ":" << value << " }" << (size_ != 0 ? devider_ : "");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& operator*()
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& operator++()
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace hack::iterators
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
class sequence_ostream_iterator
|
|
||||||
{
|
|
||||||
using iterator_category = std::output_iterator_tag;
|
|
||||||
using traits = std::char_traits<char>;
|
|
||||||
using ostream_type = std::basic_ostream<char, traits>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::basic_ostream<char, traits>* os_;
|
|
||||||
std::string devider_ = ", ";
|
|
||||||
std::size_t size_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
sequence_ostream_iterator(std::size_t size, ostream_type& os) : os_ { &os }, size_ { size } { }
|
|
||||||
|
|
||||||
auto& operator=(T const& item)
|
|
||||||
{
|
|
||||||
--size_;
|
|
||||||
*os_ << item << (size_ != 0 ? devider_ : "");
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& operator*()
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& operator++()
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,224 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <experimental/source_location>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// #include "boost/type_index.hpp"
|
|
||||||
|
|
||||||
#include "hack/view/color.hpp"
|
|
||||||
#include "hack/concepts/concepts.hpp"
|
|
||||||
#include "hack/iterators/sequence_ostream_iterator.hpp"
|
|
||||||
#include "hack/iterators/associative_ostream_iterator.hpp"
|
|
||||||
#include "hack/math/matrix.hpp"
|
|
||||||
|
|
||||||
namespace hack
|
|
||||||
{
|
|
||||||
class log
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
log(std::string devider_ = ", ", std::experimental::source_location location_ = std::experimental::source_location::current()) : location { location_ }
|
|
||||||
{
|
|
||||||
this->devider = devider_;
|
|
||||||
}
|
|
||||||
|
|
||||||
log(log&) = delete;
|
|
||||||
log(log&&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<typename... Args>
|
|
||||||
void operator() (const Args&... args)
|
|
||||||
{
|
|
||||||
count = sizeof...(Args);
|
|
||||||
prepare(make_type_view, location);
|
|
||||||
print(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
// template<typename... Args>
|
|
||||||
// static void type_trace(const Args&... args)
|
|
||||||
// {
|
|
||||||
// std::cout << make_type_view << ": " << view::color::reset;
|
|
||||||
// count = sizeof...(Args);
|
|
||||||
// print(boost::typeindex::type_id<Args>().pretty_name()...);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::experimental::source_location location;
|
|
||||||
inline static int count = 0;
|
|
||||||
inline static std::string devider = " ";
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<typename T, typename U>
|
|
||||||
void prepare(T t, U u)
|
|
||||||
{
|
|
||||||
std::cout << t
|
|
||||||
<< u.file_name() << ":" << view::color::reset
|
|
||||||
<< view::color::italic << view::color::yellow << u.function_name() << "()" << view::color::reset
|
|
||||||
<< view::color::bold << view::color::blue << "[" << u.line() << "]" << view::color::reset << ": ";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print() { std::cout << std::endl; }
|
|
||||||
|
|
||||||
static std::ostream& make_type_view(std::ostream &os)
|
|
||||||
{
|
|
||||||
os << view::color::bold << view::color::green << "[ok]" << view::color::reset << view::color::green;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
static void print(const T& data, const Args&... args)
|
|
||||||
{
|
|
||||||
--count;
|
|
||||||
print_t(data);
|
|
||||||
print(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_string T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << data << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::integral T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << data << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_sequence_container T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << "{ ";
|
|
||||||
std::copy(data.cbegin(), data.cend(), iterators::sequence_ostream_iterator<typename T::value_type>(data.size(), std::cout));
|
|
||||||
std::cout << " }" << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_set T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << "{ ";
|
|
||||||
std::copy(data.cbegin(), data.cend(), iterators::sequence_ostream_iterator<typename T::value_type>(data.size(), std::cout));
|
|
||||||
std::cout << " }" << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_unordered_set T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << "{ ";
|
|
||||||
std::copy(data.cbegin(), data.cend(), iterators::sequence_ostream_iterator<typename T::value_type>(data.size(), std::cout));
|
|
||||||
std::cout << " }" << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_forward_list T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << "{ ";
|
|
||||||
std::copy(data.cbegin(), data.cend(), iterators::sequence_ostream_iterator<typename T::value_type>(std::distance(data.cbegin(), data.cend()), std::cout));
|
|
||||||
std::cout << " }" << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_map T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << "{";
|
|
||||||
std::copy(data.begin(), data.cend(), iterators::associative_ostream_iterator<typename T::value_type>(data.size(), std::cout));
|
|
||||||
std::cout << "}" << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::is_tuple T, typename std::size_t... idx>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
print_t(data, std::make_index_sequence<std::tuple_size<T>::value>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::size_t... idx>
|
|
||||||
static void print_t(const T& data, std::index_sequence<idx...>)
|
|
||||||
{
|
|
||||||
std::cout << "{ ";
|
|
||||||
((std::cout << std::get<idx>(data) << (idx != std::tuple_size<T>::value - 1 ? devider : "")), ...);
|
|
||||||
std::cout << " }" << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, std::size_t demention>
|
|
||||||
static void print_t(const matrix<T, demention>& data)
|
|
||||||
{
|
|
||||||
std::size_t index = data.size();
|
|
||||||
for (auto& r : data)
|
|
||||||
{
|
|
||||||
--index;
|
|
||||||
std::cout << "{ ";
|
|
||||||
print_t(std::get<demention>(r));
|
|
||||||
std::cout << " }" << (index != 0 ? ", " : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<concepts::not_defined T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << data << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class warn;
|
|
||||||
friend class error;
|
|
||||||
};
|
|
||||||
|
|
||||||
class warn : public log
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
warn(std::string devider_ = ", ", std::experimental::source_location location_ = std::experimental::source_location::current()) : location { location_ }
|
|
||||||
{
|
|
||||||
this->devider = devider_;
|
|
||||||
}
|
|
||||||
|
|
||||||
warn(warn&) = delete;
|
|
||||||
warn(warn&&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<typename... Args>
|
|
||||||
void operator() (const Args&... args)
|
|
||||||
{
|
|
||||||
prepare(make_type_view, location);
|
|
||||||
count = sizeof...(Args);
|
|
||||||
print(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::experimental::source_location location;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::ostream& make_type_view(std::ostream &os)
|
|
||||||
{
|
|
||||||
os << view::color::bold << view::color::yellow << "[WARN]" << view::color::reset << view::color::yellow;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class error : public log
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
error(std::string devider_ = ", ", std::experimental::source_location location_ = std::experimental::source_location::current()) : location { location_ }
|
|
||||||
{
|
|
||||||
this->devider = devider_;
|
|
||||||
}
|
|
||||||
error(error&) = delete;
|
|
||||||
error(error&&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<typename... Args>
|
|
||||||
void operator() (const Args&... args)
|
|
||||||
{
|
|
||||||
prepare(make_type_view, location);
|
|
||||||
count = sizeof...(Args);
|
|
||||||
print(args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::experimental::source_location location;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::ostream& make_type_view(std::ostream &os)
|
|
||||||
{
|
|
||||||
os << view::color::bold << view::color::red << "[ERROR]" << view::color::reset << view::color::red;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#define MAKE_STR2(x) #x
|
|
||||||
#define MAKE_STR(x) MAKE_STR2(x)
|
|
||||||
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <tuple>
|
|
||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace hack::matrix_utils
|
|
||||||
{
|
|
||||||
template<typename T, std::size_t N>
|
|
||||||
struct generate_tuple
|
|
||||||
{
|
|
||||||
using type = decltype(std::tuple_cat(typename generate_tuple<T, N - 1>::type{}, std::make_tuple(T{})));
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct generate_tuple<T, 1>
|
|
||||||
{
|
|
||||||
using type = std::tuple<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T,typename index_data, typename index_t>
|
|
||||||
class proxy
|
|
||||||
{
|
|
||||||
using next_index_t = decltype(std::tuple_cat(index_t{}, std::make_tuple(std::size_t{})));
|
|
||||||
|
|
||||||
public:
|
|
||||||
proxy(const std::weak_ptr<index_data>& local_storage, const index_t& index) : local_storage_ { local_storage }, index_ { index } {};
|
|
||||||
|
|
||||||
auto operator[](std::size_t index) const
|
|
||||||
{
|
|
||||||
return proxy<T, index_data, next_index_t>{ local_storage_, std::tuple_cat(index_, std::make_tuple(index)) };
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& operator=(const T& value)
|
|
||||||
{
|
|
||||||
std::shared_ptr<index_data>(local_storage_)->set_value(index_, value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T() const
|
|
||||||
{
|
|
||||||
return std::shared_ptr<index_data>(local_storage_)->get_value(index_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::weak_ptr<index_data> local_storage_;
|
|
||||||
index_t index_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace hack
|
|
||||||
{
|
|
||||||
template <typename... T, std::size_t... I>
|
|
||||||
auto subtuple_s(const std::tuple<T...>& t, std::index_sequence<I...>)
|
|
||||||
{
|
|
||||||
return std::make_tuple(std::get<I>(t)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
auto subtuple(const std::tuple<T...>& t)
|
|
||||||
{
|
|
||||||
return subtuple_s(t, std::make_index_sequence<sizeof...(T) - 1>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, std::size_t dimensions>
|
|
||||||
class matrix
|
|
||||||
{
|
|
||||||
using index_t = typename matrix_utils::generate_tuple<std::size_t, dimensions>::type;
|
|
||||||
using vector_t = decltype(std::tuple_cat(index_t{}, std::make_tuple(T{})));
|
|
||||||
using index_data_t = std::vector<vector_t>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
matrix() noexcept : local_storage_ { new index_data{} } { }
|
|
||||||
matrix(std::initializer_list<vector_t> l) noexcept : local_storage_ { new index_data{} }
|
|
||||||
{
|
|
||||||
local_storage_->values.insert(local_storage_->values.end(), l.begin(), l.end());
|
|
||||||
}
|
|
||||||
matrix(matrix& mt) noexcept : local_storage_ { mt.local_storage_ } { }
|
|
||||||
matrix(matrix&& mt) noexcept : local_storage_ { mt.local_storage_ } { }
|
|
||||||
|
|
||||||
matrix& operator=(matrix&& mt)
|
|
||||||
{
|
|
||||||
if (this == &mt) return *this;
|
|
||||||
local_storage_.reset();
|
|
||||||
local_storage_ = mt.local_storage_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix& operator=(const matrix& mt)
|
|
||||||
{
|
|
||||||
if (this == &mt) return *this;
|
|
||||||
local_storage_ = mt.local_storage_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator[](std::size_t index)
|
|
||||||
{
|
|
||||||
return matrix_utils::proxy<T, index_data, std::tuple<std::size_t>>{ local_storage_, std::make_tuple(index) };
|
|
||||||
}
|
|
||||||
|
|
||||||
int size() const
|
|
||||||
{
|
|
||||||
return local_storage_->values.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto begin() noexcept
|
|
||||||
{
|
|
||||||
return local_storage_->values.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto begin() const noexcept
|
|
||||||
{
|
|
||||||
return local_storage_->values.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto end() noexcept
|
|
||||||
{
|
|
||||||
return local_storage_->values.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto end() const noexcept
|
|
||||||
{
|
|
||||||
return local_storage_->values.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cbegin() const noexcept
|
|
||||||
{
|
|
||||||
return local_storage_->values.cbegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cend() const noexcept
|
|
||||||
{
|
|
||||||
return local_storage_->values.cend();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct index_data
|
|
||||||
{
|
|
||||||
void set_value(const index_t& index, const T& v)
|
|
||||||
{
|
|
||||||
auto value = std::tuple_cat(index, std::make_tuple(v));
|
|
||||||
values.push_back(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto get_value(const index_t& index)
|
|
||||||
{
|
|
||||||
auto it = std::find_if(values.begin(), values.end(), [&](auto a) { return subtuple(a) == index; });
|
|
||||||
return std::get<dimensions>(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
index_data_t values;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<index_data> local_storage_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename U, std::size_t N>
|
|
||||||
bool operator==(const matrix<T, N>& lhs, const matrix<U, N>& rhs)
|
|
||||||
{
|
|
||||||
return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace hack
|
|
||||||
{
|
|
||||||
// std::common_type_t - делает сравнение по правилу тенарного оператора
|
|
||||||
// и выводит низводящий возвращающий тип. Т.е. если в качестве одного из
|
|
||||||
// параметров передалась ссылка, то произойдет низведление до типа ссылки
|
|
||||||
template<typename T, typename U, typename RT = std::common_type_t<T, U>>
|
|
||||||
inline RT max(T a, U b)
|
|
||||||
{
|
|
||||||
return std::max(a, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace hack
|
|
||||||
{
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
struct generate_tuple
|
|
||||||
{
|
|
||||||
using type = decltype(std::tuple_cat(std::make_tuple(T{}), typename generate_tuple<Args...>::type{}));
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct generate_tuple<T>
|
|
||||||
{
|
|
||||||
using type = std::tuple<T>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace hack
|
|
||||||
{
|
|
||||||
template<typename... Args>
|
|
||||||
class vector
|
|
||||||
{
|
|
||||||
using value_t = decltype(typename generate_tuple<Args...>::type{});
|
|
||||||
|
|
||||||
public:
|
|
||||||
vector(Args... args) : value_ { args... }
|
|
||||||
{
|
|
||||||
if (std::tuple_size<value_t>{} < 2) throw std::out_of_range("You try make no valid vector!");
|
|
||||||
}
|
|
||||||
vector& operator=(const vector& v)
|
|
||||||
{
|
|
||||||
if (this == &v) return *this;
|
|
||||||
value_ = v.value_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
value_t get_value() { return value_; };
|
|
||||||
|
|
||||||
auto x() const
|
|
||||||
{
|
|
||||||
return std::get<0>(value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto y() const
|
|
||||||
{
|
|
||||||
return std::get<1>(value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto z() const
|
|
||||||
{
|
|
||||||
if (std::tuple_size<value_t>{} < 3) throw std::out_of_range("You try get no valid vector data!");
|
|
||||||
return std::get<2>(value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto w() const
|
|
||||||
{
|
|
||||||
if (std::tuple_size<value_t>{} < 4) throw std::out_of_range("You try get no valid vector data!");
|
|
||||||
return std::get<3>(value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto length()
|
|
||||||
{
|
|
||||||
return std::sqrt(length_idx(std::make_index_sequence<std::tuple_size<value_t>::value>{}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
dest.x = a.x + ((b.x - a.x) * t);
|
|
||||||
dest.y = a.y + ((b.y - a.y) * t);
|
|
||||||
*/
|
|
||||||
value_t lerp(vector<Args...>& v, float t)
|
|
||||||
{
|
|
||||||
return lerp_idx(v.get_value(), t, std::make_index_sequence<std::tuple_size<value_t>::value>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template<typename std::size_t... idx>
|
|
||||||
auto length_idx(std::index_sequence<idx...>)
|
|
||||||
{
|
|
||||||
return ((std::get<idx>(value_) * std::get<idx>(value_)) + ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename std::size_t... idx>
|
|
||||||
auto lerp_idx(const value_t& v, float t, std::index_sequence<idx...>)
|
|
||||||
{
|
|
||||||
return std::make_tuple((std::get<idx>(value_) + (std::get<idx>(v) - std::get<idx>(value_)) * t)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
value_t value_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "hack/concepts/concepts.hpp"
|
|
||||||
|
|
||||||
namespace hack::memory
|
|
||||||
{
|
|
||||||
// обсуждение тут: https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(Args &&...args)
|
|
||||||
{
|
|
||||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(std::size_t n)
|
|
||||||
{
|
|
||||||
using RT = std::remove_extent<T>::type;
|
|
||||||
return std::unique_ptr<T>(new RT[n]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
114
src/hack/patterns/ring_buffer.hpp
Normal file
114
src/hack/patterns/ring_buffer.hpp
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace hack::patterns
|
||||||
|
{
|
||||||
|
template<typename T, std::size_t BUFFER_SIZE>
|
||||||
|
class ring_buffer
|
||||||
|
{
|
||||||
|
using MUTEX = std::lock_guard<std::recursive_mutex>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ring_buffer() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void put(T item) noexcept
|
||||||
|
{
|
||||||
|
MUTEX lock(m_mutex);
|
||||||
|
m_data[m_head] = item;
|
||||||
|
head_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// указываем размер, который хотим положить
|
||||||
|
// т.к. может нужно положить только часть из переданного массива
|
||||||
|
void put(const std::vector<T>& source, std::size_t size)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
m_data[m_head] = source[i];
|
||||||
|
head_refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// если знаем, что нужно класть весь массив
|
||||||
|
void put(const std::vector<T>& source)
|
||||||
|
{
|
||||||
|
MUTEX lock(m_mutex);
|
||||||
|
for (std::size_t i = 0; i < source.size(); ++i)
|
||||||
|
{
|
||||||
|
m_data[m_head] = source[i];
|
||||||
|
head_refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<T> get() noexcept
|
||||||
|
{
|
||||||
|
MUTEX lock(m_mutex);
|
||||||
|
|
||||||
|
if(empty()) return std::nullopt;
|
||||||
|
|
||||||
|
auto val = m_data[m_tail];
|
||||||
|
m_tail = (m_tail + 1) % BUFFER_SIZE;
|
||||||
|
m_full = false;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() noexcept
|
||||||
|
{
|
||||||
|
MUTEX lock(m_mutex);
|
||||||
|
return (!m_full && (m_head == m_tail));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() noexcept
|
||||||
|
{
|
||||||
|
MUTEX lock(m_mutex);
|
||||||
|
|
||||||
|
std::size_t size;
|
||||||
|
if(!m_full)
|
||||||
|
size = (m_head >= m_tail) ? m_head - m_tail : BUFFER_SIZE - (m_tail - m_head);
|
||||||
|
else
|
||||||
|
size = BUFFER_SIZE;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() noexcept
|
||||||
|
{
|
||||||
|
MUTEX lock(m_mutex);
|
||||||
|
m_head = m_tail;
|
||||||
|
m_full = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool full() const noexcept
|
||||||
|
{
|
||||||
|
return m_full;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t capacity() const noexcept
|
||||||
|
{
|
||||||
|
return BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void head_refresh()
|
||||||
|
{
|
||||||
|
if (m_full) m_tail = (m_tail + 1) % BUFFER_SIZE;
|
||||||
|
m_head = (m_head + 1) % BUFFER_SIZE;
|
||||||
|
m_full = m_head == m_tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t m_head{ 0 };
|
||||||
|
bool m_full{ false };
|
||||||
|
std::size_t m_tail{ 0 };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::recursive_mutex m_mutex;
|
||||||
|
std::array<T, BUFFER_SIZE> m_data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <uuid/uuid.h>
|
|
||||||
#include <regex>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace hack::security
|
|
||||||
{
|
|
||||||
inline bool is_link(const std::string& s)
|
|
||||||
{
|
|
||||||
static const std::regex e("^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$", std::regex_constants::icase);
|
|
||||||
return std::regex_match (s, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <variant>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace hack::security
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
struct is_string : public std::disjunction<std::is_same<char*,
|
|
||||||
typename std::decay_t<T>>,
|
|
||||||
std::is_same<const char*,
|
|
||||||
typename std::decay_t<T>>,
|
|
||||||
std::is_same<std::string,
|
|
||||||
typename std::decay_t<T>>> {};
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <uuid/uuid.h>
|
|
||||||
#include <regex>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace hack::security
|
|
||||||
{
|
|
||||||
inline std::string generate_uuid()
|
|
||||||
{
|
|
||||||
std::string uuid;
|
|
||||||
uuid_t uuid_obj;
|
|
||||||
uuid_generate_time_safe(uuid_obj);
|
|
||||||
char uuid_ch[UUID_STR_LEN];
|
|
||||||
uuid_unparse_lower(uuid_obj, uuid_ch);
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << uuid_ch;
|
|
||||||
ss >> uuid;
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool validate_uuid(const std::string& s)
|
|
||||||
{
|
|
||||||
static const std::regex e("^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$", std::regex_constants::icase);
|
|
||||||
return std::regex_match(s, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <regex>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace hack::security
|
|
||||||
{
|
|
||||||
inline bool validate_email(std::string& email)
|
|
||||||
{
|
|
||||||
const std::regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
|
|
||||||
return std::regex_match(email, pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace hack::string
|
|
||||||
{
|
|
||||||
using v_str = std::vector<std::string>;
|
|
||||||
using v_int_str = std::vector<int>;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
v_str split_str(const std::string& str, T t)
|
|
||||||
{
|
|
||||||
v_str v;
|
|
||||||
|
|
||||||
std::string::size_type begin = 0;
|
|
||||||
std::string::size_type end = str.find_first_of(t);
|
|
||||||
|
|
||||||
while(end != std::string::npos)
|
|
||||||
{
|
|
||||||
v.emplace_back(str.substr(begin, end - begin));
|
|
||||||
begin = ++end;
|
|
||||||
end = str.find_first_of(t, begin);
|
|
||||||
}
|
|
||||||
v.emplace_back(str.substr(begin));
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
v_int_str split_stoi(const std::string& str, T t)
|
|
||||||
{
|
|
||||||
v_int_str v;
|
|
||||||
|
|
||||||
std::string::size_type begin = 0;
|
|
||||||
std::string::size_type end = str.find_first_of(t);
|
|
||||||
|
|
||||||
while(end != std::string::npos)
|
|
||||||
{
|
|
||||||
v.emplace_back(std::stoi(str.substr(begin, end - begin)));
|
|
||||||
begin = ++end;
|
|
||||||
end = str.find_first_of(t, begin);
|
|
||||||
}
|
|
||||||
v.emplace_back(std::stoi(str.substr(begin)));
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace hack::string
|
|
||||||
{
|
|
||||||
template <typename... Strings>
|
|
||||||
class string_concat_helper;
|
|
||||||
|
|
||||||
template <typename String, typename... Strings>
|
|
||||||
class string_concat_helper<String, Strings...>
|
|
||||||
{
|
|
||||||
using string_part = string_concat_helper<Strings...>;
|
|
||||||
using string_long = string_concat_helper<std::string, String, Strings...>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const String& data;
|
|
||||||
string_part tail;
|
|
||||||
|
|
||||||
public:
|
|
||||||
string_concat_helper(const String& data_, string_part tail_) : data { data_ } , tail { tail_ } {}
|
|
||||||
|
|
||||||
int size() const
|
|
||||||
{
|
|
||||||
return data.size() + tail.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename It>
|
|
||||||
void save(It end) const
|
|
||||||
{
|
|
||||||
const auto begin = end - data.size();
|
|
||||||
std::copy(data.cbegin(), data.cend(), begin);
|
|
||||||
tail.save(begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::string() const
|
|
||||||
{
|
|
||||||
std::string result(size(), '\0');
|
|
||||||
save(result.end());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_long operator+(const std::string& other) const
|
|
||||||
{
|
|
||||||
return string_long(other, *this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class string_concat_helper<>
|
|
||||||
{
|
|
||||||
using string_part = string_concat_helper<std::string>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
int size() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename It>
|
|
||||||
void save(It) const { }
|
|
||||||
|
|
||||||
string_part operator+(const std::string& other) const
|
|
||||||
{
|
|
||||||
return string_part(other, *this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Stream, typename... Strings>
|
|
||||||
Stream& operator<<(Stream& stream, string_concat_helper<Strings...> strings)
|
|
||||||
{
|
|
||||||
return stream << static_cast<std::string>(strings);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline string_concat_helper<> str_concat;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <locale>
|
|
||||||
#include <codecvt>
|
|
||||||
|
|
||||||
namespace hack::string
|
|
||||||
{
|
|
||||||
// подсчет кол-ва символов
|
|
||||||
// В шестнадцатеричной системе счисления, 0xC0 представляет собой число 192. В бинарной системе это 11000000.
|
|
||||||
// Это число используется как маска для проверки байта в UTF-8 последовательности. И проверка в коде использует битовую операцию "И" (&) с маской 0xC0, чтобы проверить, является ли текущий
|
|
||||||
// байт началом UTF-8 последовательности. В UTF-8 первый байт символа, который не является частью
|
|
||||||
// многобайтовой последовательности, должен начинаться с битов 0 или 110 (в шестнадцатеричной системе это 0x00 или 0xC0).
|
|
||||||
// Проверка (c & 0xC0) != 0x80 используется для определения, является ли текущий байт продолжением UTF-8 многобайтовой последовательности.
|
|
||||||
// Валидные байты продолжения в UTF-8 должны начинаться с бита 10 (в бинарной системе это 0x80 или 10000000).
|
|
||||||
inline std::size_t utf8_len(const std::string& s)
|
|
||||||
{
|
|
||||||
std::size_t length = 0;
|
|
||||||
std::size_t i = 0;
|
|
||||||
|
|
||||||
while (i < s.size())
|
|
||||||
{
|
|
||||||
auto c = s[i];
|
|
||||||
if ((c & 0xC0) != 0x80)
|
|
||||||
++length;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// Данный интерфейс предназначен для более понятного и не меняющегося апи по преобразованию данных в json формат и обратно.
|
|
||||||
// Любой класс, который этого требует должен наследоваться от этого интерфейса чтобы не городить зоопарк разноименных для этого методов.
|
|
||||||
// Возможно в будущем я либо напишу рефлектор либо это будет вынесено в отдельную hack_cpp
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace hack::utils
|
|
||||||
{
|
|
||||||
template<typename JSON>
|
|
||||||
struct json_converter
|
|
||||||
{
|
|
||||||
json_converter() = default;
|
|
||||||
virtual ~json_converter() = default;
|
|
||||||
virtual JSON convert_to_json() = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace hack::utils
|
|
||||||
{
|
|
||||||
struct no_copy
|
|
||||||
{
|
|
||||||
no_copy() = default;
|
|
||||||
no_copy(const no_copy&&) = delete;
|
|
||||||
no_copy operator=(const no_copy&&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct no_move
|
|
||||||
{
|
|
||||||
no_move() = default;
|
|
||||||
no_move(no_move&&) = delete;
|
|
||||||
no_move operator=(no_move&&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct singleton : public no_move, no_copy
|
|
||||||
{
|
|
||||||
static T& instance()
|
|
||||||
{
|
|
||||||
static T t;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <array>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace hack::utils
|
|
||||||
{
|
|
||||||
// HERE
|
|
||||||
// это возможно нужно все перенести по отдельным файлам для понимания и расширения
|
|
||||||
template<typename Result, typename... Args>
|
|
||||||
auto func_memory(Result (*f)(Args...))
|
|
||||||
{
|
|
||||||
std::map<std::tuple<Args...>, Result> cache;
|
|
||||||
|
|
||||||
return [f, cache](Args... args) mutable -> Result
|
|
||||||
{
|
|
||||||
const auto key = std::make_tuple(args...);
|
|
||||||
const auto cached = cache.find(key);
|
|
||||||
|
|
||||||
if (cached == cache.end())
|
|
||||||
{
|
|
||||||
auto result = f(args...);
|
|
||||||
cache[key] = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return cached->second;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// обединяет фукнкции в один вызов при одинаковых переменных
|
|
||||||
// все переменный захватываются по значению
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
auto func_concat(T t, Args... args)
|
|
||||||
{
|
|
||||||
if constexpr (sizeof...(args) > 0)
|
|
||||||
{
|
|
||||||
return [=](auto... params)
|
|
||||||
{
|
|
||||||
return t(func_concat(args...)(params...));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return [=](auto... params)
|
|
||||||
{
|
|
||||||
return t(params...);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// вызов unix команд из с++ кода
|
|
||||||
inline std::string unix_cmd(const std::string& cmd)
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
std::array<char, 1024> buffer;
|
|
||||||
std::unique_ptr<FILE, int(*)(FILE*)> pipe(popen(cmd.c_str(), "r"), pclose);
|
|
||||||
|
|
||||||
if (!pipe) throw std::runtime_error("bash cmd failed");
|
|
||||||
|
|
||||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
|
|
||||||
{
|
|
||||||
result += buffer.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, T value = 0>
|
|
||||||
struct counter
|
|
||||||
{
|
|
||||||
inline static T id = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// this function can will use
|
|
||||||
// as switch wiht string
|
|
||||||
// switch(case_int("key"))
|
|
||||||
// case case_int("test"): hack::log()("wow!");
|
|
||||||
// case case_int("no_test"): hack::log()("wow!");
|
|
||||||
inline constexpr uint32_t case_int(const char* str, uint32_t hash = 2166136261UL)
|
|
||||||
{
|
|
||||||
return *str ? case_int(str + 1, (hash ^ *str) * 16777619ULL) : hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace hack::view::color
|
|
||||||
{
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& reset(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& bold(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[1m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& italic(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[3m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& black(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[30m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& red(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[31m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& green(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[32m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& yellow(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[33m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& blue(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[34m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& magenta(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[35m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& cyan(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[36m";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT, typename Traits>
|
|
||||||
std::basic_ostream<CharT, Traits>& white(std::basic_ostream<CharT, Traits> &os)
|
|
||||||
{
|
|
||||||
return os << "\033[37m";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +1,7 @@
|
|||||||
inc += include_directories('.')
|
inc += include_directories('.')
|
||||||
|
|
||||||
headers = [
|
headers = [
|
||||||
'hack/algorithms/sort.hpp',
|
'hack/patterns/ring_buffer.hpp',
|
||||||
|
|
||||||
'hack/concepts/concepts.hpp',
|
|
||||||
|
|
||||||
'hack/containers/containers.hpp',
|
|
||||||
'hack/containers/set.hpp',
|
|
||||||
'hack/containers/utils.hpp',
|
|
||||||
'hack/containers/vector.hpp',
|
|
||||||
|
|
||||||
'hack/exception/exception.hpp',
|
|
||||||
|
|
||||||
'hack/iterators/associative_ostream_iterator.hpp',
|
|
||||||
'hack/iterators/sequence_ostream_iterator.hpp',
|
|
||||||
|
|
||||||
'hack/logger/logger.hpp',
|
|
||||||
|
|
||||||
'hack/macros/macros.hpp',
|
|
||||||
|
|
||||||
'hack/math/matrix.hpp',
|
|
||||||
'hack/math/max.hpp',
|
|
||||||
'hack/math/vector.hpp',
|
|
||||||
|
|
||||||
'hack/memory/make_ptr.hpp',
|
|
||||||
|
|
||||||
'hack/security/is_link.hpp',
|
|
||||||
'hack/security/is_string.hpp',
|
|
||||||
'hack/security/uuid.hpp',
|
|
||||||
'hack/security/validate_email.hpp',
|
|
||||||
|
|
||||||
'hack/string/string.hpp',
|
|
||||||
'hack/string/string_concat_helper.hpp',
|
|
||||||
'hack/string/utf8_len.hpp',
|
|
||||||
|
|
||||||
'hack/utils/singleton.hpp',
|
|
||||||
'hack/utils/json_converter.hpp',
|
|
||||||
'hack/utils/utils.hpp',
|
|
||||||
|
|
||||||
'hack/view/color.hpp',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
sources = []
|
sources = []
|
||||||
|
|||||||
11
subprojects/catch2.wrap
Normal file
11
subprojects/catch2.wrap
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[wrap-file]
|
||||||
|
directory = Catch2-3.7.1
|
||||||
|
source_url = https://github.com/catchorg/Catch2/archive/v3.7.1.tar.gz
|
||||||
|
source_filename = Catch2-3.7.1.tar.gz
|
||||||
|
source_hash = c991b247a1a0d7bb9c39aa35faf0fe9e19764213f28ffba3109388e62ee0269c
|
||||||
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.7.1-1/Catch2-3.7.1.tar.gz
|
||||||
|
wrapdb_version = 3.7.1-1
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
catch2 = catch2_dep
|
||||||
|
catch2-with-main = catch2_with_main_dep
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[wrap-file]
|
|
||||||
directory = nlohmann_json-3.11.2
|
|
||||||
lead_directory_missing = true
|
|
||||||
source_url = https://github.com/nlohmann/json/releases/download/v3.11.2/include.zip
|
|
||||||
source_filename = nlohmann_json-3.11.2.zip
|
|
||||||
source_hash = e5c7a9f49a16814be27e4ed0ee900ecd0092bfb7dbfca65b5a421b774dccaaed
|
|
||||||
wrapdb_version = 3.11.2-1
|
|
||||||
|
|
||||||
[provide]
|
|
||||||
nlohmann_json = nlohmann_json_dep
|
|
||||||
20
tests/base_test_fib.cpp
Normal file
20
tests/base_test_fib.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
static int Factorial(int number)
|
||||||
|
{
|
||||||
|
// return number <= 1 ? number : Factorial(number - 1) * number; // fail
|
||||||
|
return number <= 1 ? 1 : Factorial(number - 1) * number; // pass
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[base_test_fib] Factorial of 0 is 1 (fail)", "[single-file]")
|
||||||
|
{
|
||||||
|
REQUIRE(Factorial(0) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[base_test_fib] Factorials of 1 and higher are computed (pass)", "[single-file]")
|
||||||
|
{
|
||||||
|
REQUIRE(Factorial(1) == 1);
|
||||||
|
REQUIRE(Factorial(2) == 2);
|
||||||
|
REQUIRE(Factorial(3) == 6);
|
||||||
|
REQUIRE(Factorial(10) == 3628800);
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#include <array>
|
|
||||||
|
|
||||||
#include "hack/exception/exception.hpp"
|
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
|
||||||
{
|
|
||||||
hack::exception ex;
|
|
||||||
ex.service("test service");
|
|
||||||
ex.log();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
12
tests/meson.build
Executable file → Normal file
12
tests/meson.build
Executable file → Normal file
@@ -1,7 +1,5 @@
|
|||||||
executable(
|
catch2_with_main_dep = dependency('catch2-with-main')
|
||||||
meson.project_name(),
|
dep = [hack_dep, catch2_with_main_dep]
|
||||||
'main.cpp',
|
|
||||||
dependencies : deps,
|
test('patterns', executable('patterns', ['patterns/ring_buffer.cpp'], dependencies : dep))
|
||||||
cpp_args: args,
|
|
||||||
include_directories : inc
|
|
||||||
)
|
|
||||||
|
|||||||
59
tests/patterns/ring_buffer.cpp
Normal file
59
tests/patterns/ring_buffer.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "catch2/catch_test_macros.hpp"
|
||||||
|
#include "hack/patterns/ring_buffer.hpp"
|
||||||
|
|
||||||
|
TEST_CASE("patterns")
|
||||||
|
{
|
||||||
|
SECTION("ring buffer")
|
||||||
|
{
|
||||||
|
// single value
|
||||||
|
hack::patterns::ring_buffer<int, 10> rb1;
|
||||||
|
REQUIRE(rb1.empty() == true);
|
||||||
|
|
||||||
|
for (int i = 1; i < 13; ++i) rb1.put(i);
|
||||||
|
REQUIRE(rb1.empty() == false);
|
||||||
|
REQUIRE(rb1.size() == 10);
|
||||||
|
|
||||||
|
while(!rb1.empty()) REQUIRE(rb1.get().has_value() == true);
|
||||||
|
REQUIRE(rb1.empty() == true);
|
||||||
|
REQUIRE(rb1.size() == 0);
|
||||||
|
|
||||||
|
rb1.put(123);
|
||||||
|
rb1.put(23);
|
||||||
|
rb1.put(3);
|
||||||
|
REQUIRE(rb1.get().value() == 123);
|
||||||
|
REQUIRE(rb1.empty() == false);
|
||||||
|
REQUIRE(rb1.size() == 2);
|
||||||
|
|
||||||
|
REQUIRE(rb1.get().value() == 23);
|
||||||
|
REQUIRE(rb1.empty() == false);
|
||||||
|
REQUIRE(rb1.size() == 1);
|
||||||
|
|
||||||
|
rb1.reset();
|
||||||
|
REQUIRE(rb1.empty() == true);
|
||||||
|
REQUIRE(rb1.size() == 0);
|
||||||
|
REQUIRE(rb1.get().has_value() == false);
|
||||||
|
|
||||||
|
// vector value
|
||||||
|
std::vector<int> v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||||
|
hack::patterns::ring_buffer<int, 10> rb2;
|
||||||
|
REQUIRE(rb2.empty() == true);
|
||||||
|
|
||||||
|
rb2.put(v);
|
||||||
|
REQUIRE(rb2.get().value() == 1);
|
||||||
|
REQUIRE(rb2.get().value() == 2);
|
||||||
|
|
||||||
|
v.emplace_back(17);
|
||||||
|
rb2.put(v);
|
||||||
|
REQUIRE(rb2.get().value() == 2);
|
||||||
|
REQUIRE(rb2.get().value() == 3);
|
||||||
|
REQUIRE(rb2.get().value() == 4);
|
||||||
|
REQUIRE(rb2.get().value() == 5);
|
||||||
|
REQUIRE(rb2.get().value() == 6);
|
||||||
|
REQUIRE(rb2.get().value() == 7);
|
||||||
|
REQUIRE(rb2.get().value() == 8);
|
||||||
|
REQUIRE(rb2.get().value() == 9);
|
||||||
|
REQUIRE(rb2.get().value() == 10);
|
||||||
|
REQUIRE(rb2.get().value() == 17);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user