22#ifndef EASYNAV__TYPES__NAVSTATE_HPP_
23#define EASYNAV__TYPES__NAVSTATE_HPP_
26#include <unordered_map>
48 char * p = abi::__cxa_demangle(name,
nullptr,
nullptr, &status);
49 std::string out = (status == 0 && p) ? p : name;
58inline std::string
stacktrace(std::size_t skip = 1, std::size_t max_frames = 64)
61 const int n = backtrace(buf,
static_cast<int>(std::min<std::size_t>(max_frames, 128)));
62 char ** syms = backtrace_symbols(buf, n);
63 std::ostringstream oss;
64 for (
int i =
static_cast<int>(skip); i < n; ++i) {
65 oss <<
"#" << (i -
static_cast<int>(skip)) <<
" " << syms[i] <<
"\n";
103 void set(
const std::string & key,
const T & value)
105 std::lock_guard<std::mutex> lock(mutex_);
106 auto it = values_.find(key);
108 if (it == values_.end()) {
109 values_[key] = std::make_shared<T>(value);
110 types_[key] =
typeid(T).hash_code();
112 if (types_[key] !=
typeid(T).hash_code()) {
113 std::ostringstream oss;
114 oss <<
"Type mismatch in set(\"" << key <<
"\")\n"
115 <<
" expected(hash): " << types_[key] <<
"\n"
116 <<
" provided : " <<
demangle(
typeid(T).name()) <<
"\n"
118 throw std::runtime_error(oss.str());
121 auto ptr = std::static_pointer_cast<T>(it->second);
136 void set(
const std::string & key,
const std::shared_ptr<T> value_ptr)
138 std::lock_guard<std::mutex> lock(mutex_);
139 auto it = values_.find(key);
141 if (it == values_.end()) {
142 values_[key] = std::shared_ptr<T>(value_ptr);
143 types_[key] =
typeid(T).hash_code();
145 if (types_[key] !=
typeid(T).hash_code()) {
146 std::ostringstream oss;
147 oss <<
"Type mismatch in set(\"" << key <<
"\")\n"
148 <<
" expected(hash): " << types_[key] <<
"\n"
149 <<
" provided : " <<
demangle(
typeid(T).name()) <<
"\n"
151 throw std::runtime_error(oss.str());
154 auto ptr = std::static_pointer_cast<T>(it->second);
155 ptr = std::shared_ptr<T>(value_ptr);
168 const T &
get(
const std::string & key)
const
170 std::lock_guard<std::mutex> lock(mutex_);
171 auto it = values_.find(key);
173 if (it == values_.end()) {
174 throw std::runtime_error(
"Key not found in get: " + key);
177 if (types_.at(key) !=
typeid(T).hash_code()) {
178 throw std::runtime_error(
"Type mismatch in get for key: " + key);
181 auto ptr = std::static_pointer_cast<T>(it->second);
194 const std::shared_ptr<T>
get_ptr(
const std::string & key)
const
196 std::lock_guard<std::mutex> lock(mutex_);
197 auto it = values_.find(key);
199 if (it == values_.end()) {
200 throw std::runtime_error(
"Key not found in get: " + key);
203 if (types_.at(key) !=
typeid(T).hash_code()) {
204 throw std::runtime_error(
"Type mismatch in get for key: " + key);
207 return std::static_pointer_cast<T>(it->second);
213 bool has(
const std::string & key)
const
215 return values_.find(key) != values_.end();
222 using AnyPrinter = std::function<std::string(std::shared_ptr<void>)>;
231 auto wrapper = [printer](std::shared_ptr<void> base_ptr) -> std::string {
232 auto typed_ptr = std::static_pointer_cast<T>(base_ptr);
233 return printer(*typed_ptr);
235 type_printers_[
typeid(T).hash_code()] = wrapper;
245 std::stringstream ss;
246 for (
const auto & kv : values_) {
247 ss << kv.first <<
" = ";
248 auto ptr = kv.second;
250 auto type_it = types_.find(kv.first);
251 if (type_it != types_.end()) {
252 auto printer_it = type_printers_.find(type_it->second);
253 if (printer_it != type_printers_.end()) {
254 ss <<
"[" << ptr.get() <<
"] : " << printer_it->second(ptr);
256 ss <<
"[" << ptr.get() <<
"] : " << type_it->second <<
"]";
259 ss <<
"[" << ptr.get() <<
"] : unknown]";
274 int size = backtrace(array, 50);
275 char **strings = backtrace_symbols(array, size);
276 std::cerr <<
"\nStack trace:\n";
277 for (
int i = 0; i < size; ++i) {
278 std::cerr << strings[i] << std::endl;
280 std::cerr << std::endl;
298 mutable std::mutex mutex_;
301 mutable std::unordered_map<std::string, std::shared_ptr<void>> values_;
304 mutable std::unordered_map<std::string, size_t> types_;
307 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:168
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:194
std::function< std::string(std::shared_ptr< void >)> AnyPrinter
Type alias for a generic printer functor used by debug_string().
Definition NavState.hpp:222
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:136
static void print_stacktrace()
Prints the current C++ stack trace to std::cerr.
Definition NavState.hpp:271
static void register_basic_printers()
Registers default printers for common scalar types.
Definition NavState.hpp:287
void set(const std::string &key, const T &value)
Stores a value of type T associated with key (by copy).
Definition NavState.hpp:103
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:229
NavState()
Constructs an empty NavState and registers basic type printers.
Definition NavState.hpp:85
virtual ~NavState()=default
Destructor.
bool has(const std::string &key) const
Checks whether key exists in the state.
Definition NavState.hpp:213
std::string debug_string() const
Generates a human-readable dump of all stored keys and values.
Definition NavState.hpp:243
Definition CircularBuffer.hpp:23
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:58
std::string demangle(const char *name)
Demangles a C++ RTTI type name if possible.
Definition NavState.hpp:45