ifw-fnd 2.0.1
 
Loading...
Searching...
No Matches
base.hpp
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <array>
11#include <cstdint>
12#include <iostream>
13#include <string>
14#include <thread>
15#include <ctime>
16#include <iomanip>
17#include <variant>
18
19#include <fmt/format.h>
20
21
22// FNDLOC must be defined BEFORE <ifw/fnd/defs/logger.hpp> is included,
23// because the FND* macros in logger.hpp expand FNDLOC. FNDLOC itself
24// references ifw::fnd::IsoTimeNow() and ifw::fnd::ThreadName() — we
25// forward-declare them here so the macro is valid at any call site
26// even though their definitions sit further down in this file.
27namespace ifw::fnd {
28 inline std::string IsoTimeNow(const int8_t precision);
29 inline std::string ThreadName();
30}
31
32// TODO: Replace this with std::source_location + inline functions when C++23 used.
34#define FNDLOC (ifw::fnd::IsoTimeNow(6) + ":" + std::string(__FILE__) + ":" +\
35 std::to_string(__LINE__) + ":" + std::string(__FUNCTION__) + ":" + ifw::fnd::ThreadName())
36
37// TODO: Temporary alias. Wider IFW ecosystem still uses IFWLOC; remove
38// once every downstream module has migrated to FNDLOC.
39#define IFWLOC FNDLOC
40
41// Pull in the logger AFTER FNDLOC is defined, because the FND* macros
42// in logger.hpp expand FNDLOC. The order matters; this is the seam
43// that makes <ifw/fnd/defs/base.hpp> "the single entry point" for
44// consumers who want the macros ready to use.
46
47
48namespace ifw::fnd {
49
60 inline double TimeSecs() {
61 return (std::chrono::duration_cast<std::chrono::nanoseconds>(
62 std::chrono::system_clock::now().time_since_epoch()).count() / 1e9);
63 }
64
71 inline void SleepSecs(const float sleep_time_in_seconds) {
72 FNDTRACE();
73 std::chrono::duration<double> chrono_sleep_time(sleep_time_in_seconds);
74 std::this_thread::sleep_for(chrono_sleep_time);
75 }
76
87 inline std::string IsoTime(const double time_since_epoch, const uint8_t precision) {
88 // Split the time into whole seconds and fractional part
89 std::time_t whole_seconds = static_cast<std::time_t>(time_since_epoch);
90 double fractional_seconds = time_since_epoch - whole_seconds;
91
92 // Get the base time structure (only whole seconds)
93 std::tm* gmt_time = std::gmtime(&whole_seconds);
94 std::ostringstream oss;
95
96 // Format the date and time up to the seconds part
97 oss << std::put_time(gmt_time, "%Y-%m-%dT%H:%M:");
98
99 // Ensure the seconds part is always two digits
100 oss << std::setw(2) << std::setfill('0') << gmt_time->tm_sec;
101
102 // If no precision is required, return the base ISO time
103 if (precision == 0) {
104 return oss.str();
105 }
106
107 // Format the fractional seconds with the specified precision
108 std::string fractional_str = fmt::format("{:.{}}", fractional_seconds, precision);
109
110 // Skip the "0." part from the fractional part and append the rest
111 oss << fractional_str.substr(1);
112
113 return oss.str();
114 }
115
126 inline std::string IsoTimeNow(const int8_t precision) {
127 return IsoTime(TimeSecs(), precision);
128 }
129
131 inline std::string ThreadName() {
132 std::array<char, 32> thread_name{};
133 pthread_getname_np(pthread_self(), thread_name.data(), 32);
134 return std::string(thread_name.data());
135 }
136
137 // template <typename... Ts>
138 // std::string VariantToString(const std::variant<Ts...>& var) {
139 // return std::visit([](const auto& v) { return fmt::format("{}", v); }, var);
140 // }
141
142}
143
144// FNDLOC is defined at the top of this file, before the include of
145// logger.hpp, so the FND* macros can expand it correctly.
146
147// TODO: Future implementation from C++20 (or C++23):
148// #include <source_location>
149
151// inline std::string IfwLoc(const std::source_location& location =
152// std::source_location::current()) {
153// auto thr_name = ifw::fnd::ThreadName();
154// if (thr_name != "") {
155// return std::string(location.file_name()) + ":" +
156// std::to_string(location.line()) + ":" +
157// std::string(location.function_name()) + ":" +
158// thr_name;
159// } else {
160// return std::string(location.file_name()) + ":" +
161// std::to_string(location.line()) + ":" +
162// std::string(location.function_name());
163// }
164// }
165
166namespace ifw::fnd {
167
168 // template <typename... Ts>
169 // std::string VariantToString(const std::variant<Ts...>& var) {
170 // return std::visit([](const auto& v) { return fmt::format("{}", v); }, var);
171 // }
172
173 template <typename... Ts>
174 std::string VariantToString(const std::variant<Ts...>& var) {
175 try {
176 return std::visit([](const auto& v) { return fmt::format("{}", v); }, var);
177 } catch (...) {
178 return fmt::format("{}: Invalid value", FNDLOC);
179 }
180 }
181
182}
#define FNDLOC
Macro generating a location identifier: "<iso-time>:<file>:<line>:<function>:<thread>".
Definition base.hpp:34
ifw-fnd logging abstraction.
#define FNDTRACE(...)
Definition logger.hpp:290
This source file contains definitions of the types and constants to handle data types.
Definition defs.cpp:28
std::string VariantToString(const std::variant< Ts... > &var)
Definition base.hpp:174
std::string ThreadName()
Return name of current thread.
Definition base.hpp:131
std::string IsoTimeNow(const int8_t precision)
Definition base.hpp:126
std::string IsoTime(const double time_since_epoch, const uint8_t precision)
Definition base.hpp:87
double TimeSecs()
Definition base.hpp:60
void SleepSecs(const float sleep_time_in_seconds)
Definition base.hpp:71