apps/argos/EnumInspector.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // <EnumInspector.hpp> -*- C++ -*- | ||
| 2 | |||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "simdb/sqlite/DatabaseManager.hpp" | ||
| 6 | #include "simdb/utils/Demangle.hpp" | ||
| 7 | #include "simdb/utils/TypeTraits.hpp" | ||
| 8 | |||
| 9 | #include <memory> | ||
| 10 | #include <optional> | ||
| 11 | #include <unordered_map> | ||
| 12 | #include <vector> | ||
| 13 | |||
| 14 | namespace simdb::argos { | ||
| 15 | |||
| 16 | //! This class allows us to track collected enum values (int) and their corresponding | ||
| 17 | //! stringified values (operator<<) and store them in the database for the Argos UI | ||
| 18 | //! to use. Note that enums without operator<< are just shown in Argos as their int | ||
| 19 | //! values. | ||
| 20 | class EnumInspector | ||
| 21 | { | ||
| 22 | public: | ||
| 23 | 3 | template <typename E> std::enable_if_t<type_traits::has_ostream_operator_v<E>, void> inspect(E val) | |
| 24 | { | ||
| 25 | 4 | static EnumMap<E>* map = [this] { | |
| 26 | 1 | auto& slot = enum_maps_[simdb::demangle_type<E>()]; | |
| 27 | 1 | if (!slot) | |
| 28 | { | ||
| 29 | 1 | slot = std::make_unique<EnumMap<E>>(); | |
| 30 | } | ||
| 31 | 1 | return static_cast<EnumMap<E>*>(slot.get()); | |
| 32 | 1 | }(); | |
| 33 | 3 | map->inspect(val); | |
| 34 | 3 | } | |
| 35 | |||
| 36 | 3 | template <typename E> std::enable_if_t<!type_traits::has_ostream_operator_v<E>, void> inspect(E) {} | |
| 37 | |||
| 38 | 5 | void serializeEnumMaps(DatabaseManager* db_mgr) | |
| 39 | { | ||
| 40 | 6 | for (auto& [_, map] : enum_maps_) | |
| 41 | { | ||
| 42 | 1 | map->dumpEnumMap(db_mgr); | |
| 43 | } | ||
| 44 | 5 | } | |
| 45 | |||
| 46 | private: | ||
| 47 | class EnumMapBase | ||
| 48 | { | ||
| 49 | public: | ||
| 50 | 1 | virtual ~EnumMapBase() = default; | |
| 51 | virtual void dumpEnumMap(simdb::DatabaseManager* db_mgr) const = 0; | ||
| 52 | }; | ||
| 53 | |||
| 54 | template <typename E, typename = void> class EnumMap : public EnumMapBase | ||
| 55 | { | ||
| 56 | public: | ||
| 57 | void inspect(E) {} | ||
| 58 | void dumpEnumMap(simdb::DatabaseManager*) const override final {} | ||
| 59 | }; | ||
| 60 | |||
| 61 | template <typename E> | ||
| 62 | class EnumMap<E, std::enable_if_t<type_traits::has_ostream_operator_v<E>>> : public EnumMapBase | ||
| 63 | { | ||
| 64 | public: | ||
| 65 | 3 | void inspect(E val) | |
| 66 | { | ||
| 67 | 3 | if (last_seen_ && *last_seen_ == val) | |
| 68 | { | ||
| 69 | ✗ | return; | |
| 70 | } | ||
| 71 | |||
| 72 | 6 | for (E seen : all_seen_) | |
| 73 | { | ||
| 74 | 3 | if (seen == val) | |
| 75 | { | ||
| 76 | ✗ | last_seen_ = val; | |
| 77 | ✗ | return; | |
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | 3 | all_seen_.push_back(val); | |
| 82 | 3 | last_seen_ = val; | |
| 83 | } | ||
| 84 | |||
| 85 | 1 | void dumpEnumMap(DatabaseManager* db_mgr) const override final | |
| 86 | { | ||
| 87 | using underlying_t = std::underlying_type_t<E>; | ||
| 88 | 1 | const auto itype = demangle_type<underlying_t>(); | |
| 89 | 1 | const auto enum_name = demangle_type<E>(); | |
| 90 | 1 | const auto enum_id = db_mgr->INSERT(SQL_TABLE("CollectedEnums"), SQL_VALUES(enum_name, itype))->getId(); | |
| 91 | |||
| 92 | 1 | auto inserter = db_mgr->prepareINSERT(SQL_TABLE("EnumMembers")); | |
| 93 | 4 | for (auto e : all_seen_) | |
| 94 | { | ||
| 95 | 3 | std::ostringstream oss; | |
| 96 | 3 | oss << e; | |
| 97 | |||
| 98 | 3 | const auto member_name = oss.str(); | |
| 99 | 3 | const auto raw_enum_val = static_cast<underlying_t>(e); | |
| 100 | 3 | const auto raw_enum_str = std::to_string(raw_enum_val); | |
| 101 | |||
| 102 | 3 | inserter->createRecordWithColValues(enum_id, member_name, raw_enum_str); | |
| 103 | } | ||
| 104 | 1 | } | |
| 105 | |||
| 106 | private: | ||
| 107 | std::vector<E> all_seen_; | ||
| 108 | std::optional<E> last_seen_; | ||
| 109 | }; | ||
| 110 | |||
| 111 | std::unordered_map<std::string, std::unique_ptr<EnumMapBase>> enum_maps_; | ||
| 112 | }; | ||
| 113 | |||
| 114 | } // namespace simdb::argos | ||
| 115 |