27#ifndef EASYNAV__TYPES__NAVSTATE_HPP_
28#define EASYNAV__TYPES__NAVSTATE_HPP_
31#include <unordered_map>
53 char * p = abi::__cxa_demangle(name,
nullptr,
nullptr, &status);
54 std::string out = (status == 0 && p) ? p : name;
63inline std::string
stacktrace(std::size_t skip = 1, std::size_t max_frames = 64)
66 const int n = backtrace(buf,
static_cast<int>(std::min<std::size_t>(max_frames, 128)));
67 char ** syms = backtrace_symbols(buf, n);
68 std::ostringstream oss;
69 for (
int i =
static_cast<int>(skip); i < n; ++i) {
70 oss <<
"#" << (i -
static_cast<int>(skip)) <<
" " << syms[i] <<
"\n";
108 void set(
const std::string & key,
const T & value)
110 std::lock_guard<std::mutex> lock(mutex_);
111 auto it = values_.find(key);
113 if (it == values_.end()) {
114 values_[key] = std::make_shared<T>(value);
115 types_[key] =
typeid(T).hash_code();
117 if (types_[key] !=
typeid(T).hash_code()) {
118 std::ostringstream oss;
119 oss <<
"Type mismatch in set(\"" << key <<
"\")\n"
120 <<
" expected(hash): " << types_[key] <<
"\n"
121 <<
" provided : " <<
demangle(
typeid(T).name()) <<
"\n"
123 throw std::runtime_error(oss.str());
126 auto ptr = std::static_pointer_cast<T>(it->second);
141 void set(
const std::string & key,
const std::shared_ptr<T> value_ptr)
143 std::lock_guard<std::mutex> lock(mutex_);
144 auto it = values_.find(key);
146 if (it == values_.end()) {
147 values_[key] = std::shared_ptr<T>(value_ptr);
148 types_[key] =
typeid(T).hash_code();
150 if (types_[key] !=
typeid(T).hash_code()) {
151 std::ostringstream oss;
152 oss <<
"Type mismatch in set(\"" << key <<
"\")\n"
153 <<
" expected(hash): " << types_[key] <<
"\n"
154 <<
" provided : " <<
demangle(
typeid(T).name()) <<
"\n"
156 throw std::runtime_error(oss.str());
159 auto ptr = std::static_pointer_cast<T>(it->second);
160 ptr = std::shared_ptr<T>(value_ptr);
173 const T &
get(
const std::string & key)
const
175 std::lock_guard<std::mutex> lock(mutex_);
176 auto it = values_.find(key);
178 if (it == values_.end()) {
179 throw std::runtime_error(
"Key not found in get: " + key);
182 if (types_.at(key) !=
typeid(T).hash_code()) {
183 throw std::runtime_error(
"Type mismatch in get for key: " + key);
186 auto ptr = std::static_pointer_cast<T>(it->second);
199 const std::shared_ptr<T>
get_ptr(
const std::string & key)
const
201 std::lock_guard<std::mutex> lock(mutex_);
202 auto it = values_.find(key);
204 if (it == values_.end()) {
205 throw std::runtime_error(
"Key not found in get: " + key);
208 if (types_.at(key) !=
typeid(T).hash_code()) {
209 throw std::runtime_error(
"Type mismatch in get for key: " + key);
212 return std::static_pointer_cast<T>(it->second);
218 bool has(
const std::string & key)
const
220 return values_.find(key) != values_.end();
227 using AnyPrinter = std::function<std::string(std::shared_ptr<void>)>;
236 auto wrapper = [printer](std::shared_ptr<void> base_ptr) -> std::string {
237 auto typed_ptr = std::static_pointer_cast<T>(base_ptr);
238 return printer(*typed_ptr);
240 type_printers_[
typeid(T).hash_code()] = wrapper;
250 std::stringstream ss;
251 for (
const auto & kv : values_) {
252 ss << kv.first <<
" = ";
253 auto ptr = kv.second;
255 auto type_it = types_.find(kv.first);
256 if (type_it != types_.end()) {
257 auto printer_it = type_printers_.find(type_it->second);
258 if (printer_it != type_printers_.end()) {
259 ss <<
"[" << ptr.get() <<
"] : " << printer_it->second(ptr);
261 ss <<
"[" << ptr.get() <<
"] : " << type_it->second <<
"]";
264 ss <<
"[" << ptr.get() <<
"] : unknown]";
279 int size = backtrace(array, 50);
280 char **strings = backtrace_symbols(array, size);
281 std::cerr <<
"\nStack trace:\n";
282 for (
int i = 0; i < size; ++i) {
283 std::cerr << strings[i] << std::endl;
285 std::cerr << std::endl;
303 mutable std::mutex mutex_;
306 mutable std::unordered_map<std::string, std::shared_ptr<void>> values_;
309 mutable std::unordered_map<std::string, size_t> types_;
312 static inline std::unordered_map<size_t, AnyPrinter> type_printers_;
const T & get(const std::string &key) const
Retrieves a const reference to the stored value of type T for key.
Definition NavState.hpp:173
const std::shared_ptr< T > get_ptr(const std::string &key) const
Retrieves the shared_ptr to the stored value of type T for key.
Definition NavState.hpp:199
std::function< std::string(std::shared_ptr< void >)> AnyPrinter
Type alias for a generic printer functor used by debug_string().
Definition NavState.hpp:227
void set(const std::string &key, const std::shared_ptr< T > value_ptr)
Stores a value of type T associated with key (by shared pointer).
Definition NavState.hpp:141
static void print_stacktrace()
Prints the current C++ stack trace to std::cerr.
Definition NavState.hpp:276
static void register_basic_printers()
Registers default printers for common scalar types.
Definition NavState.hpp:292
void set(const std::string &key, const T &value)
Stores a value of type T associated with key (by copy).
Definition NavState.hpp:108
static void register_printer(std::function< std::string(const T &)> printer)
Registers a pretty-printer for type T used by debug_string().
Definition NavState.hpp:234
NavState()
Constructs an empty NavState and registers basic type printers.
Definition NavState.hpp:90
virtual ~NavState()=default
Destructor.
bool has(const std::string &key) const
Checks whether key exists in the state.
Definition NavState.hpp:218
std::string debug_string() const
Generates a human-readable dump of all stored keys and values.
Definition NavState.hpp:248
Definition CircularBuffer.hpp:28
std::string stacktrace(std::size_t skip=1, std::size_t max_frames=64)
Captures a C/C++ stack trace as a string.
Definition NavState.hpp:63
std::string demangle(const char *name)
Demangles a C++ RTTI type name if possible.
Definition NavState.hpp:50