Pasha Bibko Util Library
Loading...
Searching...
No Matches
Log.h
1#pragma once
2
3
4#include <classes/Colour.h>
5#include <sections/Misc.h>
6
7#include <type_traits>
8#include <iomanip>
9#include <sstream>
10#include <ostream>
11#include <ranges>
12
20namespace PashaBibko::Util
21{
22 /* Excludes the internal namespace from the docs */
23 #ifndef DOXYGEN_HIDE
24
25 namespace Internal
26 {
27 /* Functions defined in Log.cpp to allow writing to their local variables */
28
29 void WriteToConsole(const char* message);
30 void WriteToLog(const char* message);
31
32 /* Checks if a type can be outputted to std::ostream */
33 template<typename Ty> concept StandardLogable = requires(std::ostream & os, Ty arg)
34 {
35 { os << arg } -> std::same_as<std::ostream&>;
36 };
37
38 /* Checks if the type has a LogStr function */
39 template<typename Ty> concept TypeHasLogFunction = requires(Ty obj)
40 {
41 { obj.LogStr() } -> std::same_as<std::string>;
42 };
43
44 /* Helper type to display type name in static_assert() */
45 template<typename Ty> struct DependentFalse : std::false_type {};
46
47 /* Assumes all types passed are valid as it is an internal function */
48 template<typename Ty>
49 std::string ProcessArg(Ty&& arg)
50 {
51 /* Checks if the argument type is a pointer */
52 if constexpr(std::is_pointer_v<std::remove_cvref_t<Ty>>)
53 {
54 /* If the pointer is valid forwards the derefenced arg */
55 if (arg != nullptr)
56 return ProcessArg(*arg);
57
58 /* Else prints a message about a nullptr of type Ty */
59 std::ostringstream os{};
60 os << "Nullptr of type: [" << typeid(Ty).name() << ']';
61 return std::move(os).str();
62 }
63
64 /* Custom log function has highest precedence */
65 else if constexpr (TypeHasLogFunction<Ty>)
66 {
67 return arg.LogStr();
68 }
69
70 /* Checks for standard logging (std::ostream& << Ty) */
71 else if constexpr (StandardLogable<Ty>)
72 {
73 std::ostringstream os{};
74 os << arg;
75
76 return std::move(os).str();
77 }
78
79 /* Else returns an error */
80 else
81 {
82 static_assert(DependentFalse<Ty>::value, "Invalid type passed to Util::Internal::ProcessArg(), It is recommended not to use internal functions");
83 }
84 }
85
86 /* Assumes all types passed are valid as it is an internal function */
87 template<typename... Args>
88 std::string ProcessArgs(Args&&... args)
89 {
90 return (ProcessArg(std::forward<Args>(args)) + ... + "");
91 }
92
93 template<typename Ty> concept LogableBase = Internal::StandardLogable<Ty> || Internal::TypeHasLogFunction<Ty>;
94 template<typename Ty> concept Logable = LogableBase<Ty> || (LogableBase<std::remove_cv_t<std::remove_pointer_t<std::remove_cvref_t<Ty>>>>);
95 }
96
97 #endif // DOXYGEN_HIDE
98
138 template<Colour colour = Colour::Default, typename... Args>
139 requires (Internal::Logable<std::remove_cvref_t<Args>> && ...)
140 inline void Print(Args&&... args)
141 {
142 if constexpr (colour != Colour::Default)
144
145 std::string message = Internal::ProcessArgs(std::forward<Args>(args)...);
146 Internal::WriteToConsole(message.c_str());
147
148 if constexpr (colour != Colour::Default)
150 }
151
189 template<typename... Args>
190 requires (Internal::Logable<std::remove_cvref_t<Args>> && ...)
191 inline void Log(Args&&... args)
192 {
193 std::string message = Internal::ProcessArgs("[PB_Util::Log()]: ", std::forward<Args>(args)..., '\n');
194 Internal::WriteToConsole(message.c_str());
195 Internal::WriteToLog(message.c_str());
196 }
197
198 /* These functions documentation are covered by Util::Print and Util::Log so they can be excluded */
199 #ifndef DOXYGEN_HIDE
200
201 template< Colour colour = Colour::Default, typename... Args>
202 requires (Internal::Logable<std::remove_cvref_t<Args>> && ...)
203 inline void PrintLn(Args&&... args)
204 {
205 Print(std::forward<Args>(args)..., '\n');
206 }
207
208 template<typename Ty, std::ranges::range Container_Ty, typename Cargo_Ty = std::ranges::range_value_t<Container_Ty>>
209 requires Internal::Logable<Cargo_Ty>
210 inline void Log(Ty&& name, const Container_Ty& container)
211 {
212 /* Creates a JSON like formatting of the range */
213 std::ostringstream os{};
214 os << "[PB_Util::Log]: \"" << Internal::ProcessArg(name) << "\"\n{\n";
215
216 unsigned counter = 0;
217 for (const auto& item : container)
218 {
219 std::string itemStr = Internal::ProcessArg(item);
220 os << '\t' << std::setw(4) << std::left << counter << " | " << itemStr << '\n';
221 counter++;
222 }
223
224 os << "}\n";
225 std::string message = os.str();
226
227 /* Writes the message to console/log */
228 Internal::WriteToConsole(message.c_str());
229 Internal::WriteToLog(message.c_str());
230 }
231
232 #endif // DOXYGEN_HIDE
233}
Definition Colour.h:10
void Print(Args &&... args)
Prints the message to the console.
Definition Log.h:140
Colour
Representation of each color and its corresponding Win32 console color code. Other operating systems ...
Definition Colour.h:16
@ Default
The default colour of the console.
void Log(Args &&... args)
Logs the message to the log file and console.
Definition Log.h:191
void SetConsoleColor(Colour col)
Sets the console to display text with a certain color.
Mathmatical vector class.
Definition Vec.h:216