LogIt++
Loading...
Searching...
No Matches
VariableValue.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _LOGIT_VARIABLE_VALUE_HPP_INCLUDED
3#define _LOGIT_VARIABLE_VALUE_HPP_INCLUDED
6
7#include <time_shield_cpp/time_shield.hpp>
8#include <string>
9#include <iostream>
10#include <cstdint>
11#include <type_traits>
12#include <exception>
13#include <iomanip> // std::put_time
14#include <chrono>
15#include <sstream>
16#include <memory>
17#if __cplusplus >= 201703L
18#include <filesystem>
19#include <optional>
20#include <variant>
21#endif
22
23namespace logit {
24
29 template <typename EnumType>
30 std::string enum_to_string(EnumType value) {
31 // Convert enum to underlying integral value and then to string.
32 typedef typename std::underlying_type<EnumType>::type UnderlyingType;
33 return std::to_string(static_cast<UnderlyingType>(value));
34 }
35
39 std::string name;
41
71
72 union {
73 int8_t int8_value;
74 uint8_t uint8_value;
75 int16_t int16_value;
76 uint16_t uint16_value;
77 int32_t int32_value;
78 uint32_t uint32_value;
79 int64_t int64_value;
80 uint64_t uint64_value;
85 long double long_double_value;
87
88 std::string string_value;
89 std::error_code error_code_value;
90
91 // Constructors for each type.
92 template <typename T>
93 VariableValue(const std::string& name, T value,
94 typename std::enable_if<std::is_same<T, bool>::value>::type* = nullptr)
96 pod_value.bool_value = value;
97 }
98
99 template <typename T>
100 VariableValue(const std::string& name, T value,
101 typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr)
103 pod_value.char_value = value;
104 }
105
106 explicit VariableValue(const std::string& name, const std::string& value)
108 }
109
110 explicit VariableValue(const std::string& name, const char* value) :
111 VariableValue(name, std::string(value)) {}
112
113 template <typename T>
114 VariableValue(const std::string& name, const T& value,
115 typename std::enable_if<std::is_base_of<std::exception, T>::value>::type* = nullptr)
117 }
118
119 explicit VariableValue(const std::string& name, const std::error_code& ec)
121 }
122
123 template <typename T>
124 VariableValue(const std::string& name, T value,
125 typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr)
127 if (std::is_same<T, float>::value) {
129 pod_value.float_value = value;
130 } else if (std::is_same<T, double>::value) {
132 pod_value.double_value = value;
133 } else if (std::is_same<T, long double>::value) {
135 pod_value.long_double_value = value;
136 }
137 }
138
139 template <typename T>
140 VariableValue(const std::string& name, T value,
141 typename std::enable_if<std::is_integral<T>::value>::type* = nullptr)
143 if (std::is_signed<T>::value) {
144 if (sizeof(T) <= sizeof(int8_t)) {
146 pod_value.int8_value = static_cast<int8_t>(value);
147 } else if (sizeof(T) <= sizeof(int16_t)) {
149 pod_value.int16_value = static_cast<int16_t>(value);
150 } else if (sizeof(T) <= sizeof(int32_t)) {
152 pod_value.int32_value = static_cast<int32_t>(value);
153 } else {
155 pod_value.int64_value = static_cast<int64_t>(value);
156 }
157 } else {
158 if (sizeof(T) <= sizeof(uint8_t)) {
160 pod_value.uint8_value = static_cast<uint8_t>(value);
161 } else if (sizeof(T) <= sizeof(uint16_t)) {
163 pod_value.uint16_value = static_cast<uint16_t>(value);
164 } else if (sizeof(T) <= sizeof(uint32_t)) {
166 pod_value.uint32_value = static_cast<uint32_t>(value);
167 } else {
169 pod_value.uint64_value = static_cast<uint64_t>(value);
170 }
171 }
172 }
173
178 template <typename EnumType>
179 VariableValue(const std::string& name, EnumType value,
180 typename std::enable_if<std::is_enum<EnumType>::value>::type* = 0)
183 }
184
185 template <typename Rep, typename Period>
186 VariableValue(const std::string& name, const std::chrono::duration<Rep, Period>& duration)
188 string_value = std::to_string(duration.count()) + " " + duration_units<Period>();
189 }
190
191 template <typename Clock, typename Duration>
192 VariableValue(const std::string& name, const std::chrono::time_point<Clock, Duration>& time_point)
194 auto ts_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_point.time_since_epoch());
195 string_value = time_shield::to_human_readable_ms(ts_ms.count());
196 }
197
198# if __cplusplus >= 201703L
199
200 explicit VariableValue(const std::string& name, const std::filesystem::path& path)
202 }
203
204 template <typename... Ts>
205 explicit VariableValue(const std::string& name, const std::variant<Ts...>& variant)
207 string_value = std::visit([](const auto& value) -> std::string {
208 if constexpr (std::is_arithmetic_v<decltype(value)>) {
209 return std::to_string(value);
210 } else if constexpr (std::is_same_v<decltype(value), std::string>) {
211 return value;
212 } else {
213 std::ostringstream oss;
214 oss << value;
215 return oss.str();
216 }
217 }, variant);
218 }
219
220 template <typename T>
221 explicit VariableValue(const std::string& name, const std::optional<T>& optional)
223 if (optional) {
224 if constexpr (std::is_arithmetic_v<T>) {
225 string_value = std::to_string(*optional);
226 } else if constexpr (std::is_same_v<T, std::string>) {
227 string_value = *optional;
228 } else {
229 std::ostringstream oss;
230 oss << *optional;
231 string_value = oss.str();
232 }
233 } else {
234 string_value = "nullopt";
235 }
236 }
237
238# endif
239
240 explicit VariableValue(const std::string& name, void* ptr)
242 std::ostringstream oss;
243 oss << ptr;
244 string_value = oss.str();
245 }
246
247 template <typename T>
248 explicit VariableValue(const std::string& name, const std::shared_ptr<T>& ptr)
250 std::ostringstream oss;
251 if (ptr) oss << "shared_ptr@" << ptr.get();
252 else oss << "nullptr";
253 string_value = oss.str();
254 }
255
256 template <typename T>
257 explicit VariableValue(const std::string& name, const std::unique_ptr<T>& ptr)
259 std::ostringstream oss;
260 if (ptr) oss << "unique_ptr@" << ptr.get();
261 else oss << "nullptr";
262 string_value = oss.str();
263 }
264
267 : name(other.name), is_literal(other.is_literal), type(other.type),
270 if (is_pod_type(type)) {
271 pod_value = other.pod_value;
272 }
273 }
274
277 if (this == &other) return *this; // Self-assignment check.
278
279 name = other.name;
280 is_literal = other.is_literal;
281 type = other.type;
284
285 if (is_pod_type(type)) {
286 pod_value = other.pod_value;
287 }
288
289 return *this;
290 }
291
293 ~VariableValue() = default;
294
297 std::string to_string() const {
298 switch (type) {
299 case ValueType::INT8_VAL: return std::to_string(pod_value.int8_value);
300 case ValueType::UINT8_VAL: return std::to_string(pod_value.uint8_value);
301 case ValueType::INT16_VAL: return std::to_string(pod_value.int16_value);
302 case ValueType::UINT16_VAL: return std::to_string(pod_value.uint16_value);
303 case ValueType::INT32_VAL: return std::to_string(pod_value.int32_value);
304 case ValueType::UINT32_VAL: return std::to_string(pod_value.uint32_value);
305 case ValueType::INT64_VAL: return std::to_string(pod_value.int64_value);
306 case ValueType::UINT64_VAL: return std::to_string(pod_value.uint64_value);
307 case ValueType::BOOL_VAL: return pod_value.bool_value ? "true" : "false";
308 case ValueType::CHAR_VAL: return std::string(1, pod_value.char_value);
309 case ValueType::FLOAT_VAL: return std::to_string(pod_value.float_value);
310 case ValueType::DOUBLE_VAL: return std::to_string(pod_value.double_value);
311 case ValueType::LONG_DOUBLE_VAL: return std::to_string(static_cast<double>(pod_value.long_double_value));
322 return string_value;
324 return error_code_value.message() + " (" + std::to_string(error_code_value.value()) + ")";
325 default: break;
326 }
327 return "unknown";
328 }
329
333 std::string to_string(const char* fmt) const {
334 switch (type) {
335 case ValueType::INT8_VAL: return logit::format(fmt, pod_value.int8_value);
336 case ValueType::UINT8_VAL: return format(fmt, pod_value.uint8_value);
337 case ValueType::INT16_VAL: return format(fmt, pod_value.int16_value);
338 case ValueType::UINT16_VAL: return format(fmt, pod_value.uint16_value);
339 case ValueType::INT32_VAL: return format(fmt, pod_value.int32_value);
340 case ValueType::UINT32_VAL: return format(fmt, pod_value.uint32_value);
341 case ValueType::INT64_VAL: return format(fmt, pod_value.int64_value);
342 case ValueType::UINT64_VAL: return format(fmt, pod_value.uint64_value);
343 case ValueType::BOOL_VAL: return format(fmt, pod_value.bool_value);
344 case ValueType::CHAR_VAL: return format(fmt, pod_value.char_value);
345 case ValueType::FLOAT_VAL: return format(fmt, pod_value.float_value);
346 case ValueType::DOUBLE_VAL: return format(fmt, pod_value.double_value);
347 case ValueType::LONG_DOUBLE_VAL: return format(fmt, static_cast<double>(pod_value.long_double_value));
358 return format(fmt, string_value.c_str());
360 return format(fmt, error_code_value.message().c_str(), error_code_value.value());
361 default: break;
362 }
363 return "unknown";
364 }
365
366 private:
370 static bool is_valid_literal_name(const std::string& name) {
371 if (name.empty()) return false;
372 return !std::isdigit(static_cast<unsigned char>(name[0]));
373 }
374
379 switch (type) {
393 return true;
394 default:
395 return false;
396 }
397 }
398
402 template <typename Period>
403 static std::string duration_units() {
404 if (std::is_same<Period, std::ratio<1>>::value) {
405 return "s"; // seconds
406 } else if (std::is_same<Period, std::milli>::value) {
407 return "ms"; // milliseconds
408 } else if (std::is_same<Period, std::micro>::value) {
409 return "us"; // microseconds
410 } else if (std::is_same<Period, std::nano>::value) {
411 return "ns"; // nanoseconds
412 } else if (std::is_same<Period, std::ratio<60>>::value) {
413 return "min"; // minutes
414 } else if (std::is_same<Period, std::ratio<3600>>::value) {
415 return "h"; // hours
416 } else {
417 return "custom"; // Custom units
418 }
419 }
420 }; // VariableValue
421
422} // namespace logit
423
424#endif // _LOGIT_VARIABLE_VALUE_HPP_INCLUDED
The primary namespace for the LogIt++ library.
std::string format(const char *fmt,...)
Formats a string according to the specified format.
Definition format.hpp:27
std::string enum_to_string(EnumType value)
Helper function to convert an enumeration to a string.
VariableValue(const std::string &name, T value, typename std::enable_if< std::is_integral< T >::value >::type *=nullptr)
VariableValue(const std::string &name, const std::chrono::duration< Rep, Period > &duration)
long double long_double_value
std::error_code error_code_value
Variable to store std::error_code.
std::string name
Variable name.
VariableValue & operator=(const VariableValue &other)
Assignment operator.
VariableValue(const std::string &name, const T &value, typename std::enable_if< std::is_base_of< std::exception, T >::value >::type *=nullptr)
static std::string duration_units()
Helper function to get the unit of the duration.
VariableValue(const std::string &name, const std::chrono::time_point< Clock, Duration > &time_point)
VariableValue(const std::string &name, T value, typename std::enable_if< std::is_same< T, bool >::value >::type *=nullptr)
~VariableValue()=default
Destructor.
bool is_literal
Flag indicating if the variable is a literal.
std::string to_string() const
Method to get the value as a string.
enum logit::VariableValue::ValueType type
Specifies the type of the stored value in the VariableValue structure.
union logit::VariableValue::@031270277233142267156311255133022172106116140056 pod_value
Union to store POD types.
std::string string_value
Variable to store string, exception messages, and enums.
VariableValue(const std::string &name, const std::unique_ptr< T > &ptr)
VariableValue(const std::string &name, const std::string &value)
VariableValue(const VariableValue &other)
Copy constructor.
VariableValue(const std::string &name, const std::shared_ptr< T > &ptr)
ValueType
Enumeration of possible value types for VariableValue.
@ FLOAT_VAL
Value of type float (single-precision floating point).
@ ENUM_VAL
Value of any enumeration type (converted to string or integral value).
@ INT16_VAL
Value of type int16_t (signed 16-bit integer).
@ CHAR_VAL
Value of type char (single character).
@ OPTIONAL_VAL
Value of type std::optional (optional value holder).
@ STRING_VAL
Value of type std::string (dynamic-length string).
@ POINTER_VAL
Value of type void* (raw pointer).
@ UINT64_VAL
Value of type uint64_t (unsigned 64-bit integer).
@ UINT32_VAL
Value of type uint32_t (unsigned 32-bit integer).
@ VARIANT_VAL
Value of type std::variant (type-safe union).
@ SMART_POINTER_VAL
Value of type std::shared_ptr or std::unique_ptr (smart pointers).
@ INT64_VAL
Value of type int64_t (signed 64-bit integer).
@ PATH_VAL
Value of type std::filesystem::path (filesystem path).
@ DURATION_VAL
Value of type std::chrono::duration (time duration).
@ DOUBLE_VAL
Value of type double (double-precision floating point).
@ INT32_VAL
Value of type int32_t (signed 32-bit integer).
@ UINT8_VAL
Value of type uint8_t (unsigned 8-bit integer).
@ LONG_DOUBLE_VAL
Value of type long double (extended-precision floating point).
@ TIME_POINT_VAL
Value of type std::chrono::time_point (specific point in time).
@ INT8_VAL
Value of type int8_t (signed 8-bit integer).
@ UINT16_VAL
Value of type uint16_t (unsigned 16-bit integer).
@ UNKNOWN_VAL
Unknown or unsupported value type.
@ EXCEPTION_VAL
Value representing an exception (derived from std::exception).
@ ERROR_CODE_VAL
Value of type std::error_code (system error code).
VariableValue(const std::string &name, EnumType value, typename std::enable_if< std::is_enum< EnumType >::value >::type *=0)
Constructor for enumerations.
static bool is_valid_literal_name(const std::string &name)
Helper function to check if a name is a valid literal.
VariableValue(const std::string &name, const std::error_code &ec)
static bool is_pod_type(ValueType type)
Helper function to determine if a ValueType represents a POD type.
VariableValue(const std::string &name, T value, typename std::enable_if< std::is_same< T, char >::value >::type *=nullptr)
VariableValue(const std::string &name, const std::filesystem::path &path)
VariableValue(const std::string &name, const std::variant< Ts... > &variant)
std::string to_string(const char *fmt) const
Method to get the value as a formatted string.
VariableValue(const std::string &name, T value, typename std::enable_if< std::is_floating_point< T >::value >::type *=nullptr)
VariableValue(const std::string &name, const char *value)
VariableValue(const std::string &name, const std::optional< T > &optional)
VariableValue(const std::string &name, void *ptr)