add new concepts and error and warn logger
This commit is contained in:
@@ -14,10 +14,10 @@
|
|||||||
+ patterns - набор различных паттернов проектирования
|
+ patterns - набор различных паттернов проектирования
|
||||||
+ security - что-то типа защиты от чего-то
|
+ security - что-то типа защиты от чего-то
|
||||||
+ utils - вспомогательные решения для библиотеки
|
+ utils - вспомогательные решения для библиотеки
|
||||||
|
+ logger - реализация логирования
|
||||||
|
|
||||||
- logger - реализация логирования
|
|
||||||
- exception - универсальный класс обработки ошибок
|
|
||||||
- iterators - набор разнообразных реализаций итераторов
|
- iterators - набор разнообразных реализаций итераторов
|
||||||
|
- exception - универсальный класс обработки ошибок
|
||||||
|
|
||||||
+ - задукоментированно с коментариями и примерами
|
+ - задукоментированно с коментариями и примерами
|
||||||
- - доки в раборте, нужно делать и разбирать
|
- - доки в раборте, нужно делать и разбирать
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <set>
|
||||||
#include "hack/concepts/concepts.hpp"
|
#include "hack/concepts/concepts.hpp"
|
||||||
#include "hack/logger/logger.hpp"
|
#include "hack/logger/logger.hpp"
|
||||||
|
|
||||||
@@ -108,12 +109,6 @@ void example_is_any_container(const T& container)
|
|||||||
hack::log()("Any container with ", container.size(), " elements");
|
hack::log()("Any container with ", container.size(), " elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<hack::concepts::is_iterable T>
|
|
||||||
void example_is_iterable(const T& iterable)
|
|
||||||
{
|
|
||||||
hack::log()("Iterable object");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<hack::concepts::is_sized T>
|
template<hack::concepts::is_sized T>
|
||||||
void example_is_sized(const T& sized)
|
void example_is_sized(const T& sized)
|
||||||
{
|
{
|
||||||
@@ -132,12 +127,6 @@ void check_support(const T& value)
|
|||||||
hack::log()("Type is supported");
|
hack::log()("Type is supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<hack::concepts::is_contiguous_container T>
|
|
||||||
void example_is_contiguous_container(const T& container)
|
|
||||||
{
|
|
||||||
hack::log()("Contiguous memory container");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Value>
|
template<typename Container, typename Value>
|
||||||
requires hack::concepts::can_push_front<Container, Value>
|
requires hack::concepts::can_push_front<Container, Value>
|
||||||
void example_can_push_front(Container& container, Value&& value)
|
void example_can_push_front(Container& container, Value&& value)
|
||||||
@@ -200,11 +189,9 @@ auto main(int argc, char *argv[]) -> int
|
|||||||
example_is_fixed_array(fixed_array);
|
example_is_fixed_array(fixed_array);
|
||||||
example_is_std_array(std_array);
|
example_is_std_array(std_array);
|
||||||
example_is_any_container(vec);
|
example_is_any_container(vec);
|
||||||
example_is_iterable(vec);
|
|
||||||
example_is_sized(vec);
|
example_is_sized(vec);
|
||||||
check_support(a);
|
check_support(a);
|
||||||
check_support(custom);
|
check_support(custom);
|
||||||
example_is_contiguous_container(vec);
|
|
||||||
example_can_push_front(list, 0);
|
example_can_push_front(list, 0);
|
||||||
example_can_push_back(vec, 99);
|
example_can_push_back(vec, 99);
|
||||||
example_can_find(set, 3);
|
example_can_find(set, 3);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "hack/logger/logger.hpp"
|
#include "hack/logger/logger.hpp"
|
||||||
|
#include "hack/patterns/ring_buffer.hpp"
|
||||||
|
|
||||||
auto main(int argc, char *argv[]) -> int
|
auto main(int argc, char *argv[]) -> int
|
||||||
{
|
{
|
||||||
@@ -24,6 +25,9 @@ auto main(int argc, char *argv[]) -> int
|
|||||||
sti.push(3);
|
sti.push(3);
|
||||||
std::set<int> si = { 1, 2, 3 };
|
std::set<int> si = { 1, 2, 3 };
|
||||||
std::unordered_set<int> usi = { 1, 1, 1 };
|
std::unordered_set<int> usi = { 1, 1, 1 };
|
||||||
|
hack::patterns::ring_buffer<int> rb;
|
||||||
|
rb.create(10);
|
||||||
|
for (int i = 0; i < 10; ++i) rb.put(i);
|
||||||
|
|
||||||
hack::log().set_devider(", ");
|
hack::log().set_devider(", ");
|
||||||
hack::log().no_func();
|
hack::log().no_func();
|
||||||
@@ -53,7 +57,13 @@ auto main(int argc, char *argv[]) -> int
|
|||||||
hack::log().reset();
|
hack::log().reset();
|
||||||
hack::log().set_devider(", ");
|
hack::log().set_devider(", ");
|
||||||
hack::log()(sti, 123, true);
|
hack::log()(sti, 123, true);
|
||||||
|
hack::log().reset();
|
||||||
|
hack::log()("log", 123, sti, false, 1.8f, vs);
|
||||||
|
|
||||||
|
hack::warn()("warn");
|
||||||
|
hack::error()("error");
|
||||||
|
|
||||||
|
hack::log()(rb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ executable(
|
|||||||
# 'examples/math/main.cpp',
|
# 'examples/math/main.cpp',
|
||||||
# 'examples/range/main.cpp',
|
# 'examples/range/main.cpp',
|
||||||
# 'examples/patterns/main.cpp',
|
# 'examples/patterns/main.cpp',
|
||||||
'examples/logger/main.cpp',
|
'examples/logger/main.cpp',
|
||||||
dependencies : deps,
|
dependencies : deps,
|
||||||
cpp_args: args,
|
cpp_args: args,
|
||||||
include_directories : inc
|
include_directories : inc
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ namespace hack::concepts
|
|||||||
std::same_as<T, std::deque<typename T::value_type, typename T::allocator_type>> ||
|
std::same_as<T, std::deque<typename T::value_type, typename T::allocator_type>> ||
|
||||||
std::same_as<T, std::forward_list<typename T::value_type, typename T::allocator_type>>);
|
std::same_as<T, std::forward_list<typename T::value_type, typename T::allocator_type>>);
|
||||||
|
|
||||||
|
|
||||||
// Адаптеры контейнеров
|
// Адаптеры контейнеров
|
||||||
// @brief Проверяет, является ли тип адаптером контейнера
|
// @brief Проверяет, является ли тип адаптером контейнера
|
||||||
// @details Обнаруживает типы-обертки над другими контейнерами:
|
// @details Обнаруживает типы-обертки над другими контейнерами:
|
||||||
@@ -156,88 +157,7 @@ namespace hack::concepts
|
|||||||
arr[0];
|
arr[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Универсальные концепты для категоризации
|
// @brief Проверяет, является ли тип bool
|
||||||
// @brief Проверяет, является ли тип любым контейнером
|
|
||||||
// @details Всеобъемлющий концепт для обнаружения контейнеров любого типа:
|
|
||||||
// - Последовательные контейнеры
|
|
||||||
// - Ассоциативные контейнеры
|
|
||||||
// - Адаптеры контейнеров
|
|
||||||
// - Массивы (C-style и std::array)
|
|
||||||
// Основной концепт для обобщенных алгоритмов работы с контейнерами
|
|
||||||
template<typename T>
|
|
||||||
concept is_any_container = is_sequence_container<T> ||
|
|
||||||
is_associative_container<T> ||
|
|
||||||
is_unordered_associative_container<T> ||
|
|
||||||
is_container_adapter<T> ||
|
|
||||||
is_fixed_array<T> ||
|
|
||||||
is_std_array<T>;
|
|
||||||
|
|
||||||
// @brief Проверяет, является ли тип итерируемым
|
|
||||||
// @details Обнаруживает любые типы, по которым можно итерироваться:
|
|
||||||
// - Контейнеры STL с begin()/end()
|
|
||||||
// - Массивы (работают с std::begin/std::end)
|
|
||||||
// - Кортежи (хотя итерирование по ним особое)
|
|
||||||
// Самый общий концепт для range-based for и алгоритмов
|
|
||||||
template<typename T>
|
|
||||||
concept is_iterable = has_iterator<T> || is_fixed_array<T> || is_tuple_like<T>;
|
|
||||||
|
|
||||||
// @brief Проверяет, имеет ли тип размер
|
|
||||||
// @details Обнаруживает типы, у которых можно узнать размер:
|
|
||||||
// - Контейнеры с методом size()
|
|
||||||
// - Массивы с известным размером
|
|
||||||
// - Кортежи с известным количеством элементов
|
|
||||||
// Важно для алгоритмов, требующих предварительного знания размера
|
|
||||||
template<typename T>
|
|
||||||
concept is_sized = has_size<T> || is_fixed_array<T> || is_tuple_like<T>;
|
|
||||||
|
|
||||||
// Концепт для "неподдерживаемых" типов
|
|
||||||
// @brief Проверяет, является ли тип неподдерживаемым
|
|
||||||
// @details Обнаруживает типы, которые не входят в известные категории:
|
|
||||||
// - Пользовательские типы без ожидаемого интерфейса
|
|
||||||
// - Специфичные типы из сторонних библиотек
|
|
||||||
// - Типы, для которых нет специализированной обработки
|
|
||||||
// Используется для static_assert и генерации понятных ошибок
|
|
||||||
template<typename T>
|
|
||||||
concept not_supported = !(std::integral<T> ||
|
|
||||||
std::floating_point<T> ||
|
|
||||||
is_string<T> ||
|
|
||||||
is_any_container<T> ||
|
|
||||||
is_tuple_like<T> ||
|
|
||||||
std::is_pointer_v<T>);
|
|
||||||
|
|
||||||
// @brief Проверяет, является ли тип контейнером с непрерывной памятью
|
|
||||||
// @details Обнаруживает контейнеры, элементы которых хранятся в непрерывной памяти:
|
|
||||||
// - std::vector - динамический массив
|
|
||||||
// - C-style массивы
|
|
||||||
// - std::array - статический массив
|
|
||||||
// Критически важно для низкоуровневых операций и взаимодействия с C API
|
|
||||||
template<typename T>
|
|
||||||
concept is_contiguous_container = std::same_as<T, std::vector<typename T::value_type, typename T::allocator_type>> ||
|
|
||||||
is_fixed_array<T> ||
|
|
||||||
is_std_array<T>;
|
|
||||||
|
|
||||||
// @brief Проверяет, поддерживает ли контейнер добавление в начало
|
|
||||||
// @details Обнаруживает контейнеры с push_front():
|
|
||||||
// - deque, list, forward_list
|
|
||||||
// Полезно для алгоритмов, работающих с очередями и стеками
|
|
||||||
template<typename Container, typename Value>
|
|
||||||
concept can_push_front = requires(Container c, Value&& v) { c.push_front(std::forward<Value>(v)); };
|
|
||||||
|
|
||||||
// @brief Проверяет, поддерживает ли контейнер добавление в конец
|
|
||||||
// @details Обнаруживает контейнеры с push_back():
|
|
||||||
// - vector, deque, list
|
|
||||||
// Важно для алгоритмов, которые строят контейнеры последовательно
|
|
||||||
template<typename Container, typename Value>
|
|
||||||
concept can_push_back = requires(Container c, Value&& v) { c.push_back(std::forward<Value>(v)); };
|
|
||||||
|
|
||||||
// @brief Проверяет, поддерживает ли контейнер поиск по ключу
|
|
||||||
// @details Обнаруживает контейнеры с методом find():
|
|
||||||
// - map, set, unordered_map, unordered_set
|
|
||||||
// Ключевой концепт для алгоритмов поиска и проверки существования элементов
|
|
||||||
template<typename Container, typename Key>
|
|
||||||
concept can_find = requires(Container c, Key&& key) { c.find(std::forward<Key>(key)); };
|
|
||||||
|
|
||||||
// @brief Проверяет, является ли тип bool
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept is_bool = std::is_same_v<std::remove_cvref_t<T>, bool>;
|
concept is_bool = std::is_same_v<std::remove_cvref_t<T>, bool>;
|
||||||
|
|
||||||
@@ -278,46 +198,76 @@ namespace hack::concepts
|
|||||||
{ s.empty() } -> std::same_as<bool>;
|
{ s.empty() } -> std::same_as<bool>;
|
||||||
{ s.size() } -> std::convertible_to<std::size_t>;
|
{ s.size() } -> std::convertible_to<std::size_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Универсальные концепты для категоризации
|
||||||
|
// @brief Проверяет, является ли тип любым контейнером
|
||||||
|
// @details Всеобъемлющий концепт для обнаружения контейнеров любого типа:
|
||||||
|
// - Последовательные контейнеры
|
||||||
|
// - Ассоциативные контейнеры
|
||||||
|
// - Адаптеры контейнеров
|
||||||
|
// - Массивы (C-style и std::array)
|
||||||
|
// Основной концепт для обобщенных алгоритмов работы с контейнерами
|
||||||
|
template<typename T>
|
||||||
|
concept is_any_container = is_sequence_container<T> ||
|
||||||
|
is_associative_container<T> ||
|
||||||
|
is_unordered_associative_container<T> ||
|
||||||
|
is_container_adapter<T> ||
|
||||||
|
is_fixed_array<T> ||
|
||||||
|
is_set_like<T> ||
|
||||||
|
is_tuple_like<T> ||
|
||||||
|
is_stack<T> ||
|
||||||
|
is_std_array<T>;
|
||||||
|
|
||||||
|
// @brief Проверяет, имеет ли тип размер
|
||||||
|
// @details Обнаруживает типы, у которых можно узнать размер:
|
||||||
|
// - Контейнеры с методом size()
|
||||||
|
// - Массивы с известным размером
|
||||||
|
// - Кортежи с известным количеством элементов
|
||||||
|
// Важно для алгоритмов, требующих предварительного знания размера
|
||||||
|
template<typename T>
|
||||||
|
concept is_sized = has_size<T> || is_fixed_array<T> || is_tuple_like<T>;
|
||||||
|
|
||||||
|
// Концепт для "неподдерживаемых" типов
|
||||||
|
// @brief Проверяет, является ли тип неподдерживаемым
|
||||||
|
// @details Обнаруживает типы, которые не входят в известные категории:
|
||||||
|
// - Пользовательские типы без ожидаемого интерфейса
|
||||||
|
// - Специфичные типы из сторонних библиотек
|
||||||
|
// - Типы, для которых нет специализированной обработки
|
||||||
|
// Используется для static_assert и генерации понятных ошибок
|
||||||
|
template<typename T>
|
||||||
|
concept not_supported = !(is_number<T> ||
|
||||||
|
is_string<T> ||
|
||||||
|
is_bool<T> ||
|
||||||
|
is_any_container<T> ||
|
||||||
|
std::is_pointer_v<T>);
|
||||||
|
|
||||||
|
// @brief Проверяет, поддерживает ли контейнер добавление в начало
|
||||||
|
// @details Обнаруживает контейнеры с push_front():
|
||||||
|
// - deque, list, forward_list
|
||||||
|
// Полезно для алгоритмов, работающих с очередями и стеками
|
||||||
|
template<typename Container, typename Value>
|
||||||
|
concept can_push_front = requires(Container c, Value&& v) { c.push_front(std::forward<Value>(v)); };
|
||||||
|
|
||||||
|
// @brief Проверяет, поддерживает ли контейнер добавление в конец
|
||||||
|
// @details Обнаруживает контейнеры с push_back():
|
||||||
|
// - vector, deque, list
|
||||||
|
// Важно для алгоритмов, которые строят контейнеры последовательно
|
||||||
|
template<typename Container, typename Value>
|
||||||
|
concept can_push_back = requires(Container c, Value&& v) { c.push_back(std::forward<Value>(v)); };
|
||||||
|
|
||||||
|
// @brief Проверяет, поддерживает ли контейнер поиск по ключу
|
||||||
|
// @details Обнаруживает контейнеры с методом find():
|
||||||
|
// - map, set, unordered_map, unordered_set
|
||||||
|
// Ключевой концепт для алгоритмов поиска и проверки существования элементов
|
||||||
|
template<typename Container, typename Key>
|
||||||
|
concept can_find = requires(Container c, Key&& key) { c.find(std::forward<Key>(key)); };
|
||||||
|
|
||||||
|
// для логирования собственных структур
|
||||||
|
// мало где используется, только в логере для проверки и выдачи сообщения
|
||||||
|
template<typename T>
|
||||||
|
concept has_get_logger_data = requires(T t) {
|
||||||
|
{ t.get_logger_data() };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,209 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <experimental/source_location>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "hack/utils/color.hpp"
|
|
||||||
#include "hack/concepts/concepts.hpp"
|
|
||||||
#include "hack/iterators/sequence_ostream_iterator.hpp"
|
|
||||||
#include "hack/iterators/associative_ostream_iterator.hpp"
|
|
||||||
|
|
||||||
#include "hack/patterns/ring_buffer.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...);
|
|
||||||
}
|
|
||||||
|
|
||||||
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() << ":" << utils::color::reset
|
|
||||||
<< utils::color::italic << utils::color::yellow << u.function_name() << "()" << utils::color::reset
|
|
||||||
<< utils::color::bold << utils::color::blue << "[" << u.line() << "]" << utils::color::reset << ": ";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print() { std::cout << std::endl; }
|
|
||||||
|
|
||||||
static std::ostream& make_type_view(std::ostream &os)
|
|
||||||
{
|
|
||||||
os << utils::color::bold << utils::color::green << "[ok]" << utils::color::reset << utils::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<concepts::not_defined T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << data << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static void print_t(const hack::patterns::ring_buffer<T>& rb)
|
|
||||||
{
|
|
||||||
print_t(rb.get_src());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 << utils::color::bold << utils::color::yellow << "[WARN]" << utils::color::reset << utils::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 << utils::color::bold << utils::color::red << "[ERROR]" << utils::color::reset << utils::color::red;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -8,11 +8,6 @@
|
|||||||
#include "hack/concepts/concepts.hpp"
|
#include "hack/concepts/concepts.hpp"
|
||||||
#include "hack/iterators/sequence_ostream_iterator.hpp"
|
#include "hack/iterators/sequence_ostream_iterator.hpp"
|
||||||
#include "hack/iterators/associative_ostream_iterator.hpp"
|
#include "hack/iterators/associative_ostream_iterator.hpp"
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
#include <execinfo.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
// HERE
|
// HERE
|
||||||
// и нужно сделать реализацию где выводлится все в одной линии но при помощи цикла
|
// и нужно сделать реализацию где выводлится все в одной линии но при помощи цикла
|
||||||
@@ -38,6 +33,11 @@ namespace hack
|
|||||||
m_bool_as_number = m_base_config.m_bool_as_number;
|
m_bool_as_number = m_base_config.m_bool_as_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void on_log() { m_type = type::LOG; }
|
||||||
|
void on_warn() { m_type = type::WARN; }
|
||||||
|
void on_error() { m_type = type::ERROR; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void operator() (const Args&... args)
|
void operator() (const Args&... args)
|
||||||
@@ -58,17 +58,35 @@ namespace hack
|
|||||||
std::string m_devider = " "; // разделитель по умолчанию
|
std::string m_devider = " "; // разделитель по умолчанию
|
||||||
} m_base_config;
|
} m_base_config;
|
||||||
|
|
||||||
|
enum class type
|
||||||
|
{
|
||||||
|
LOG,
|
||||||
|
WARN,
|
||||||
|
ERROR
|
||||||
|
} m_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << utils::color::bold << utils::color::green << "[ok] " << utils::color::reset;
|
switch(m_type)
|
||||||
|
{
|
||||||
|
case type::LOG:
|
||||||
|
ss << utils::color::bold << utils::color::green << "[ok] " << utils::color::reset;
|
||||||
|
break;
|
||||||
|
case type::WARN:
|
||||||
|
ss << utils::color::bold << utils::color::magenta << "[WARN]" << utils::color::reset;
|
||||||
|
break;
|
||||||
|
case type::ERROR:
|
||||||
|
ss << utils::color::bold << utils::color::red << "[ERROR]" << utils::color::reset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_no_file)
|
if (!m_no_file)
|
||||||
ss << utils::color::green << m_location.file_name() << ":" << utils::color::reset;
|
ss << utils::color::green << m_location.file_name() << ":" << utils::color::reset;
|
||||||
|
|
||||||
if (!m_no_func)
|
if (!m_no_func)
|
||||||
ss << utils::color::italic << utils::color::yellow << m_location.function_name() << utils::color::reset;
|
ss << utils::color::italic << utils::color::yellow<< m_location.function_name() << utils::color::reset;
|
||||||
|
|
||||||
if (!m_no_row)
|
if (!m_no_row)
|
||||||
ss << utils::color::bold << utils::color::blue << "[" << m_location.line() << "] " << utils::color::reset;
|
ss << utils::color::bold << utils::color::blue << "[" << m_location.line() << "] " << utils::color::reset;
|
||||||
@@ -171,25 +189,35 @@ namespace hack
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Для stack - выводим содержимое (но stack нельзя итерировать!)
|
// Для stack - выводим содержимое (но stack нельзя итерировать!)
|
||||||
template<concepts::is_stack T>
|
template<concepts::is_stack T>
|
||||||
void print_t(const T& stack)
|
void print_t(const T& stack)
|
||||||
{
|
|
||||||
T temp = stack;
|
|
||||||
|
|
||||||
std::cout << "{ ";
|
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
while (!temp.empty())
|
|
||||||
{
|
{
|
||||||
if (!first)
|
T temp = stack;
|
||||||
std::cout << m_devider;
|
|
||||||
first = false;
|
std::cout << "{ ";
|
||||||
std::cout << temp.top();
|
|
||||||
temp.pop();
|
bool first = true;
|
||||||
|
while (!temp.empty())
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
std::cout << m_devider;
|
||||||
|
first = false;
|
||||||
|
std::cout << temp.top();
|
||||||
|
temp.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << " }" << (m_count != 0 ? m_devider : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// для пользовательских типов
|
||||||
|
// у них должен быть отпределен метод get_data()
|
||||||
|
// возвращающий один из обработанных типов
|
||||||
|
template<concepts::not_supported T>
|
||||||
|
void print_t(const T& rb)
|
||||||
|
{
|
||||||
|
static_assert(concepts::has_get_logger_data<T>, "Type must have get_logger_data() method that returns value_type");
|
||||||
|
print_t(rb.get_logger_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << " }" << (m_count != 0 ? m_devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::source_location m_location;
|
std::source_location m_location;
|
||||||
@@ -199,12 +227,30 @@ namespace hack
|
|||||||
bool m_no_file = m_base_config.m_no_file;
|
bool m_no_file = m_base_config.m_no_file;
|
||||||
bool m_no_row = m_base_config.m_no_row;
|
bool m_no_row = m_base_config.m_no_row;
|
||||||
bool m_bool_as_number = m_base_config.m_bool_as_number;
|
bool m_bool_as_number = m_base_config.m_bool_as_number;
|
||||||
|
|
||||||
|
friend class warn;
|
||||||
|
friend class error;
|
||||||
};
|
};
|
||||||
|
|
||||||
// основная функция вызова логера
|
// основная функция вызова логера
|
||||||
inline logger& log(std::source_location location = std::source_location::current())
|
inline logger& log(std::source_location location = std::source_location::current())
|
||||||
{
|
{
|
||||||
logger::instance().set_location(location);
|
logger::instance().set_location(location);
|
||||||
|
logger::instance().on_log();
|
||||||
|
return logger::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline logger& warn(std::source_location location = std::source_location::current())
|
||||||
|
{
|
||||||
|
logger::instance().set_location(location);
|
||||||
|
logger::instance().on_warn();
|
||||||
|
return logger::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline logger& error(std::source_location location = std::source_location::current())
|
||||||
|
{
|
||||||
|
logger::instance().set_location(location);
|
||||||
|
logger::instance().on_error();
|
||||||
return logger::instance();
|
return logger::instance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
namespace hack::patterns
|
namespace hack::patterns
|
||||||
{
|
{
|
||||||
// Колцевой буфер.
|
// Колцевой буфер.
|
||||||
// HERE
|
|
||||||
// сделать опсание каждой функции
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class ring_buffer
|
class ring_buffer
|
||||||
{
|
{
|
||||||
@@ -91,7 +89,7 @@ namespace hack::patterns
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<T>& get_src() const noexcept
|
const std::vector<T>& get_logger_data() const noexcept
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace hack::utils::color
|
|||||||
return os << "\033[0m";
|
return os << "\033[0m";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// вид
|
||||||
template<typename CharT, typename Traits>
|
template<typename CharT, typename Traits>
|
||||||
std::basic_ostream<CharT, Traits>& bold(std::basic_ostream<CharT, Traits> &os)
|
std::basic_ostream<CharT, Traits>& bold(std::basic_ostream<CharT, Traits> &os)
|
||||||
{
|
{
|
||||||
@@ -28,6 +29,13 @@ namespace hack::utils::color
|
|||||||
return os << "\033[30m";
|
return os << "\033[30m";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& underline(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[4m";
|
||||||
|
}
|
||||||
|
|
||||||
|
// цвета
|
||||||
template<typename CharT, typename Traits>
|
template<typename CharT, typename Traits>
|
||||||
std::basic_ostream<CharT, Traits>& red(std::basic_ostream<CharT, Traits> &os)
|
std::basic_ostream<CharT, Traits>& red(std::basic_ostream<CharT, Traits> &os)
|
||||||
{
|
{
|
||||||
@@ -69,4 +77,46 @@ namespace hack::utils::color
|
|||||||
{
|
{
|
||||||
return os << "\033[37m";
|
return os << "\033[37m";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& gray(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[90m"; // Яркий черный = серый
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& dark_gray(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[30m"; // Темно-серый
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& brown(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[33m"; // Коричневый (желтый)
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& orange(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[38;5;208m"; // Оранжевый (256 цветов)
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& light_blue(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[94m"; // Голубой (яркий синий)
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& violet(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[95m"; // Фиолетовый (яркий пурпурный)
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CharT, typename Traits>
|
||||||
|
std::basic_ostream<CharT, Traits>& purple(std::basic_ostream<CharT, Traits> &os)
|
||||||
|
{
|
||||||
|
return os << "\033[35m"; // Пурпурный
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user